ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现
在简单了解了Unobtrusive JavaScript形式的验证在jQuery中的编程方式之后,我们来介绍ASP.NET MVC是如何利用它实现客户端验证的。服务端验证最终实现在相应的ModelValidator中,而最终的验证规则定义在相应的ValidationAttribute中;而客户端验证规则通过HtmlHelper<TModel>相应的扩展方法(比如TextBoxFor、EditorFor和EdidtorForModel等)出现在生成的被验证HTML元素中。毫无疑问,服务端验证和客户端验证必须采用相同的验证规则,那么通过应用ValidationAttribute特性定义的验证规则也同样体现在基于客户端验证规则的HTML上。[本文已经同步到《How ASP.NET MVC Works?》中]
一、ValidationAttribute与HTML
ASP.NET MVC默然采用基于ValidationAttribute特性的声明式Model验证,服务端验证最终实现在两个重写的IsValid方法中。对于客户端验证,ASP.NET MVC对jQuery的验证插件进行了扩展,实现了另一种不同的内联方式是我们 可以将验证规则定义在被验证输入元素的属性中。为了让客户端和服务端采用相同的验证规则,应用在Model类型某个属性上的ValidationAttribute特性最终会体现在目标属性对应的HTML元素上。
1: public class Contact
2: {
3: [DisplayName("姓名")]
4: [Required(ErrorMessage ="请输入{0}!")]
5: [StringLength(8, ErrorMessage="作为{0}字符串长度不能超过{1}!")]
6: public string Name { get; set; }
7:
8: [DisplayName("电子邮箱地址")]
9: [RegularExpression(@"^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$",ErrorMessage="请输入正确的电子邮箱地址!")]
10: public string EmailAddress { get; set; }
11: }
假设我们具有如上一个数据类型Contact,RequiredAttribute和StringLengthAttribute特性应用到表示姓名的Name属性上用于确保用于必须输入一个不超过128个字符的字符串,而表示Email地址的EmailAddress属性应用了一个RegularExpressionAttribute用于确保用于输入一个合法的Email地址。在一个以此Contact为Model类型的View中,如果我们调用HtmlHelper<TModel>的扩展方法EditorForModel,最终会生成如下一段HTML。
1: <div class="editor-label">
2: <label for="Name">姓名</label>
3: </div>
4:
5: <div class="editor-field">
6: <input class="text-box single-line"
7: data-val ="true"
8: data-val-length ="作为姓名字符串长度不能超过8!"
9: data-val-length-max ="8"
10: data-val-required ="请输入姓名!"
11: id="Name" name="Name" type="text" value="" />
12: <span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
13: </div>
14:
15: <div class="editor-label">
16: <label for="EmailAddress">电子邮箱地址</label>
17: </div>
18:
19: <div class="editor-field">
20: <input class="text-box single-line"
21: data-val ="true"
22: data-val-regex ="请输入正确的电子邮箱地址!"
23: data-val-regex-pattern ="^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$"
24: id="EmailAddress" name ="EmailAddress" type="text" value="" />
25: <span class="field-validation-valid" data-valmsg-for="EmailAddress" data-valmsg-replace="true"></span>
26: </div>
通过上面的这段HTML我们可以看到,对应着Model对象两个属性的<input>元素具有一个“data-val”属性和一系列以“data-val-”为前缀的属性,前者表示是否需要对用户输入的值进行验证,后者则代表相应的验证规则。具体来说,去除“data-val-”前缀后的属性名称对应着采用jQuery验证时对应的验证规则名称。
一般来说,一个ValidationAttribute对应着一种验证类型和一系列可选的验证参数。比如RequiredAttribute、StringLengthAttribute和RegularExpressionAttribute对应的验证类型分别是“required”、“length”和“regex”,而StringLengthAttribute和RegularExpressionAttribute各自具有一个验证参数length-max(表示允许的字符串最大长度)和regex-pattern(正则表达式)。验证错误消息一般作为验证类型属性的值,而验证参数对应的属性值自然就是相应的属性值。
对于上面生成的HTML还有一点值得一提的是:对应着被验证属性的<input>元素会紧跟一个<span>元素用于显示验证失败后的错误消息。该<span>元素的CSS类型为“field-validation-valid”,我们可以通过它来定制错误消息的显示样式。
二、客户端验证规则的生成
ASP.NET MVC在利用jQuery进行客户端验证的时候,虽然验证规则并没有采用其原生的方式通过被验证元素的class属性来提供,但是却可以通过“data-val-{rulename}”的命名模式提取相应的验证规则属性值,并最终得到一样验证规则,ASP.NET MVC只需要对两种作简单的适配即可。
我们现在关心的是当我们调用HtmlHelper<TModel>相应的扩展方法将Model对象的某个属性以表单输入元素的形式呈现的时候是如何生成这些以“data-val-”为前缀的验证属性的呢?在这里我们需要涉及到一个重要的类型ModelClientValidationRule,顾名思义,ModelClientValidationRule用于描述客户端验证规则。如下面的代码所示,ModelClientValidationRule具有三个属性,字符串属性ErrorMessage和ValidationType表示验证错误消息和验证的类型,类型为IDictionary<string, object>的只读属性ValidationParameters表示辅助客户端验证的参数,其中Key和Value分别表示验证参数名和参数值。
1: public class ModelClientValidationRule
2: {
3: public string ErrorMessage { get; set; }
4: public string ValidationType { get; set; }
5: public IDictionary<string, object> ValidationParameters { get; }
6: }
7:
8: public abstract class ModelValidator
9: {
10: //其他成员
11: public virtual IEnumerable<ModelClientValidationRule> GetClientValidationRules();
12: public abstract IEnumerable<ModelValidationResult> Validate(object container);
13: }
通过前面的介绍我们知道抽象类ModelValidator中具有一个虚方法GetClientValidationRules用于返回一个ModelClientValidationRule对象的列表。对于所有支持客户端验证的ModelValidator来说,它必须重写该方法以通过重写Validate方法实现的服务端验证逻辑相一致的客户端验证规则。
以用于进行范围验证的RangeAttribute特性对应的RangeAttributeAdapter为例,通过如下的代码片断我们知道它重写了GetClientValidationRules并返回一个ModelClientValidationRangeRule对象元素的列表,该ModelClientValidationRule对象的验证类型为“range”,采用RangeAttributeAdapter的ErrorMessage属性作为自身的错误消息,作为验证范围的上、下限的值成为了该ModelClientValidationRule的两个验证参数,参数分别为“min”和“max”。
1: public class RangeAttributeAdapter : DataAnnotationsModelValidator<RangeAttribute>
2: {
3: //其他成员
4: public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
5: {
6: string errorMessage = base.ErrorMessage;
7: return new ModelClientValidationRangeRule[] { new ModelClientValidationRangeRule(errorMessage, base.Attribute.Minimum, base.Attribute.Maximum) };
8: }
9: }
10:
11: public class ModelClientValidationRangeRule : ModelClientValidationRule
12: {
13: public ModelClientValidationRangeRule(string errorMessage, object minValue, object maxValue)
14: {
15: base.ErrorMessage = errorMessage;
16: base.ValidationType = "range";
17: base.ValidationParameters["min"] = minValue;
18: base.ValidationParameters["max"] = maxValue;
19: }
20: }
客户端验证还在这里涉及到一个重要的接口IClientValidatable,它具有唯一的GetClientValidationRules方法返回一个以ModelClientValidationRule对象表示的客户端验证规则列表。
1: public interface IClientValidatable
2: {
3: IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context);
4: }
对于所有支持客户端验证的ValidationAttrubute来说,都需要实现IClientValidatable接口并通过实现GetClientValidationRules方法提供对应的验证规则,而生成的验证规则需要与通过重写的IsValid方法实现的服务端验证逻辑一致。DataAnnotationsModelValidator重写了GetClientValidationRules方法,如果对应的ValidationAttribute实现了IClientValidatable接口,它(ValidationAttribute)的GetClientValidationRules方法被调用返回的ModelClientValidationRule列表作为该方法的返回值。
当我们在某个View中调用HtmlHelper<TModel>的扩展方法将Model对象的某个属性以表单输入元素呈现出来的时候,会采用我们前面介绍的ModelValidator的提供机制根据目标属性对应的Model元数据创建相应的ModelValidator,然后调用GetClientValidationRules方法得到一组表示客户端验证规则的ModelClientValidationRule列表。如果该列表不为空,它们将作为验证属性附加到目标属性对应的<input>元素中。
ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现的更多相关文章
- 【ASP.NET MVC系列】浅谈数据注解和验证
[ASP.NET MVC系列]浅谈数据注解和验证 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google C ...
- [asp.net mvc 奇淫巧技] 01 - 封装上下文 - 在View中获取自定义的上下文
我们在asp.net 开发中已经封装了最强大的HttpContext,我们可以在HttpContext中可以获取到几乎任何想获取的东西,也可以在HttpContext写入需要返回客户端的信息.但是这些 ...
- ASP.NET MVC的客户端验证:jQuery的验证
之前我们一直讨论的Model验证仅限于服务端验证,即在Web服务器根据相应的规则对请求数据实施验证.如果我们能够在客户端(浏览器)对用户输入的数据先进行验证,这样会减少针对服务器请求的频率,从而缓解W ...
- ASP.NET MVC 音乐商店 - 6. 使用 DataAnnotations 进行模型验证
在前面的创建专辑与编辑专辑的表单中存在一个问题:我们没有进行任何验证.字段的内容可以不输入,或者在价格的字段中输入一些字符,在执行程序的时候,这些错误会导致数据库保存过程中出现错误,我们将会看到来自数 ...
- ASP.NET MVC View 和 Web API 的基本权限验证
ASP.NET MVC 5.0已经发布一段时间了,适应了一段时间,准备把原来的MVC项目重构了一遍,先把基本权限验证这块记录一下. 环境:Windows 7 Professional SP1 + Mi ...
- ASP.NET MVC 5改进了基于过滤器的身份验证
ASP.NET MVC 5包含在最近发布的Visual Studio 2013开发者预览版中,它使开发人员可以应用身份验证过滤器,它们提供了使用各种第三方供应商或自定义的身份验证提供程序进行用户身份验 ...
- ASP.NET MVC 4 (十三) 基于表单的身份验证
在前面的章节中我们知道可以在MVC应用程序中使用[Authorize]特性来限制用户对某些网址(控制器/控制器方法)的访问,但这都是在对用户认证之后,而用户的认证则依然是使用ASP.NET平台的认证机 ...
- ASP.NET MVC轻教程 Step By Step 10——模型验证
在使用表单获取用户输入的数据时,我们必须对数据进行有效性验证,因为来自网络的信息都是不可信的.同时也要给用户即时的反馈,避免让用户感到困惑.这就涉及到数据验证的范畴. 数据验证最直接的做法是在服务器端 ...
- aspx中的表单验证 jquery.validate.js 的使用 以及 jquery.validate相关扩展验证(Jquery表单提交验证插件)
这一期我们先讲在aspx中使用 jquery.validate插件进行表单的验证, 关于MVC中使用 validate我们在下一期中再讲 上面是效果,下面来说使用步骤 jQuery.Valid ...
随机推荐
- Webpack+React+ES6开发模式入门指南
React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了Reac ...
- AngularJS过滤器filter-时间日期格式-渲染日期格式-$filter
今天遇到了这些问题索性就 写篇文章吧 话不多说直接上栗子 不管任何是HTML格式还是JS格式必须要在 controller 里面写 // new Date() 获取当前时间 yyyy-MM-ddd ...
- Atitit MATLAB 图像处理attilax总结
Atitit MATLAB 图像处理attilax总结 1.1. 下载 Matlab7.0官方下载_Matlab2012 v7.0 官方简体中文版-办公软件-系统大全.html1 1.2. Matla ...
- 打印Lua的Table对象
小伙伴们再也不用为打印lua的Table对象而苦恼了, 本人曾也苦恼过,哈哈 不过今天刚完成了这个东西, 以前在网上搜过打印table的脚本,但是都感觉很不理想,于是,自己造轮子了~ 打印的效果,自己 ...
- WCF学习之旅—TCP双工模式(二十一)
WCF学习之旅—请求与答复模式和单向模式(十九) WCF学习之旅—HTTP双工模式(二十) 五.TCP双工模式 上一篇文章中我们学习了HTTP的双工模式,我们今天就学习一下TCP的双工模式. 在一个基 ...
- Application Request Route实现IIS Server Farms集群负载详解
序言 随着公司业务的发展,后台业务就变的越来越多,然而服务器的故障又像月经一样,时不时的汹涌而至,让我们防不胜防.那么后台的高可用,以及服务器的处理能力就要做一个横向扩展的方案,以使后台业务持续的稳定 ...
- 编写Windows服务疑问2:探索服务与安装器的关系
首先,来弄两个服务,一个叫“飞机”,一个叫“火车”. public class FeiJiService : ServiceBase { public FeiJiService() { Service ...
- MVC 验证码实现( 简易版)
现在网站上越来越多的验证码,使用场景也是越来越多,登陆.注册.上传.下载...等等地方,都有可能大量使用到验证码,那么制作验证码到底有多简单呢?我们一起来看下最简易版的验证码实现过程- 验证码的基本步 ...
- angular2系列教程(二)模板语法
今天我们要讲的是angualr2的模板语法,官网写的很清楚,但我也用通俗易懂的讲法再罗列一下吧! 例子
- 【Python五篇慢慢弹(4)】模块异常谈python
模块异常谈python 作者:白宁超 2016年10月10日12:08:31 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondo ...