我有一个名为 Foo 的模型,它有一个名为 MyProp 的属性 Bar 。 当我将此模型发布到控制器时,我希望模型绑定器验证 MyProp ,因为它具有Required属性,就像对字符串一样。我需要它在Bar类中自包含或作为单独的类。我曾尝试在 Bar 类上使用IValidatableObject,但似乎无法检查 Foo 类是否具有必需属性 MyProp ?所以现在我没有选择,需要一些帮助。以下是我的问题的一些示例代码。
public class Foo {
[Required]
public Bar MyProp { get; set; }
}
public class Bar {
[ScaffoldColumn(false)]
public int Id { get; set; }
public string Name { get; set; }
}
答案 0 :(得分:2)
这是我的问题的一个解决方案,我可以使用内置的必需属性,仍然可以获得自定义行为。这只是概念代码的一些证据。
模特:
public class Page : IPageModel {
[Display(Name = "Page", Prompt = "Specify page name...")]
[Required(ErrorMessage = "You must specify a page name")]
public PageReference PageReference { get; set; }
}
模型活页夹:
public class PageModelBinder : DefaultModelBinder {
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(bindingContext.ModelType)) {
var attributes = property.Attributes;
if (attributes.Count == 0) continue;
foreach (var attribute in attributes) {
if (attribute.GetType().BaseType == typeof(ValidationAttribute) && property.PropertyType == typeof(PageReference)) {
var pageReference = bindingContext.ModelType.GetProperty(property.Name).GetValue(bindingContext.Model, null) as PageReference;
Type attrType = attribute.GetType();
if (attrType == typeof (RequiredAttribute) && string.IsNullOrEmpty(pageReference.Name)) {
bindingContext.ModelState.AddModelError(property.Name,
((RequiredAttribute) attribute).ErrorMessage);
}
}
}
}
base.OnModelUpdated(controllerContext, bindingContext);
}
}
模型绑定提供者:
public class InheritanceAwareModelBinderProvider : Dictionary<Type, IModelBinder>, IModelBinderProvider {
public IModelBinder GetBinder(Type modelType) {
var binders = from binder in this
where binder.Key.IsAssignableFrom(modelType)
select binder.Value;
return binders.FirstOrDefault();
}
}
并持续global.asax注册:
var binderProvider = new InheritanceAwareModelBinderProvider {
{
typeof (IPageModel), new PageModelBinder() }
};
ModelBinderProviders.BinderProviders.Add(binderProvider);
那你怎么看待这个解决方案呢?
答案 1 :(得分:0)
问题是没有名为MyProp
的html字段,并且MVC不会对此属性进行任何验证。
实现目标的一种方法是摆脱Bar
并在Bar's
中创建Foo
属性。您可以使用 AutoMapper 将管道代码最小化。
另一种解决方案是编写一个自定义验证属性,该属性根据null
值进行验证,并使用它而不是Required
属性。
答案 2 :(得分:0)
尝试自定义[Required]
ValidationAttribute
public class Foo {
[RequiredBar]
public Bar MyProp { get; set; }
}
public class Bar {
[ScaffoldColumn(false)]
public int Id { get; set; }
public string Name { get; set; }
}
public class RequiredBar : ValidationAttribute {
public override bool IsValid(object value)
{
Bar bar = (Bar)value;
// validate. For example
if (bar == null)
{
return false;
}
return bar.Name != null;
}
}
只需将Required
放在Bar的相应必需属性上,例如
public class Foo {
//[RequiredBar]
public Bar MyProp { get; set; }
}
public class Bar {
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}