MVC 3模型验证问题 - 监督或设计

时间:2011-09-16 16:46:31

标签: c# .net asp.net-mvc asp.net-mvc-3 validation

我遇到了一个场景,我需要知道自定义ValidationAttribute中当前正在验证哪个属性。我认为这在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进行单元测试时,一切都运行良好!

HOWEVER ......

在我的控制器中调用TryUpdateModelTryValidateModel时,验证会运行,但ValidationContext.MemberName为空。

哇啊???

我做了一点调查,果然,DataAnnotationsModelValidator内部是代码......或缺乏代码。

public override IEnumerable<ModelValidationResult> 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
        };
    }
} 

如果没有DisplayName应用于该属性,我意识到DisplayAttribute 可能是属性名称。不幸的是,我无法真正处理假设。我需要知道完全属性名称是什么。

那么这笔交易是什么?这是设计还是诚实的疏忽。如果是疏忽,那么在MVC 4中解决这个问题真是太棒了:))

声明:

上面代码示例中的添加评论意味着很有趣。我不知道,也没见过Phil Haack。从我所知,他似乎是一个非常好的人。在中学推他下去会让我成为皇家冲洗!

4 个答案:

答案 0 :(得分:4)

我遇到了同样的问题,并决定将属性名称作为参数传递给属性构造函数,然后将其存储在属性中。例如:

[MyValidationAttribute("MyProperty")]
public string MyProperty { get; set; }

然后在MyValidationAttribute.cs中:

public class MyValidationAttribute
{
    private string PropertyName;

    public MyValidationAttribute(string propertyName)
    {
        this.PropertyName = propertyName;
    }
}

现在我必须两次输入我的属性名称但它解决了这个问题,这有点令人讨厌。

答案 1 :(得分:3)

乔希,

令人沮丧,是的。

但是,出于您的目的,您可以创建自己的继承自DataAnnotationsModelValidator的类,覆盖Validate()方法,并取消注释嘲弄您的代码行。然后,在Global.asax.cs中,清除ModelValidatorProviders.Providers并添加您的班级。

不是最佳解决方案,但可以帮助您到达目的地。

答案 2 :(得分:1)

您需要为您的属性类型调用DataAnnotationsModelValidatorProvider.RegisterAdapterDataAnnotationsModelValidatorProvider.RegisterAdapterFactory方法并提供自定义ModelValidator

答案 3 :(得分:1)

有同样的问题,这个问题让我走上正轨。我通过更改自定义验证器来修复它,以便在创建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 });
}