asp.net MVC学习系列-前后台数据校验

转载 http://blog.csdn.net/ydm19891101/article/details/43485253


Web页面,是一个数据进入的接口,对数据的合法性、正确性检测非常重要。做好表单数据验证工作可以防止那些攻击数据以及不合理数据。通过使用客户端和服务器端双重验证,可以保证表单数据的安全性。有时候客户端验证不是太安全的,可以设法绕开客户端验证,所以服务端验证也是需要的。但是为了减轻服务器的压力,还是尽量使用客户端验证。下面分别介绍MVC设计模式中如何实现两种验证。

一、客户端校验

客户端的校验有两种方式:jQuery方式、MVC方式

在讲校验之前先说明一个问题:VIew视图的创建必须是强类型的。

首先在Models文件夹下添加一个类,以Teacher类为例,具体代码:

[csharp]  view plain  copy
  1. public class Teacher  
  2. {  
  3.     public string Tno { setget; }  
  4.     public string Tname { setget; }  
  5.     public int Tsex { setget; }  
  6.     public string Taddress { setget; }  
  7.     public string Tphone { setget; }  
  8. }  
重新生成项目

新添加一个Teacher控制器,为该控制器添加一个Create的Action,添加对应于该Action的视图(选择Teacher强类型视图),默认为我们生成了以下代码

[csharp]  view plain  copy
  1. <% using (Html.BeginForm("Create""Teacher", FormMethod.Post, new { id = "frmAdd" }))//这段代码需要我们填写Url  
  2.    { %>  
  3.     <%: Html.ValidationSummary(true)%>  
  4.     <fieldset>  
  5.         <legend>Teacher</legend>  
  6.   
  7.         <div class="editor-label">//由于我们选择的是强类型视图,后台返回的数据都是Teacher实体类型即model实体  
  8.             <%: Html.LabelFor(model => model.Tno)%>//Tno与我们Teacher类的Tno属性是对应的  
  9.         </div>  
  10.         <div class="editor-field">  
  11.             <%: Html.EditorFor(model => model.Tno)%>  
  12.             <%: Html.ValidationMessageFor(model => model.Tno)%>  
  13.         </div>  
  14.   
  15.         <div class="editor-label">  
  16.             <%: Html.LabelFor(model => model.Tname)%>  
  17.         </div>  
  18.         <div class="editor-field">  
  19.             <%: Html.EditorFor(model => model.Tname)%>  
  20.             <%: Html.ValidationMessageFor(model => model.Tname)%>  
  21.         </div>  
  22.   
  23.         <div class="editor-label">  
  24.             <%: Html.LabelFor(model => model.Tsex)%>  
  25.         </div>  
  26.         <div class="editor-field">  
  27.             <%: Html.EditorFor(model => model.Tsex)%>  
  28.             <%: Html.ValidationMessageFor(model => model.Tsex)%>  
  29.         </div>  
  30.   
  31.         <div class="editor-label">  
  32.             <%: Html.LabelFor(model => model.Taddress)%>  
  33.         </div>  
  34.         <div class="editor-field">  
  35.             <%: Html.EditorFor(model => model.Taddress)%>  
  36.             <%: Html.ValidationMessageFor(model => model.Taddress)%>  
  37.         </div>  
  38.   
  39.         <div class="editor-label">  
  40.             <%: Html.LabelFor(model => model.Tphone)%>  
  41.         </div>  
  42.         <div class="editor-field">  
  43.             <%: Html.EditorFor(model => model.Tphone)%>  
  44.             <%: Html.ValidationMessageFor(model => model.Tphone)%>  
  45.         </div>  
  46.   
  47.         <p>  
  48.             <input type="submit" value="Create" />  
  49.         </p>  
  50.     </fieldset>  
  51. <% } %>  
  52.   
  53. <div>  
  54.     <%: Html.ActionLink("Back to List""Index") %>  
  55. </div>  

如果我们这个时候就运行程序,查看页面源代码时可以看到微软已经为我们自动添加了一些校验:

[html]  view plain  copy
  1. <div class="editor-field">  
  2.                 <input class="text-box single-line" id="Tphone" name="Tphone" type="text" value="">  
  3.                 <span class="field-validation-valid" data-valmsg-for="Tphone" data-valmsg-replace="true"></span>  
  4.             </div>  
我们在定义Teacher类时定义了Tphone属性为字符串类型,这样在我们输入时就通过class="field-validation-valid"限定了我们只能输入字符串。这种验证简单但是有一定局限性。下面就讲解我们自定义的两种验证方式。

1.jQuery验证方式

添加script脚本引用:

[html]  view plain  copy
  1. <script type="text/javascript" src="../../Scripts/jquery-1.4.4.js"></script>  
  2. <script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>     

添加jQuery进行数据验证

