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

2023-09-03 09:59:19 作者:xx卑微辽

我遇到了一个场景,我需要知道哪个属性是目前正在定制 ValidationAttribute 验证。我以为这会很容易在MVC 3,因为 ValidationContext 被传递到的 的IsValid 的方法。

I ran into a scenario where I needed to know which property was currently being validated in a custom ValidationAttribute. I assumed this would be easy in MVC 3 since the ValidationContext is being passed into the IsValid method.

没有进入细节,这里的基本思想是:

Without going into detail, here is the basic idea:

protected override ValidationResult IsValid(Object value, ValidationContext validationContext) {

   if (ShouldICareAboutYou(validationContext.MemberName))
   {
       //Do some stuff
   }

   //Return the results
}

这似乎像是一个完美的解决方案,而事实上,在单元测试我的自定义ValidationAttribute使用Validator.TryValidateObject一切都一级棒!

This seemed like the perfect solution, and indeed, when unit testing my custom ValidationAttribute using Validator.TryValidateObject everything worked beautifully!

但是...

在调用TryUpdateModel,或TryValidateModel在我的控制器,验证运行,但 ValidationContext.MemberName 为空。

Whaa咦?!?

我做了一个小调查,果然,就在那里里面DataAnnotationsModelValidator是code ...或缺乏。

I did a little investigation and sure enough, right there inside of DataAnnotationsModelValidator is the code... or lack thereof.

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
        };
    }
} 

我知道显示名称的可以的是属性名,如果没有 DisplayAttribute 已施加到属性。不幸的是我真的不能买卖hypotheticals。我需要知道的完全什么是属性名称是。

I realize that DisplayName could be the property name if no DisplayAttribute has been applied to the property. Unfortunately I can't really deal in hypotheticals. I need to know exactly what the property name is.

那么,什么是交易?这是由设计或一个诚实的监督如果这是一个疏忽,那么这将是真棒得到这个固定的MVC 4:。)

So what is the deal? Is this by design or an honest oversight. If it is an oversight, then it would be awesome to get this fixed in MVC 4 :)

在加入的的code样品上方意在评论很好玩。我不知道,我也没有见过菲尔哈克。从我可以告诉他似乎是一个真正的好人。而把他倒在初中就已经让我皇室冲洗!

The added comments in the code sample above are meant to be funny. I do not know, nor have I ever met Phil Haack. From what I can tell he seems like a really nice guy. And pushing him down in middle school would have made me a royal douche!

推荐答案

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

I had this same problem and decided to pass in the property name as a parameter in the attribute constructor and then store it in the attribute. For example:

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

然后在MyValidationAttribute.cs:

Then in MyValidationAttribute.cs:

public class MyValidationAttribute
{
    private string PropertyName;

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

这是一个有点讨厌,现在我必须键入我的财产的名字两次,但它解决了这个问题。

It is a little annoying that now I have to type the name of my property twice but it solves the problem.