如何在ASP.NET MVC 2应用程序中执行复杂的模型验证?

时间:2012-09-21 16:55:21

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

我一直在努力重构我现在做模型验证的方式。我的应用程序都是ASP.NET MVC 2(.Net 3.5框架)。我已经阅读了这个主题的相关问题,但它们与我提出的问题并不完全相同。

目前,对于页面验证,我通常会遇到if / else语句的大杂烩。问题是,如果字段A是某个值,有时字段B会被验证,但字段A也有自己的验证。在某些情况下,有一些角色可以发挥作用,这也可以根据用户的角色来验证验证(即,不验证具有角色x的用户无法修改的字段)。

我的问题归结为:

1)如何以更易于阅读的方式处理验证?我看过DataAnnotations,但还不够。数据注释处理字段值的验证,其中可能需要完成的验证取决于字段的值和对象上其他属性的值。

2)如何将验证框架与ASP.NET MVC 2集成?

我真正讨厌我现在正在进行验证的事情是,当我添加模型错误时,我很难为该属性编写密钥。那太糟糕了。不过,我不知道如何获取所述属性的密钥,使其与html帮助程序创建的html字段匹配。

例如,在我看来,我使用编辑器模板来显示客户对象的字段。

   <%= Html.EditorFor(m => m.CustomerInfo) %>

生成的部分html为FirstName创建字段:

<input id="CustomerInfo_FirstName" name="CustomerInfo.FirstName" style="width:330px;" type="text" value="John" />

为了让框架仍然使用必要的CSS突出显示该字段,我正在强制执行此验证:

//Ignore that this can be done with DataAnnotations. This is just a simple example.   
if (String.IsnullOrEmpty(customerInfo.FirstName) )
{
    ModelState.AddModelError("CustomerInfo.FirstName",
    "First Name is required.");
}

这是我认为的主要问题。我没有办法知道页面上字段的名称。它似乎采取了

的模式
 <objectname>.<propertyname>

,但我真的想要更可靠的东西。

要获取对象名称,我想我可以将它从ModelBindingContext类中拉出来,但我不确定如何从控制器内部获取此实例。对于属性名称,我可以使用somekind lambda将属性的名称作为字符串返回。

总结一下,我正在寻找:1)某种允许复杂验证的验证框架2)识别在ModelState.AddModelError方法中使用的键的一些方法,以便MVC的错误样式仍然有效。

1 个答案:

答案 0 :(得分:0)

你真的在寻找FluentValidation

但是,我不确定它是否支持MVC2。它确实支持MVC3和MVC4。

其网站上的示例代码:

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Company).NotNull();
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}