65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET MVC3 验证基础

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (13投票s)

2011 年 9 月 4 日

CPOL

4分钟阅读

viewsIcon

143063

downloadIcon

3012

在本文中,我将简要解释 ASP.NET MVC3 的验证是如何工作的。

引言

ASP.NET MVC3 附带了一个验证功能,它不仅支持服务器端和客户端验证,还隐藏了所有验证细节,从而实现了非常整洁的控制器代码和 HTML 标记。

验证演练

尝试 ASP.NET MVC 验证功能的最简单方法是创建一个具有默认 Internet 应用程序模板的 Web 应用程序,该模板将自动生成所有必需的验证代码。

模型类上的验证属性

让我们看看为 RegisterModel 类生成的验证代码。

public class RegisterModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email address")]
    public string Email { get; set; }

    [Required]
    [ValidatePasswordLength]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password 
		do not match.")]
    public string ConfirmPassword { get; set; }
}
  • Required 属性用于 UserNameEmail Password 属性,将它们标记为必填项。
  • Display 属性用于所有属性,为它们提供显示名称,用作字段标签或错误消息。
  • DataType 属性用于 Email Password 属性,以指示属性的类型。
  • ValidationPasswordLength 属性是一个自定义验证属性。我稍后会详细讨论它。
  • Compare 属性用于 ConfirmPassword ,以比较 Password ConfirmPassword
验证属性来自哪里?

通用验证属性定义在 System.ComponentModel.DataAnnotations 命名空间(System.ComponentModel.DataAnnotations.dll)中。这包括 Required 属性、Range 属性、RegularExpression 属性、StringLength 属性等。它们都继承自 ValidationAttribute 基类,并重写 IsValid 方法以提供其特定的验证逻辑。DisplayAttribute 也位于 System.ComponentMode.DataAnnotations 命名空间中,但它是显示属性而不是验证属性。DataTypeAttribute 是一个验证属性,但在 MSDN 中被归类为显示属性。供参考,在 System.ComponentMode.DataAnnotations 命名空间中,有用于 Entity Framework 的数据建模属性,如 AssociationAttributeKeyAttribute 等。

MVCValidationBasic/RequiredAttributeClass.gif

CompareAttribute 是 ASP.NET MVC 提供的特殊用途验证属性。它位于 System.Web.Mvc 命名空间(System.Web.Mvc.dll)中。ASP.NET MVC 提供的另一个验证属性是 RemoteAttribute,它使用 Ajax 调用服务器端控制器操作来执行验证。CompareAttribute 还实现了 ASP.NET MVC 客户端验证的接口 IClientValidatableIClientValidatable 只有一个方法 GetClientValidationRule,其签名如下:

IEnumerable<modelclientvalidationrule> GetClientValidationRules
(ModelMetadata metadata, ControllerContext context);
</modelclientvalidationrule>
  • ModelMetadata 是通用元数据的容器。它允许类在进行验证时利用模型信息。
  • ControllerContext 是 HTTP 请求和其他请求环境数据的容器。
  • ModelClientValidationRule 是发送到浏览器的客户端验证规则的基类。MVC 中有六个内置验证规则:ModelClientValidationEqualToRuleModelClientValidationRemoteRuleModelClientValidationRequiredRuleModelClientValidationRangeRuleModelClientValidationStringLengthRuleModelClientValidationRegexRule。如果你留意一下,你会发现 System.ComponentModel.DataAnnotations 中的所有通用验证属性都有一个对应的 ModelClientValidationRule 。ASP.NET MVC 创建适配器,例如 RequiredAttributeAdapter,来扩展通用验证属性以支持 ASP.NET MVC 验证设计。
MVCValidationBasic/CompareAttributeClass.gif

ValidatePasswordLengthAttribute 是一个自定义验证,它继承自 ValidateAttribute 并实现了 IClientValidatable

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, 
		AllowMultiple = false, Inherited = true)]
    public sealed class ValidatePasswordLengthAttribute : ValidationAttribute, 
		IClientValidatable
    {
        private const string _defaultErrorMessage = "'{0}' 
			must be at least {1} characters long.";
        private readonly int _minCharacters = 
		Membership.Provider.MinRequiredPasswordLength;

        public ValidatePasswordLengthAttribute()
            : base(_defaultErrorMessage)
        {
        }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentCulture, ErrorMessageString,
                name, _minCharacters);
        }

        public override bool IsValid(object value)
        {
            string valueAsString = value as string;
            return (valueAsString != null && valueAsString.Length >= _minCharacters);
        }

        public IEnumerable<modelclientvalidationrule> 
	GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            return new[]{
                new ModelClientValidationStringLengthRule(FormatErrorMessage
		(metadata.GetDisplayName()), _minCharacters, int.MaxValue)
            };
        }
    }
