类/模型级别validation(与财产级别相对)? (ASP.NET MVC 2.0)

基本上,标题是什么。 我有几个属性组合在一起真正做出一个逻辑答案,我想运行一个服务器端validation代码(我写),考虑到这些多个字段,并挂钩只有一个validation输出/错误消息,用户在网页上看到。

我查看了scott guthries扩展属性并在dataannotations声明中使用它的方法,但是,正如我所看到的,没有办法在多个属性上声明dataannotations-style属性,并且只能放置声明(例如[电子邮件],[范围],[必填])超过一个属性:(。

我查看了启动新项目时出现的默认mvc 2.0项目中的PropertiesMustMatchAttribute,这个示例与使用一对引脚检查机油一样有用 – 没用!

我已经尝试过这种方法,但是,创建一个类级别属性,并且不知道如何在我的aspx页面中显示错误。 我已经尝试过html.ValidationMessage(“ClassNameWhereAttributeIsAdded”)和其他各种各样的东西,但它还没有用。 我应该提一下,在这个级别上没有一篇关于进行validation的博客文章 – 尽管这是任何项目或业务逻辑场景中的常见需求!

任何人都可以帮助我在我的aspx页面中显示我的消息,并且如果可能的话,还有一个适当的文档或参考解释在这个级别的validation?

现在您已经查看了数据注释并得出结论它们不适合您的场景我建议您查看FluentValidation ,它与ASP.NET MVC的集成以及您对unit testingvalidation逻辑的方式 – 您赢了不要感到失望(我真的没有任何反对数据注释,他们非常适合博客文章和教程,但一旦你遇到真实世界的应用程序,你很快就会意识到限制)。


更新:

正如评论部分中所要求的,这是一个使用FluentValidation框架和一个服务器端validation函数访问多个属性的示例(请不要这样做,因为它很难看并且有更好的方法):

class AuthInfo { public string Username { get; set; } public string Password { get; set; } public string ConfirmPassword { get; set; } } class AuthInfoValidator : AbstractValidator { public override ValidationResult Validate(AuthInfo instance) { var result = base.Validate(instance); if (string.IsNullOrEmpty(instance.Username)) { result.Errors.Add(new ValidationFailure("Username", "Username is required")); } if (string.IsNullOrEmpty(instance.Password)) { result.Errors.Add(new ValidationFailure("Password", "Password is required")); } if (string.IsNullOrEmpty(instance.ConfirmPassword)) { result.Errors.Add(new ValidationFailure("ConfirmPassword", "ConfirmPassword is required")); } if (instance.Password != instance.ConfirmPassword) { result.Errors.Add(new ValidationFailure("ConfirmPassword", "Passwords must match")); } return result; } } 

更自然的方法是执行此操作(它也不受属性重命名的影响,因为它不包含任何魔术字符串):

 class AuthInfoValidator : AbstractValidator { public AuthInfoValidator() { RuleFor(x => x.Username) .NotEmpty() .WithMessage("Username is required"); RuleFor(x => x.Password) .NotEmpty() .WithMessage("Password is required"); RuleFor(x => x.ConfirmPassword) .NotEmpty() .WithMessage("ConfirmPassword is required"); RuleFor(x => x.ConfirmPassword) .Equal(x => x.Password) .WithMessage("Passwords must match"); } } 

我不确定,但你是不是因为没有明显原因(或者我对VB.NET的观点b / c)继续投票我的答案/问题的人吗?

无论如何, PropertiesMustMatchAttribute只是在对象上使用特定属性的值的一个很好的实现。 如果需要使用对象的多个字段运行某些逻辑,则可以使用以下内容执行此操作,类似于PropertiesMustMatchAttribute执行的操作。

下面是ValidationAttribute的主要部分,它访问对象属性以运行某些逻辑。

  public override bool IsValid(object value) { PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value); // Get the values of the properties we need. // Alternatively, we don't need to hard code the property names, // and instead define them via the attribute constructor object prop1Value = properties.Find("Person", true).GetValue(value); object prop2Value = properties.Find("City", true).GetValue(value); object prop3Value = properties.Find("Country", true).GetValue(value); // We can cast the values we received to anything Person person = (Person)prop1value; City city = (City)prop2value; Country country = (Country)prop3value; // Now we can manipulate the values, running any type of logic tests on them if(person.Name.Equals("Baddie") && city.ZIP == 123456) { return country.name.Equals("Australia"); } else { return false; } } 

PropertiesMustMatchAttribute只是使用Reflection来完成一项常见任务。 我试图分解代码以使其更易读/更容易理解。

可能的杜佩:

编写CompareTo DataAnnotation属性

你的问题的答案应该在那里,至少它指向这篇博文:

http://byatool.com/mvc/custom-data-annotations-with-mvc-how-to-check-multiple-properties-at-one-time/


要显示错误消息,您必须使用:

 <%: Html.ValidationMessage("") %> 

会发生什么是因为您在类级别validation您获得带有键的ModelState,通常是属性名称,带有空字符串。

通过ValidationAttribute的子类创建类级属性时,如果validation失败,ModelState中没有对应的键=>它将是一个空字符串,但下面提供的链接中提供了解决方法,这将帮助U显示错误消息在你的视图中只使用html.ValidationMessage(“urpropertyname”)而不是你试过的html.ValidationMessage(“ClassNameWhereAttributeIsAdded”)。

无法在MVC2中设置自定义validation属性的成员名称

我知道这已经得到了回答,但是如果你想继续使用DataAnotations Attributes,MVC3似乎已经添加了另一种方法来实现这一点。

您的类可以实现提供Validate方法的IValidatableObject接口。 只是另一种皮肤猫的方式。

我使用FluentValidator完成了以下操作,如果它对任何人都有用,感谢Darin的建议:

 Public Class tProductValidator Inherits AbstractValidator(Of tProduct) Public Sub New() Const RetailWholsaleError As String = "You need to enter either a Retail Price (final price to user) or a Wholesale Price (price sold to us), but not both." Dim CustomValidation As System.Func(Of tProduct, ValidationFailure) = Function(x) If (x.RetailPrice Is Nothing AndAlso x.WholesalePrice Is Nothing) OrElse (x.RetailPrice IsNot Nothing AndAlso x.WholesalePrice IsNot Nothing) Then Return New ValidationFailure("RetailPrice", RetailWholsaleError) End If Return Nothing End Function Custom(CustomValidation) End Sub End Class 

像往常一样,我被愚弄认为MVC是一个完整的框架,真实世界的场景是可能的。 他们如何发布这样的东西,甚至没有提到我不理解的局限性,我们开发人员然后遇到的问题是一个噩梦,或者我们必须依靠第三方的东西去做本质上的MVC责任,如果第三方物品不可用 – 那么什么?

这不是我在mvc 2.0中发现的第一次严重后退,该列表不断增长。

确保团队不断给出这些“酷”的例子,说明使用虚构的非现实世界的例子是多么简单,当谈到真实的东西时,它就像“我们不知道或不关心,我们也不会告诉你,你只需要遇到它并自己解决“类型交易

哦,并且在一次往返中更新视图的多个部分仍然是不可能的,除非你使用js hack并剪切返回html并将其分配给不同的div …你甚至不能返回多个视图或至少更新页面的多个区域本身(在一个往返),它只是令人伤心。

也许当MVC达到3.0版本时,它可能实际上是完整的,手指交叉,因为dotnet框架实际上并非“完整”,直到clr 3.5并包括linq / EF到SQL …