使用 ASP.NET MVC 的 Validator Toolkit 创建客户端和服务器端表单验证






4.98/5 (25投票s)
本文介绍如何结合 jQuery JavaScript 库在客户端和服务器端验证 HTML 表单。
引言
Microsoft 刚刚发布了 ASP.NET MVC 框架的第一个预览版本,这是 Microsoft 基于模型-视图-控制器 (MVC) 架构开发 Web 应用程序的方式。它不会取代传统的 ASP.NET WebForms 模型。有关新框架的更多信息,请参阅 Scott Guthrie 的 博客文章。
由于目前只有一个预览版本可用,最终功能列表尚未完整。此时,没有内置的标准化系统来在客户端和服务器端验证 HTML 表单。**ASP.NET MVC 的 Validator Toolkit** 提供了一种使用验证集在客户端和服务器端进行表单验证的方法。该工具包是 Microsoft 的开源社区网站 CodePlex.com 上的一个新项目,网址为 CodePlex.com。
注意:Validator Toolkit 的最新源代码和示例站点可从 CodePlex 项目(源代码选项卡)下载。
下面的截图让您对该工具包的工作方式有所了解。

这是另一张截图,展示了如何显示错误消息。

现在,开始吧!
解决方案
如上所述,该工具包使用验证集作为关键元素。验证集是派生自 ValidationSet
基类的特殊类,它们定义了 HTML 表单的所有验证规则(验证器)。在视图渲染期间,该工具包会根据定义的验证器生成客户端 JavaScript 代码。
客户端利用功能强大的 jQuery
JavaScript 库及其 jQuery
验证插件来完成客户端验证的最终任务。有关 jQuery
及其插件的更多信息,请参阅以下链接:
该工具包使用的验证插件经过 sedikit 定制,以支持所有必需的行为。除了使用 jQuery
库进行客户端验证外,您还可以将其用于许多其他用途,例如动画或 DOM 操作。此外,还有许多已开发的插件扩展了核心库。验证集也用于在服务器端验证表单(基于 Request.Form
集合)。
在继续之前,让我们先看一下示例验证集。
public class LoginValidationSet : ValidationSet {
protected override ValidatorCollection GetValidators() {
return new ValidatorCollection (
new ValidateElement("username")
{ Required = true, MinLength = 5, MaxLength = 30 },
new ValidateElement("password")
{ Required = true, MinLength = 3, MaxLength = 50 }
);
}
}
此 LoginValidationSet
类通过覆盖基类的 GetValidators
方法来定义验证简单登录表单的规则。该方法必须返回一个 ValidatorCollection
实例,其中包含以后用于验证 HTML 表单的所有验证器。在这种情况下,用户名字段是必需的,并且输入字段必须包含至少 5 个字符,最多 30 个字符。密码字段也是必需的,但长度限制在 3 到 50 个字符之间。
定义的验证器的顺序也决定了验证过程的执行顺序。如果该工具包使用自定义属性来设置验证规则而不是 GetValidators
方法,则无法保证验证过程会按照属性定义的顺序进行验证,因为 Type.GetCustomAttributes
方法会按字母顺序返回属性列表。
当然,您也可以编写自己的自定义验证器,或者使用 ValidateScriptMethod
验证器,它允许您在客户端调用特定的 JavaScript 函数,并在验证集类中调用一个方法进行服务器端验证。稍后将详细介绍。
定义验证集类后,使用 ValidationSet
属性将其附加到视图和 HTML 表单处理控制器操作,如下所示:
//
// File: LoginController.cs
//
public class LoginController : Controller {
[ControllerAction]
public void Login() {
RenderView("Login");
}
[ControllerAction]
[ValidationSet(typeof(LoginValidationSet))]
public void Authenticate() {
if(this.ValidateForm())
RenderView("Overview");
else
RenderView("Login");
}
}
...
//
// File: Login.aspx.cs (CodeBehind)
//
[ValidationSet(typeof(LoginValidationSet))]
public partial class Login : ViewPage {
[ValidationSet(typeof(LoginValidationSet))]
public partial class Login : ViewPage {
}
}
然后,控制器操作 Authenticate
调用 ValidateForm
方法,该方法使用 ValidationSet
属性根据 NameValueCollection Request:Form
执行服务器端表单验证。
在 HTML 页面中,您需要如下初始化登录表单(loginForm
)的脚本验证:
<script type="text/javascript">
$(function(){
updateSettingsForSample1ValidationSet($('#loginForm').validate({rules:{}}));
});
</script>
下一步,您像往常一样定义 HTML 表单。
<form id="loginForm" action="/Login/Authenticate" method="post">
Username: <input type="text" id="username" name="username" /><br />
Password: <input type="text" id="password" name="password" /><br />
<input type="submit" value="Login" />
</form>
最后,必须定义定义验证规则的脚本。
<% this.RenderValidationSetScripts(); %>
您还需要将 jQuery
JavaScript 库包含在表单或主页面中。有关更多信息,请参阅 Validator
Toolkit 示例站点。该工具包的示例站点已将脚本包含在主页面中。
<script type="text/javascript" src="../../Content/jDate.js"></script>
<script type="text/javascript" src="../../Content/jQuery.Core.js"></script>
<script type="text/javascript" src="../../Content/jQuery.Delegate.js"></script>
<script type="text/javascript" src="../../Content/jQuery.Validation.js"></script>
基本上,您需要做的就是这样 - 在客户端和服务器端包含表单验证。下一节将概述标准验证器及其用法。
标准验证器
该工具包开箱即用地提供了一些标准验证器。下表概述了提供的验证器:
ValidatePresence |
验证输入值的存在性。 示例 new ValidatePresence("username")
|
ValidateDate |
根据给定的日期格式验证输入值。将 DateFormats 属性设置为逗号分隔的日期格式列表,可以检查该值是否符合指定的格式之一。您可以检查 MM/DD/YYYY 等日期格式。如果未定义 DateFormats ,则验证器将使用当前线程的区域性信息。示例 new ValidateDate("startDate", "yyyy-mm-dd,yyyymmdd")
new ValidateDate("startDate")
{ DateFormats = "yyyy-mm-dd,yyyymmdd" }
|
ValidateMin ValidateMax ValidateRange |
根据最小值、最大值或整数范围验证输入值。 示例 new ValidateMin("step", 5)
new ValidateRange("step") { Min = 1, Max = 99 }
|
ValidateMinLength ValidateMaxLength ValidateRangeLength |
根据最小值、最大值或整数范围验证输入值。 示例 new ValidateMaxLength("password ", 30)
new ValidateRangeLength("password")
{ MinLength = 5, MaxLength = 30 }
|
ValidateElement |
将多个验证器合并为一个验证器以保持简单,并允许以下验证:Required 、Min 、Max 、MinLength 、MaxLength 。示例 new ValidateElement("username")
{ Required = true, MinLength = 5 }
|
ValidateEqualTo |
将输入值与另一个输入值进行比较。此验证器对于比较密码输入很有用。 示例 new ValidateEqualTo("password", "passwordAgain")
|
ValidateScriptMethod |
使用自定义 JavaScript 函数和验证集类方法来验证输入值。 示例 new ValidateScriptMethod("username")
{ MethodName = "valUsername" }
new ValidateScriptMethod("username") {
MethodName = "valiUsername",
Parameters = "{Opt1:2, Opt2: "AB"}" }
|
仍缺少一些验证器,例如通用的正则表达式验证器或特定的电子邮件验证器。
验证集
每个验证集定义类都派生自 ValidationSet
基类。该基类包含并提供验证过程的通用功能。让我们看下面的示例,以解释验证集在验证复杂表单时提供的一些可能性。
public class LoginValidationSet : ValidationSet {
string Username = "";
string Password = "";
protected override ValidatorCollection GetValidators() {
return new ValidatorCollection
(
new ValidateElement("username")
{ Required = true, MinLength = 5, MaxLength = 30 },
new ValidateElement("password")
{ Required = true, MinLength = 3, MaxLength = 50 },
new ValidateScriptMethod("username", "validateUsername")
);
}
protected bool ValidateUsername() {
// DO HERE SOME VALIDATION AND RETURN RESULT AS BOOLEAN VALUE
return true;
}
protected override void OnValidate() {
if(Username.StartsWith("billy") && Password.StartsWith("gat"))
throw new ValidatorException("username", "The username/password combination ");
}
}
创建类型为 String
的非公共实例成员字段,例如 Username
或 Password
字段,允许基类使用相应的输入字段值来填充这些字段。这是一种无需检查底层值集合(例如 Request.Form
)即可访问输入值的简单方法。
ValidateScriptMethod
验证器定义了一个 JavaScript 函数(validateUsername
),以便在客户端验证期间调用。此函数必须在 HTML 页面中定义或包含。ValidationSet
基类在服务器端验证期间检查当前的验证集类是否包含一个不区分大小写且名为 validateUsername
的方法。
一旦在验证过程中调用了 GetValidators
方法定义的所有验证器,基类就会调用一个名为 OnValidate
的总体方法。通过覆盖此方法,您可以执行一些最终验证。如果要抛出异常,则需要使用字段名称和消息作为参数来抛出 ValidatorException
。
使用所述技术、jQuery
库的可能性以及自定义验证器(见下文),您可以相当有效地验证大多数复杂表单。下一节将介绍本地化消息的方法。
本地化
使用标准文件夹可以轻松地本地化工具包的错误消息。如果未更改默认设置,则每个验证器的默认错误消息存储在 *App_GlobalResources* 文件夹中的 ValidationSet.resx 文件中。资源键的命名约定如下:<VALIDATORNAME>_DefaultErrorMessage
。
要更改 ValidationSet.resx 资源文件的默认名称,派生验证集类可以使用 static
字段 DefaultMessageResourceName
或通过向类添加 MessageResourceName
属性来设置名称。还可以组合使用这些技术并使用多个资源文件。
Validator
Toolkit 中的示例站点包含本地化错误消息和字段名称的用法示例。本地化简单明了。
自定义验证器
创建自定义验证器非常简单,但需要对 jQuery
JavaScript 库和验证插件有一些基本了解(如果验证器希望支持客户端验证)。示例站点包含一个名为 ValidateBuga
的自定义验证器,它将输入值与常量字符串 buga 进行比较。每个验证器都派生自 Validator
类,该类提供了一些自定义验证器必须覆盖的虚拟方法:
GetClientMethodData |
此方法通过返回 ValidatorMethodData 类的实例来定义自定义验证器的名称(用于 jQuery 验证插件)、JavaScript 函数代码和默认错误消息。 |
GetClientRule |
此方法在验证器定义在验证集类中后,返回要使用的插件客户端规则。 |
GetClientMessage |
此方法返回给定元素的本地化错误消息。 |
GetDefaultErrorMessageFormat |
此方法返回自定义验证器的默认错误消息。 |
Validate |
此方法验证给定元素的输入值。如果输入无效,验证器必须调用 Validator 基类的 InsertError 方法来发出错误信号。 |
这是 ValidateBuga
示例验证器的源代码:
public class ValidateBuga : Validator {
public ValidateBuga(string elementsToValidate)
: base(elementsToValidate) {
}
public override ValidatorMethodData GetClientMethodData() {
return new ValidatorMethodData(
"buga",
"function(value,element,parameters){return value=='buga';}",
"$.format('" + ErrorMessageFormat + "')"
);
}
public override string GetClientRule(string element) {
return "buga:true";
}
public override string GetClientMessage(string element) {
return string.Format("buga:'{0}'", GetLocalizedErrorMessage(element))
.Replace("'", "\'");
}
protected override void Validate(string element) {
if(Values.ContainsKey(element) == false || (Values[element] ??
string.Empty).Trim() != "buga")
InsertError(element);
}
protected override string GetDefaultErrorMessageFormat() {
return "The field {0} must contain the value \"buga\"";
}
}
使用自定义验证的另一种方法是使用 ValidateScriptMethod
验证器。它允许在客户端调用 JavaScript 函数,在服务器端调用验证集类的特定方法。自定义验证是验证集类的一部分,不能在多个验证集中使用。
摘要
Validator
Toolkit 是一种简单易用的方法,可为新的 ASP.NET MVC 框架添加客户端和服务器端 HTML 表单验证。通过添加自定义验证器,可以轻松扩展该工具包。您可以使用该工具包,直到 Microsoft 提供 HTML 表单验证的解决方案。