在简单了解了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的验证
ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现
ASP.NET MVC的客户端验证:自定义验证

转载于:https://www.cnblogs.com/artech/archive/2012/06/18/client-validation-02.html

ASP.NET MVC的客户端验证:jQuery验证在Model验证中的实现相关推荐

  1. DynamicData for Asp.net Mvc留言本实例 中篇 新建.删除.数据验证

    上篇咱完成了显示列表的功能,下面接着来 也许您有疑问,这个显示列表不是和正常的Asp.net Mvc差不多吗?也是个foreach只是由原来的<%=字段%>变成了<% Html.Re ...

  2. [翻译-ASP.NET MVC]Contact Manager开发之旅迭代3 - 验证表单

    本翻译系列为asp.net mvc官方实例教程.在这个系列中,Stephen Walther将演示如何通过ASP.NET MVC framework结合单元测试.TDD.Ajax.软件设计原则及设计模 ...

  3. Jeesite 客户端验证Jquery Validate及服务器端验证

    2019独角兽企业重金招聘Python工程师标准>>> Jeesite框架采用了双重验证模式,即客户端采用Jquery Validate表单验证以及服务器端数据校验,可以有效的防止恶 ...

  4. ASP.NET MVC 音乐商店 - 6. 使用 DataAnnotations 进行模型验证

    在前面的创建专辑与编辑专辑的表单中存在一个问题:我们没有进行任何验证.字段的内容可以不输入,或者在价格的字段中输入一些字符,在执行程序的时候,这些错误会导致数据库保存过程中出现错误,我们将会看到来自数 ...

  5. ASP.NET MVC 4 (十三) 基于表单的身份验证

    在前面的章节中我们知道可以在MVC应用程序中使用[Authorize]特性来限制用户对某些网址(控制器/控制器方法)的访问,但这都是在对用户认证之后,而用户的认证则依然是使用ASP.NET平台的认证机 ...

  6. ASP.Net MVC从客户端中检测到有潜在危险的 Request.Form 值

    ASP.NET MVC4(Razor)从客户端中检测到有潜在危险的 Request.Form 值  "/"应用程序中的服务器错误. 从客户端(Content=" sdfd ...

  7. Asp.net MVC 示例项目Suteki.Shop分析之---Model和Service

    老戴的文章,自己去看吧 http://www.cnblogs.com/daizhj/archive/2009/05/31/1455867.html 转载于:https://www.cnblogs.co ...

  8. [ASP.NET MVC 小牛之路]16 - Model 验证

    上一篇博文 [ASP.NET MVC 小牛之路]15 - Model Binding 中讲了MVC在Model Binding过程中如何根据用户提交HTTP请求数据创建Model对象.在实际的项目中, ...

  9. ASP.NET MVC 2示例Tailspin Travel UI层分析

    Tailspin Travel 是一个旅游预订的应用程序示例,最新版本采用ASP.NET MVC 2技术构建,主要使用 DataAnnotations 验证, 客户端验证和ViewModels,还展示 ...

  10. How ASP.NET MVC Works?

    一.ASP.NET + MVC IIS与ASP.NET管道 MVC.MVP以及Model2[上篇] MVC.MVP以及Model2[下篇] ASP.NET MVC是如何运行的[1]: 建立在" ...

最新文章

  1. tcp 的ack, seq
  2. [HAOI2008]移动玩具
  3. sql查询索引语句_sql优化总结--基于sql语句优化和索引优化
  4. python项目结构图_python项目
  5. Aittit rpc的实现协议 JSON-RPC XML-RPC . Ws协议webservice 目录 1. XML-RPC协议 1 1.1. JSON-RPC远程调用协议 - CieloSun
  6. 嵌入式、单片机开发必备软件
  7. 转账设计测试用例-----必背
  8. 36.42. schemata
  9. Runtime Error! R6025-pure virtual function call 问题怎么解决
  10. c语言用fun函数求最大公约数,c语言求最大公约数
  11. Good Ticket(深搜)
  12. 关于Code Virtualizer pcode解密的一种方法
  13. EC20 AT指令 列举
  14. 自动生成无课表(云南农业大学)
  15. 前端技术-HTML页面的加载
  16. flutter TextDecoration 和 TextDecorationStyle
  17. 深度对比 Python 与 Java 的区别(一)
  18. 全球遥感监测土壤水分技术水平
  19. 如何通过GZIP来优化你的网站
  20. 封神台--第二章:遇到阻难!绕过WAF过滤!解题思路

热门文章

  1. File /usr/local/lib/python3.5/site-packages/dateutil/rrule.py, line 55 raise ValueError
  2. unrecognized selector sent to instance的一类解决办法
  3. access html导出,AccessToFile
  4. php个人资料表单显示,php-如何显示用户从表单构建器中选择的带...
  5. edge浏览器卸载不掉_【喂你播】华为申请 “荣耀”啤酒饮料类商标;微软确认Edge浏览器无法卸载...
  6. iOS中书写代码规范35条小建议
  7. 浙大研究生hadoop工作分享
  8. 关于strcpy的安全函数的选择
  9. 轻量级前端MVVM框架avalon - 初步接触
  10. Macx OS下没有GCC问题