</modelclientvalidationrule>

这里需要注意的一点是 ValidatePasswordLengthAttribute 引用了 Membership,因此应用程序需要配置 Membership 提供程序才能使其正常工作。

MVCValidationBasic/ValidatePasswordLengthAttributeClass.gif

您可以在单个属性上应用不同的验证属性,这种聚合设计使得 ASP.NET MVC 的验证功能更加强大和灵活。

Server Side Validation

为了了解我们的自定义验证在 ASP.NET MVC 服务器端是如何发挥作用的,让我们看一下调用自定义验证属性 ValidatePasswordLengthAttribute IsValid 方法的调用堆栈。

MVCValidationBasic/CallStack.gif

从调用堆栈可以看出,服务器端验证发生在模型绑定阶段(DefaultModelBinder.BindModel(…))。ModelValidator 调用每个验证属性类,根据给定的设置来验证模型数据。验证结果(ModelValidationResult)存储在 ModelState 中,供操作或视图使用。

[HttpPost]
public ActionResult Register(RegisterModel model)
{
    if (ModelState.IsValid)
    {
        // Attempt to register the user
        MembershipCreateStatus createStatus = MembershipService.CreateUser
			(model.UserName, model.Password, model.Email);

        if (createStatus == MembershipCreateStatus.Success)
        {
            FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            ModelState.AddModelError("", 
		AccountValidation.ErrorCodeToString(createStatus));
        }
    }

    // If we got this far, something failed, redisplay form
    ViewBag.PasswordLength = MembershipService.MinPasswordLength;
    return View(model);
}

ModelState.IsValid 通过检查内部错误集合返回 true false

public bool IsValid
{
    get
    {
        return this.Values.All((ModelState modelState) => modelState.Errors.Count == 0);
    }
}
Client Side Validation

客户端验证在 web.config 中默认启用。

  <appSettings>
    <add key="ClientValidationEnabled" value="true"/> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/> 
  </appSettings>

但是,您必须确保 jquery.validation.min.jsjquery.validation.unobtrusive.min.js 也已添加到视图页面。

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript">
</script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" 
type="text/javascript"></script>

验证需要 HtmlHelper 类的扩展方法:ValidateValidateForValidationMessageValidationMessageForValidationSummary

jquery.validate.min.js 是标准的 jQuery 验证库。jquery.validate.unobtrusive.min.js 是一个 ASP.NET MVC 客户端验证库,它构建在 jQuery 验证库之上。它使用 HTML 元素属性来存储验证信息。这种设计非常整洁,对 UI 设计师来说侵入性很小。

远程验证属性的实际应用

上面的验证代码是从 ASP.NET MVC 项目模板生成的。我还想在这里展示远程验证属性,以说明如何使用它。要求很简单——用户名“Bin”在此应用程序中不允许,应用程序需要在用户名字段中输入“Bin”后立即显示错误。

  1. LogOnModelUserName 属性上添加 Remote 属性。
    [Required]
    [Display(Name = "User name")]
    [Remote("DisallowName", "Account")]
    public string UserName { get; set; }

    第一个参数是 Action 名称,第二个参数是 Controller 名称。

  2. AccountController 中创建一个 DisallowName 操作。
    public ActionResult DisallowName(string UserName)
    {
        if (UserName != "Bin")
        {
            return Json(true, JsonRequestBehavior.AllowGet);
        }
    
        return Json(string.Format("{0} is invalid", UserName), 
    			JsonRequestBehavior.AllowGet);
    }

    就是这样。远程验证就完成了。让我们看看屏幕上的效果。

    MVCValidationBasic/LogOnScreen.gif

结论

ASP.NET MVC3 中的验证设计非常整洁且功能强大。它使服务器端和客户端验证保持一致。

Using the Code

代码是在 Visual Studio 2010 中开发的。使用代码没有特殊要求。

历史

  • 2011 年 9 月 4 日:初稿
© . All rights reserved.