ExtJS表单验证与ASP.NET MVC视图模型验证

  带过下传统的ASP.NET MVC程序中的模型验证。在MVC程序中的视图模型是一种具有自我描述能力的实体类,而这个自我描述的能力是可以我们开发人员进行扩展的。在这些描述信息中,很重要的一部分就是对模型本身进行校验的信息,这些信息可以供框架校验用户反馈的模型的合法性,当然这个校验的过程在后台是少不了的。当然前台的校验工作也不能缺少,为了让用户有更好的体验以及减轻服务器端不必要的校验工作,ASP.NET MVC会将一部分的校验工作放在前台界面,让js来承担这部分的责任。这就是传统的模型验证的大概,详细的,可以参考MicrosoftMvcValidation.debug.js的代码以及在.aspx页面中输出的模型验证元数据。

  使用传统的模型验证,不仅具有很好的可扩展性,恐怕其易用性以及简洁的代码的威力也是不可小觑的,相信有接触过的人都有感受。用过ExtJS的可能也有接触过extjs的表单验证,对于它的优点及用法我不是很清楚,总不至于是个差的东西,应该是不错的。尽管它可能很好用,但是它终归是一个独立的框架,无法直接去使用ASP.NET MVC为MicrosoftMvcValidation.debug.js生成的前台模型验证元数据。有一个很明显的事实那就是前台页面上已经有了模型验证元数据了,这些元数据是一些很有价值的东西,我总得想个办法使用它吧,1、要么打extjs的主意,扩展它的验证器;2、要么就是打MicrosoftMvcValidation的主意,让它的验证结果最终变成extjs的验证结果。出于对extjs庞大的体系的恐惧,我最终选择了后者。我重写了MicrosoftMvcValidation.debug.js中的Sys.Mvc.FieldContext.prototype._displayError,让原本的显示逻辑转换为extjs的呈现错误的逻辑即可,很干脆!

代码
 
   
1 Ext.QuickTips.init();
2
3 Ext.form.Field.prototype.msgTarget = ' side ' ;
4 Ext.form.Field.prototype.validationDelay = 0 ;
5 Ext.form.Field.prototype.validateOnBlur = false ;
6 Ext.form.Field.prototype.validationEvent = ' keydown ' ;
7 Sys.Mvc.FieldContext.prototype._displayError = function () {
8 if ( this ._errors.length > 0 ) {
9 Ext.getCmp($( this .elements).attr( ' id ' )).markInvalid( this ._errors[ 0 ]);
10 }
11 }

 Ext.QuickTips.init();Ext.form.Field.prototype.msgTarget = 'side';Ext.form.Field.prototype.validationDelay = 0;Ext.form.Field.prototype.validateOnBlur = false;Ext.form.Field.prototype.validationEvent = 'keydown';Sys.Mvc.FieldContext.prototype._displayError = function () {    if (this._errors.length > 0) {        Ext.getCmp($(this.elements).attr('id')).markInvalid(this._errors[0]);    }}

