我遇到了一个场景,我需要知道自定义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 ......
在我的控制器中调用TryUpdateModel
或TryValidateModel
时,验证会运行,但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。从我所知,他似乎是一个非常好的人。在中学推他下去会让我成为皇家冲洗!
答案 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.RegisterAdapter
或DataAnnotationsModelValidatorProvider.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 });
}