MVC 3模型validation问题 – 监督或设计
我遇到了一个场景,我需要知道当前在自定义ValidationAttribute
validation了哪个属性 。 我认为这很容易在MVC 3中,因为ValidationContext
被传递到IsValid
方法。
没有详细说明,这是基本的想法:
protected override ValidationResult IsValid(Object value, ValidationContext validationContext) { if (ShouldICareAboutYou(validationContext.MemberName)) { //Do some stuff } //Return the results }
这似乎是完美的解决方案,事实上,当使用Validator.TryValidateObject
对我的自定义ValidationAttribute进行unit testing时,一切都运行得非常好!
然而…
在我的控制器中调用TryUpdateModel
或TryValidateModel
,validation会运行,但ValidationContext.MemberName
为null。
哇啊?!?
我做了一点调查,果然, DataAnnotationsModelValidator
内部就是代码……或缺乏代码。
public override IEnumerable Validate(object container) { // Per the WCF RIA Services team, instance can never be null (if you have // no parent, you pass yourself for the "instance" parameter). ValidationContext context = new ValidationContext(container ?? Metadata.Model, null, null); context.DisplayName = Metadata.GetDisplayName(); // Setting the MemberName here would be trivial! // However, philh told me not to. Something about // a guy named Josh who pushed him down on the playground // in middle school. //context.MemberName = Metadata.PropertyName; (Suck It, Josh!!!) ValidationResult result = Attribute.GetValidationResult(Metadata.Model, context); if (result != ValidationResult.Success) { yield return new ModelValidationResult { Message = result.ErrorMessage }; } }
我意识到如果没有将DisplayAttribute
应用于属性, DisplayName
可以是属性名称。 不幸的是,我无法真正处理假设。 我需要确切知道属性名称是什么。
那么这笔交易是什么? 这是设计还是诚实的疏忽。 如果是疏忽,那么在MVC 4中修复它会很棒:)
免责声明:
上面代码示例中添加的注释意味着很有趣。 我不知道,也没见过Phil Haack 。 从我可以看出他似乎是一个非常好的人。 在中学推他下去会让我成为皇室冲洗!
我遇到了同样的问题,并决定将属性名称作为参数传递给属性构造函数,然后将其存储在属性中。 例如:
[MyValidationAttribute("MyProperty")] public string MyProperty { get; set; }
然后在MyValidationAttribute.cs中:
public class MyValidationAttribute { private string PropertyName; public MyValidationAttribute(string propertyName) { this.PropertyName = propertyName; } }
这有点烦人,现在我必须两次输入我的属性的名称,但它解决了问题。
乔希,
令人沮丧,是的。
但是,出于您的目的,您可以创建自己的inheritance自DataAnnotationsModelValidator
的类,重写Validate()
方法,并取消注释那些嘲弄您的代码行。 然后,在Global.asax.cs中,清除ModelValidatorProviders.Providers
并添加您的类。
这不是一个最佳解决方案,而是一个可以帮助您到达目的地的解决方案。
您需要为属性类型调用DataAnnotationsModelValidatorProvider.RegisterAdapter
或DataAnnotationsModelValidatorProvider.RegisterAdapterFactory
方法并提供自定义ModelValidator
。
有同样的问题,这个问题让我走上正轨。 我通过更改自定义validation器来修复它,以便在创建ValidationResult时填充MemberName,如下所示(请注意ValidationResult构造函数中的第二个参数):
protected override ValidationResult IsValid(Object value, ValidationContext validationContext) { if (ShouldICareAboutYou(validationContext.MemberName)) { //Do some stuff } return new ValidationResult(FormatErrorMessage(validationContext.DisplayName), new string[] { validationContext.MemberName }); }