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时,一切都运行得非常好!

然而…

在我的控制器中调用TryUpdateModelTryValidateModel ,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.RegisterAdapterDataAnnotationsModelValidatorProvider.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 }); }