[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.        $(function () {  
  3.            $("#frmAdd").validate({  
  4.                rules: {  
  5.                    Tsex: {  
  6.                    required:true,  
  7.                    digits: true  
  8.                    }  
  9.                },  
  10.                messages: {  
  11.                    Tsex:"*必须输入0或者1"  
  12.                }  
  13.            });  
  14.        });  
  15.    </script>  
2.MVC验证方式
方式1:Model层校验

在Model层上实现这些验证规则的好处是,这将确保这些验证在应用中任何使用Teacher对象的场景中都被执行,这将帮助确保我们的代码DRY(Don't Repeat Yourself,不重复自己,意味着我们应该只在一处实施验证规则,然后使我们的控制器,Action方法和视图来遵守),避免在多处重复这些规则。MVC3允许开发人员轻松地在模型或视图模型类上添加声明式验证特性,然后在应用中实施模型绑定操作时,这些验证规则就会被自动执行。

添加script脚本引用:

[html]  view plain  copy
  1. <script type="text/javascript" src="../../Scripts/jquery-1.4.4.js"></script>  
  2. <script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>   
  3. <script src="../../Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>  

修改Teacher类代码

[csharp]  view plain  copy
  1. [StringLength(10, MinimumLength = 6)]  
  2. [Required(ErrorMessage = "工号为必填项")]  
  3. public string Tno { setget; }  
  4. [StringLength(10, MinimumLength = 2)]  
  5. [Required(ErrorMessage = "姓名为必填项")]  
  6. public string Tname { setget; }  
  7. [Range(0, 1)]  
  8. [Required(ErrorMessage = "性别为必填项")]  
  9. public int Tsex { setget; }  
  10. [StringLength(30, MinimumLength = 6)]  
  11. public string Taddress { setget; }  
  12. [RegularExpression(@"^\d+$", ErrorMessage = "*电话必须是数字")]  
  13. public string Tphone { setget; }  

运行程序,在加载页面之前,微软会先在程序集的元数据上添加以上的验证标签,加载页面时也会读取元数据,当发现元数据中存在验证标签时会为该标签添加上验证标签属性,具体代码如下所示:

[html]  view plain  copy
  1. <fieldset>  
  2.             <legend>Teacher</legend>  
  3.       
  4.             <div class="editor-label">  
  5.                 <label for="Tno">Tno</label>  
  6.             </div>  
  7.             <div class="editor-field">  
  8.                 <input class="text-box single-line" data-val="true" data-val-length="字段 Tno 必须是一个字符串,其最小长度为 6,最大长度为 10。" data-val-length-max="10" data-val-length-min="6" data-val-required="工号为必填项" id="Tno" name="Tno" type="text" value="">  
  9.                 <span class="field-validation-valid" data-valmsg-for="Tno" data-valmsg-replace="true"></span>  
  10.             </div>  
  11.       
  12.             <div class="editor-label">  
  13.                 <label for="Tname">Tname</label>  
  14.             </div>  
  15.             <div class="editor-field">  
  16.                 <input class="text-box single-line" data-val="true" data-val-length="字段 Tname 必须是一个字符串,其最小长度为 2,最大长度为 10。" data-val-required="姓名为必填项" id="Tname" name="Tname" type="text" value="">  
  17.                 <span class="field-validation-valid" data-valmsg-for="Tname" data-valmsg-replace="true"></span>  
  18.             </div>  
  19.       
  20.             <div class="editor-label">  
  21.                 <label for="Tsex">Tsex</label>  
  22.             </div>  
  23.             <div class="editor-field">  
  24.                 <input class="text-box single-line" data-val="true" data-val-number="The field Tsex must be a number." data-val-range="字段 Tsex 必须在 0 和 1 之间。" data-val-range-max="1" data-val-range-min="0" data-val-required="性别为必填项" id="Tsex" name="Tsex" type="text" value="">  
  25.                 <span class="field-validation-valid" data-valmsg-for="Tsex" data-valmsg-replace="true"></span>  
  26.             </div>  
  27.       
  28.             <div class="editor-label">  
  29.                 <label for="Taddress">Taddress</label>  
  30.             </div>  
  31.             <div class="editor-field">  
  32.                 <input class="text-box single-line" data-val="true" data-val-length="字段 Taddress 必须是一个字符串,其最小长度为 6,最大长度为 30。" data-val-length-max="30" data-val-length-min="6" id="Taddress" name="Taddress" type="text" value="">  
  33.                 <span class="field-validation-valid" data-valmsg-for="Taddress" data-valmsg-replace="true"></span>  
  34.             </div>  
  35.       
  36.             <div class="editor-label">  
  37.                 <label for="Tphone">Tphone</label>  
  38.             </div>  
  39.             <div class="editor-field">  
  40.                 <input class="text-box single-line" data-val="true" data-val-regex="*电话必须是数字" data-val-regex-pattern="^\d+$" id="Tphone" name="Tphone" type="text" value="">  
  41.                 <span class="field-validation-valid" data-valmsg-for="Tphone" data-valmsg-replace="true"></span>  
  42.             </div>  
  43.       
  44.             <p>  
  45.                 <input type="submit" value="Create">  
  46.             </p>  
  47.         </fieldset>  
Model层的校验方式比较简单,容易理解。Model层的数据校验主要有四种:必填项、正则匹配、限定范围、字符串长度,具体使用如上所示。

方式2:EF框架实体类校验

第二种实现方式与第一种差不多,也是在模型对应的实体类上添加上面的四种校验方式。但是,当我们根据模型更新实体的属性时,会造成之前添加的验证的丢失,这是我们不愿看到的。解决方法就是利用微软为我们提供的一种伙伴类技术,具体操作如下。

Teacher类代码还是用之前的

[csharp]  view plain  copy
  1. public class Teacher  
  2. {  
  3.     public string Tno { setget; }  
  4.     public string Tname { setget; }  
  5.     public int Tsex { setget; }  
  6.     public string Taddress { setget; }  
  7.     public string Tphone { setget; }  
  8. }  
在Models文件夹下添加TeacherExt类,修改其代码如下

[csharp]  view plain  copy
  1.     [MetadataType(typeof(TeacheExt))]//代表:Teacher要共享TeacherExt的元数据信息  
  2.     public partial class Teacher  
  3.     {  
  4.   
  5.   
  6.     }  
  7.     public class TeacheExt  
  8.     {    //元数据描述:   Tname属性有特性:StringLength  
  9.         [Required(ErrorMessage = "姓名为必填项")]  
  10.         [StringLength(20, ErrorMessage = "请限制输入字符串长度小于20")]  
  11.         public string Tname { setget; }  
  12.     }  

经过上面的操作,Teacher类的Tname具有了数据校验,并且当更新Teacher实体类的属性时,其Tname属性仍具有了数据校验特效。

当我们加载页面时微软也为我们的Tname标签添加了以下的标签属性

[html]  view plain  copy
  1. <input class="text-box single-line" data-val="true" data-val-length="请限制输入字符串长度小于20" data-val-length-max="20" data-val-required="姓名为必填项" id="Tname" name="Tname" type="text" value="">  

上面讲解了客户端的两种验证方式,客户端的校验只能保证用户的正确输入,并不能保证数据就一定能提交到数据库,这时候就需要后台校验了。

二、服务器端校验

MVC设计模式同样为我们提供了后台校验数据的方法,具体使用如下:

我们还是需要先在Teacher类添加一些验证特效,具体代码如下

[csharp]  view plain  copy
  1. [StringLength(10, MinimumLength = 6)]  
  2.       [Required(ErrorMessage = "工号为必填项")]  
  3.       public string Tno { setget; }  
  4.       [StringLength(10, MinimumLength = 2)]  
  5.       [Required(ErrorMessage = "姓名为必填项")]  
  6.       public string Tname { setget; }  
  7.       [Range(0, 1)]  
  8.       [Required(ErrorMessage = "性别为必填项")]  
  9.       public int Tsex { setget; }  
  10.       [StringLength(30, MinimumLength = 6)]  
  11.       public string Taddress { setget; }  
  12.       [RegularExpression(@"^\d+$", ErrorMessage = "*电话必须是数字")]  
  13.       public string Tphone { setget; }  
相应的修改Action方法的代码

[csharp]  view plain  copy
  1. public ActionResult Create(MvcLogin.Models.Teacher teacher)  
  2.       {  
  3.           if (ModelState.IsValid)  //校验成功  
  4.           {  
  5.               //执行数据的入库、更新等操作  
  6.           }  
  7.           else  
  8.           {  
  9.               //给出提示信息  
  10.           }  
  11.           return View(teacher);  
  12.       }  

在我们的HTML表单被提交回服务器时,上面的Create方法就会被调用。因为该Action方法接受一个“Teacher” 对象为参数,ASP.NET MVC会创建一个Teacher对象,自动地将进来的表单输入数值映射到该对象上。作为该过程的一部分,ASP.NET MVC还会检查该Teacher对象上的DataAnnotation验证特性是否合法。如果一切都合法,那么我们代码中的 ModelState.IsValid检查就会返回真值,在这种情形下,我们(最终)将把该Teacher对象保存到数据库中。但如果Teacher对象上有任何验证错误的话,我们的Action方法就会以该不合法Teacher对象的数据重新显示表单,这是通过上面代码片段中最后一行代码实现的。然 后,错误消息就会显示在我们的视图中,因为我们的Create表单在每一个<%= Html.TextBoxFor() %>辅助方法的调用旁边都有一个<%= Html.ValidationMessageFor() %>辅助方法调用。Html.ValidationMessageFor() 辅助方法会针对传入视图的任何不合法的模型属性输出合适的错误消息。

这个模式/方式有一个好处,就是非常容易配置,它还允许我们轻松地添加或改变我们Teacher类上的验证规则,而不必改变控制器或视图中的任何代码。这个在一个地方指定验证规则,然后在所有的地方都会被遵守的能力,允许我们快速地发展我们的应用和规则,并且将代码保持在非常DRY的程度。

MVC学习系列-了解Url的路由规则

MVC学习系列-HTML帮助器的使用

MVC学习系列-表单的异步提交

MVC学习系列-表单数据提交

MVC学习系列-ViewData与ViewBag


版权声明:本文为博主原创文章,未经博主允许不得转载。如果感觉文章哪里写的不对或者存在疑问,欢迎留言,共同学习、进步!



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值