zoukankan      html  css  js  c++  java
  • Asp.Net MVC 模型验证详解-实现客户端、服务端双重验证

    概要

             在asp.net webform开发中经常会对用户提交输入的信息进行校验,一般为了安全起见大家都会在客户端进行Javascript(利于交互)、服务端双重校验(安全)。书写校验代码是一个繁琐的过程。在Asp.Net MVC中就很好的解决了这一问题、利用模型的数据注解实现客户端与服务端双重校验,使你的开发效率大大提高。

    数据注解

             微软提供了很多数据注解的类(通俗点就是特性标签类),也为我们提供了自定义接口来满足开发人员不同的需求。下面一一为大家说明。

             命名空间:System.ComponentModel.DataAnnotations;

           程序集:System.ComponentModel.DataAnnotations;

    StringLength特性-限制长度

             这个特性看它命名规则就知道它是什么意思了,字符串长度对吧。是的你没看错,就是字符串长度。实例代码:

    [StringLength(20,ErrorMessage = "密码不能超过20个字符")]
    public string Password { get; set; }

    我们只需要在模型属性上加上这么个特性,那么校验的时候这个字符串不能超过20个字符。ErrorMessage就是校验不通过时的消息。

    Required特性-不能为空

             这个特性表必须的、不能为空的。用于不为空校验。默认为不允许为空。允许为空则添加AllowEmptyStrings = true

    [Required(ErrorMessage = "密码不能超过20个字符")]
    public string Password { get; set; }

    RegularExpression-规则校验(正则校验)

             正则表达式在校验中是必不可少的一部分、微软也为我们提供了这个类型,非常方便的使用。

    [RegularExpression(@"^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$", ErrorMessage = "邮箱不正确")]
    public string Email { get; set; }

    Range-数值范围

             当对一个数值进行校验时、一般可能会用到取值范围。比如年龄:

    [Range(0,120,ErrorMessage = "年龄取值范围0-120")]
    public int Age { set; get; }

    Compare-比较

             比较两个值是否一致,一般用于二次输入。Password是需要比较的值

    [Compare("Password",ErrorMessage = "两次输入不一致")]
    public string PasswordConfirm { get; set; }

    Remote-远程校验

             这个在登录的时候用的非常多。比如你的用户名ID是否已经被注册,这是需要从数据库查询之后才知道的。这个类有些特殊,它不在System.ComponentModel.DataAnnotations命名空间下,它是在System.Web.Mvc;命名空间下的。

    [Remote("CheckUserName","Register",ErrorMessage = "用户名已被注册")]
    public string UserName { get; set; }

    Action:代表你要请求的方法

    Controller:表示你要请求的控制器

    这个特性有一个约定,就是你请求的这个路径必须返回True或False,并且是以Json格式返回的。至于返回True或False的逻辑,看大家自己的需求了。

    public ActionResult CheckUserName()
    {
         return Json(false, JsonRequestBehavior.AllowGet);
    }

     

    Display-显示名称

             这个特性、个人认为不属于校验里面的一部分,它只是用户前台展示时的一个显示名称。后面在为大家讲解这个的实际应用

    [Display(Name = "年龄")]
     public int Age { set; get; }

    总结:

    通过以上五种模型注解,一般能满足生产中大部分校验,如有特殊校验,可以自定义特性来进行模型注解。了解了模型注解,也就是开始我们asp.net MVC校验的第一步了。自定义数据注解我就不说了,看下这个就可以了:

    http://www.cnblogs.com/zhangkai2237/archive/2012/12/12/2814825.html

    数据绑定及验证

    首先要进行客户端校验有几个比较重要的点:

    1、  必须要用@Html.BeginForm()这种方式包含住输入标签。(自己试验了下,是这样的。如果有错误请好心提醒)

    2、  必须要用强类型页面。

    3、  必须要引用Jquery库、Jquery.Validate、Jquery.Validate.unobtrusive这三个文件

    4、  web.config文件中这两个值必须为True。默认为True

    <appSettings>
        <add key="ClientValidationEnabled" value="true" />
        <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    </appSettings>

    前台代码:

    由于我时间问题、我创建视图的时候就直接创建了编辑视图了。

       <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
        
        @using (Html.BeginForm("Create","Register")) {
            @Html.ValidationSummary(true)
            <fieldset>
                <legend>RegisterViewModel</legend>
        
                <div class="editor-label">
                    @Html.LabelFor(model => model.UserName)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.UserName)
                    @Html.ValidationMessageFor(model => model.UserName)
                </div>
        
                <div class="editor-label">
                    @Html.LabelFor(model => model.Password)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Password)
                    @Html.ValidationMessageFor(model => model.Password)
                </div>
        
                <div class="editor-label">
                    @Html.LabelFor(model => model.PasswordConfirm)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.PasswordConfirm)
                    @Html.ValidationMessageFor(model => model.PasswordConfirm)
                </div>
        
                <div class="editor-label">
                    @Html.LabelFor(model => model.Phone)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Phone)
                    @Html.ValidationMessageFor(model => model.Phone)
                </div>
        
                <div class="editor-label">
                    @Html.LabelFor(model => model.Email)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Email)
                    @Html.ValidationMessageFor(model => model.Email)
                </div>
        
                <p>
                    <input type="submit" value="Save" />
                </p>
            </fieldset>
        }

    补充前面一个内容、在属性前加上Display特性,那么在前台@Html.LabelFor(model => model.Email)这种代码就会优先使用Display里面定义的名称,如果没有定义,则显示属性的名称(UserName)。

    后台代码:

    public class RegisterController : Controller
        {
            //
            // GET: /Register/
    
            public ActionResult Index()
            {
                if (ModelState.IsValid)
                {
                    //后台校验。判断所有数据是否建议通过、
                }
                return View();
            }
            
            public ActionResult CheckUserName()
            {
                return Json(false, JsonRequestBehavior.AllowGet);
            }
    
            [HttpPost]
            public ActionResult Create(RegisterViewModel model)
            {
                return View();
            }
        }

    使用Entity Framework模型

    在实际生产中我们用到的很有可能就是ORM框架,或者代码生成器生成的代码。为了避免每次重新生成后而将我们的数据注解给消失掉、微软也提供了一种叫元数据共享的一种方式(我叫它”元数据”共享)

        /// <summary>
        /// 验证类
        /// </summary>
        public class RegisterViewModel_Validate
        {
            [Display(Name = "用户名")]
            [Required(ErrorMessage = "不能为空",AllowEmptyStrings = false)]
            [Remote("CheckUserName","Register",ErrorMessage = "用户名已被注册")]
            public string UserName { get; set; }
    
            [Display(Name = "密码")]
            [Required(ErrorMessage = "密码不能超过20个字符")]
            public string Password { get; set; }
    
            [Display(Name = "确认密码")]
            [System.ComponentModel.DataAnnotations.Compare("Password",ErrorMessage = "两次输入不一致")]
            public string PasswordConfirm { get; set; }
    
            [Display(Name = "公司电话")]
            [Required(ErrorMessage = "公司电话不能为空")]
            [StringLength(20, ErrorMessage = "错误的公司电话")]
            [RegularExpression("^[0-9]+$", ErrorMessage = "公司电话不正确")]
            public string Phone { get; set; }
    
    
            [Required(ErrorMessage = "注册人邮箱不能为空")]
            [RegularExpression(@"^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$", ErrorMessage = "邮箱不正确")]
            public string Email { get; set; }
    
            [Display(Name = "年龄")]
            [Range(0,120,ErrorMessage = "年龄取值范围0-120")]
            public int Age { set; get; }
        }
        /// <summary>
        /// 自动生成的类
        /// </summary>
        [MetadataType(typeof(RegisterViewModel_Validate))]//该类共享RegisterViewModel_Validate元数据
        public partial class RegisterViewModel
        {
    
        }

    我来了看起来方便就将两个类放到了一个文件夹下面,在生产中你还是得分开他们,不然自动生产代码还是会覆盖我们写的验证代码。

    总结:

      想想应该算是比较完整的了。希望对一些还不太明白的朋友有所帮助,自己也重新加深了印象。从事MVC开发后,

    感觉开发起来确实比较Web Form Happy多了,asp.net MVC这种开发方式我非常喜欢,而且可操作性、灵活性更强。

    希望更多的朋友一起加入MVC的阵营吧。一起享受MVC 编码的乐趣.....

      还有不明白的朋友可以私密我。欢迎讨论

  • 相关阅读:
    A % B Problem
    封锁阳光大学
    数楼梯
    海滩防御
    修复公路
    四子连棋
    口袋的天空
    兔子数
    逆序对&求逆序对
    【模板】单源最短路径*
  • 原文地址:https://www.cnblogs.com/showstyle/p/3336369.html
Copyright © 2011-2022 走看看