Asp.net MVC源码分析--Model Validation(Client端)实现(2)

来源:岁月联盟 编辑:exp 时间:2012-01-01

上一篇我们介绍了如果输出Client Validation 信息到浏览器,下面我们来分析一个MVC是如果实现JavaScript验证的。
一.TextFor 输出的Html文本
先来看一下标记了[Required] attribute的属性通过TextFor输出的Html代码:
<input data-val="true" data-val-required="The User name field is required." id="UserName" name="UserName" type="text" value="" class="valid">
复制代码
• data-val:是否需要客户端验证
• data-val-required:验证类型和错误消息
二.jquery.validate.unobtrusive.js的实现
1.unobtrusive 自定义验证规则
1 var $jQval = $.validator,
2          adapters,
3         data_validation = "unobtrusiveValidation";
复制代码
我们看到$jQval对象其实就是$.validator对象。
 1 $jQval.unobtrusive = {
 2  adapters: [],
 3 
 4  adapters = $jQval.unobtrusive.adapters;
 5    adapters.add = function (adapterName, params, fn) {
 6           if (!fn) {  // Called with no params, just a function
 7               fn = params;
 8               params = [];
 9           }
10           this.push({ name: adapterName, params: params, adapt: fn });
11           return this;
12       };
13  
14    adapters.add("required", function (options) {
15                 if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
16               setValidationValues(options, "required", true);
17           }
18       });
19  }
复制代码
上面代码第10行,我们看到unobtrusive把所有与MVC相关的验证规则都放到了$jQval.unobtrusive.adapters(Array)对象中. 那么这些验证规则如果被Jquery调用的呢?我们接着来看.
2.用Adapter模式与Jquery集成
下面我们看一下jquery.validate.unobtrusive.js的实现,当初始化时调用了$jQval.unobtrusive.parse方法请注意上面第42行,unobtrusive只对data-val设置为true的input控件进行验证 。
 1 $(function () {
 2          $jQval.unobtrusive.parse(document);
 3      });
 4 
 5    function validationInfo(form) {
 6          var $form = $(form),
 7              result = $form.data(data_validation);
 8 
 9          if (!result) {
10              result = {
11                  options: {  // options structure passed to jQuery Validate's validate() method
12                      errorClass: "input-validation-error",
13                      errorElement: "span",
14                      errorPlacement: $.proxy(onError, form),
15                      invalidHandler: $.proxy(onErrors, form),
16                      messages: {},
17                      rules: {},
18                      success: $.proxy(onSuccess, form)
19                  },
20                  attachValidation: function () {
21                      $form.validate(this.options);
22                  },
23                  validate: function () {  // a validation function that is called by unobtrusive Ajax
24                      $form.validate();
25                      return $form.valid();
26                  }
27              };
28              $form.data(data_validation, result);
29          }
30 
31          return result;
32      }
33 
34   parse: function (selector) {       
35              $(selector).find(":input[data-val=true]").each(function () {
36                  $jQval.unobtrusive.parseElement(this, true);
37              });
38 
39              $("form").each(function () {
40                  var info = validationInfo(this);
41                  if (info) {
42                      info.attachValidation();
43                  }
44              });
45          }
复制代码
上面的代码第21行,就是调用了jQuery的valildate方法对form 表单进行验证,那么this.options 是怎么得到的呢?
是在$jQval.unobtrusive.parseElement方法里完成的。
 1 parseElement: function (element, skipAttach) {
 2    
 3              var $element = $(element),
 4                  form = $element.parents("form")[0],
 5                  valInfo, rules, messages;
 6 
 7              if (!form) {  // Cannot do client-side validation without a form
 8                  return;
 9              }
10 
11              valInfo = validationInfo(form);
12              valInfo.options.rules[element.name] = rules = {};
13              valInfo.options.messages[element.name] = messages = {};
14 
15              $.each(this.adapters, function () {
16                  var prefix = "data-val-" + this.name,
17                      message = $element.attr(prefix),
18                      paramValues = {};
19 
20                  if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)
21                      prefix += "-";
22 
23                      $.each(this.params, function () {
24                          paramValues[this] = $element.attr(prefix + this);
25                      });
26 
27                      this.adapt({
28                          element: element,
29                          form: form,
30                          message: message,
31                          params: paramValues,
32                          rules: rules,
33                          messages: messages
34                      });
35                  }
36              });
37 
38              jQuery.extend(rules, { "__dummy__": true });
39 
40              if (!skipAttach) {
41                  valInfo.attachValidation();
42              }
43          },
复制代码
小结:
• $jQval.unobtrusive 利用adapter模式,对jQuery的validate方法包装
• unobtrusive只对data-val设置为true的input控件进行验证 。 

 

摘自 十一月的雨