到现在还完全不够,因为extjs的表单的是用Ext.form.FormPanel来构建的,而ASP.NET MVC只会在Html.EndForm()的时候为这个form进行表单域的验证信息的输出,这完全是不符合extjs的需求的。我们需要一种手段,不需要在Html.EndForm()的时候输出一段验证信息,而是指定为某个表单输出某个或者某几个视图模型的验证信息,那么extjs的FormPanel才能很好的工作。这需要额外的工作来为extjs以另外一种不同于ASP.NET MVC原生的模型验证元数据输出方式输出验证信息。下面是一个辅助类,有两个扩展方法
代码
 
   
1 /// <summary>
2 /// 输出验证信息的辅助类
3 /// </summary>
4 public static class ValidateHelper
5 {
6 private const string _clientValidationScript = @" <script type=""text/javascript"">
7 //<![CDATA[
8 if (!window.mvcClientValidationMetadata) {{ window.mvcClientValidationMetadata = []; }}
9 //]]>
10 </script> " ;
11 private const string _clientMetadatas = @" <script type=""text/javascript"">
12 //<![CDATA[
13 window.mvcClientValidationMetadata.push({0});
14 //]]>
15 </script> " ;
16 private const string _enableKey = " *&^enable*UY^ " ;
17 // 开启客户端验证
18 public static void EnableExtJsValidation( this HtmlHelper html)
19 {
20 var httpContext = HttpContext.Current;
21 if ( ! httpContext.Items.Contains(_enableKey))
22 {
23 httpContext.Items[_enableKey] = true ;
24 httpContext.Response.Write(_clientValidationScript);
25 }
26 }
27
28 /// <summary>
29 /// 向客户端输出模型验证元数据
30 /// </summary>
31 /// <param name="formId"> 需要进行验证的表单 </param>
32 /// <param name="modelTypes"> 提供元数据的视图模型的类型 </param>
33 public static void OutputClientValidationMetadata( this HtmlHelper html, string formId, params Type[] modelTypes)
34 {
35 if (HttpContext.Current.Items[_enableKey] != null &&
36 HttpContext.Current.Items[_enableKey] is bool &&
37 ( bool )HttpContext.Current.Items[_enableKey])
38 {
39
40 FormContext formContext = new FormContext {FormId = formId};
41 html.ViewContext.FormContext = formContext;
42 var dataAnnotationsModelMetadataProvider = new DataAnnotationsModelMetadataProvider();
43 foreach (var modelType in modelTypes)
44 {
45 var metadatas = dataAnnotationsModelMetadataProvider.GetMetadataForType( null , modelType);
46 foreach (var prop in metadatas.Properties)
47 {
48 var fieldMetadata = formContext.GetValidationMetadataForField(prop.PropertyName, true );
49 var validators = ModelValidatorProviders.Providers.GetValidators(prop, html.ViewContext);
50 foreach (
51 ModelClientValidationRule rule in validators.SelectMany(v => v.GetClientValidationRules()))
52 {
53 fieldMetadata.ValidationRules.Add(rule);
54 }
55 }
56 }
57
58 html.ViewContext.HttpContext.Response.Write( string .Format(_clientMetadatas,
59 formContext.GetJsonValidationMetadata()));
60 }
61 }
62 }


 public static class ValidateHelper{    private const string _clientValidationScript = @"<script type=""text/javascript"">//<![CDATA[if (!window.mvcClientValidationMetadata) {{ window.mvcClientValidationMetadata = []; }}//]]></script>";    private const string _clientMetadatas= @"<script type=""text/javascript"">//<![CDATA[window.mvcClientValidationMetadata.push({0});//]]></script>";    private const string _enableKey = "*&^enable*UY^";    //开启客户端验证    public static void EnableExtJsValidation(this HtmlHelper html)    {        var httpContext = HttpContext.Current;        if (!httpContext.Items.Contains(_enableKey))        {            httpContext.Items[_enableKey] = true;            httpContext.Response.Write(_clientValidationScript);        }    }    /// <summary>    /// 向客户端输出模型验证元数据    /// </summary>    /// <param name="formId">需要进行验证的表单</param>    /// <param name="modelTypes">提供元数据的视图模型的类型</param>    public static void OutputClientValidationMetadata(this HtmlHelper html, string formId, params Type[] modelTypes)    {        if (HttpContext.Current.Items[_enableKey] != null &&            HttpContext.Current.Items[_enableKey] is bool &&            (bool)HttpContext.Current.Items[_enableKey])        {            FormContext formContext = new FormContext {FormId = formId};            html.ViewContext.FormContext = formContext;            var dataAnnotationsModelMetadataProvider = new DataAnnotationsModelMetadataProvider();            foreach (var modelType in modelTypes)            {                var metadatas = dataAnnotationsModelMetadataProvider.GetMetadataForType(null, modelType);                foreach (var prop in metadatas.Properties)                {                    var fieldMetadata = formContext.GetValidationMetadataForField(prop.PropertyName, true);                    var validators = ModelValidatorProviders.Providers.GetValidators(prop, html.ViewContext);                    foreach (                        ModelClientValidationRule rule in validators.SelectMany(v => v.GetClientValidationRules()))                    {                        fieldMetadata.ValidationRules.Add(rule);                    }                }            }            html.ViewContext.HttpContext.Response.Write(string.Format(_clientMetadatas,                                                                        formContext.GetJsonValidationMetadata()));        }    }}

 

OK,一切工作就绪。下面是示例代码

extjs构建formPanel

代码
 
   
1 $( function () {
2 new Ext.form.FormPanel({
3 title: ' form1 ' ,
4 formId: ' form01 ' ,
5 items: [{
6 id: ' Name ' ,
7 fieldLabel: ' 姓名 ' ,
8 xtype: ' textfield '
9 }, {
10 id: ' Age ' ,
11 fieldLabel: ' 年龄 ' ,
12 xtype: ' textfield '
13 }],
14 renderTo: document.body
15 })
16 });

开启客户端验证

 
  
1 <%
2 Html.EnableExtJsValidation();
3 Html.OutputClientValidationMetadata( " form01 " , typeof(StudentModel));
4 %>

视图模型

代码
 
   
1 public class StudentModel
2 {
3 [Required]
4 [StringLength( 10 ,ErrorMessage = " 姓名的长度不能超过10个字符 " )]
5 public string Name { get ; set ; }
6 [RegularExpression( @" \d{1,3} " ,ErrorMessage = " 年龄必须是3位数字 " )]
7 public int Age { get ; set ; }
8 }

结果:

 

当然还有很多细节工作需要完善,例如form表单提交时的验证等(可能的话明天再补充)。上面只是一种解决的思路,采用它是因为微软的模型验证机制比较容易扩展,并且这样扩展不仅能应用于传统的ASP.NET MVC的开发同时也可以应用extjs同mvc的结合开发。

转载于:https://www.cnblogs.com/dickhead/archive/2010/11/14/1876776.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值