zoukankan      html  css  js  c++  java
  • MVC之验证

    MVC之验证

    有时候我觉得,很多人将一个具体的技术细节写的那么复杂,我觉得没有必要,搞得很多人一头雾水的,你能教会别人用就成了,具体的细节可以去查MSDN什么的,套用爱因斯坦的名言:能在网上查到的就不要去记,用的时候拿过来就是。应用层面的东东,没必要深究,真正的核心已经被那些大胡子老外们搞定了,你要说你非想搞明白某个东东,那你可以把你的时间用在架构和管理上去,亦或是你也搞个编译器(搞swift语言的那家伙就是捯饬的这个)什么的,玩玩金融,甚至把把妹子都比你去研究一门最底层的技术细节强,我们常说面向抽象编程,说白了就是低层要依赖高层,所以还是研究点高端的东东对你以后有帮助!

    言归正传,MVC验证走起,不过只此一篇,希望能讲多少是多少吧!

    一、基于数据注解特性的验证

    SO EASY:

    A、你如果想用数据注解特性,那就必须要引入以下命名空间:using System.ComponentModel.DataAnnotations;

    可以注意到,这个命名空间不是以System.Web开头的,这也说明了它并不单单是为Web项目准备的,如何其它类型的项目都可以使用。

    例如:对于一个注册用的model,在其上面用特性验证

    复制代码
    using System.ComponentModel.DataAnnotations;
    namespace Ctrip.Models { public class Register { [Required(ErrorMessage="用户名必须填写")] [MinLength(6,ErrorMessage="用户名长度过短")] public String UserName { get; set; } [DataType(DataType.Password)] public String Password { get; set; } [DataType(DataType.Password)] [Compare("Password",ErrorMessage="密码要一致")] public String RptPassword { get; set; } public String Email { get; set; } public DateTime BirthDate { get; set; } }
    }
    复制代码

    注:错误消息还可以用占位符,体会一下好处在哪

    [Required(ErrorMessage=”Your {0} is required.”)]
    
    public string Name { get; set; }

    B、在view中用HtmlHelper的方法就可以实现客户端验证了(前提是要开启客户端验证)

    @Html.ValidationSummary()会输出所有验证错误, 一般放在Form头处
    @Html.ValidationMessageFor()是针对单个输入的验证

    大概就是下面的格式:

    复制代码
    @using (Html.BeginForm()) { 
        @Html.AntiForgeryToken() 
        @Html.ValidationSummary()
    
        <fieldset> 
            <legend>Registration Form</legend> 
            <ol> 
                <li> 
                    @Html.LabelFor(m => m.UserName) 
                    @Html.EditorFor(m => m.UserName) 
                    @Html.ValidationMessageFor(m => m.UserName) 
                </li> 
                <li> 
                    @Html.LabelFor(m => m.Password) 
                    @Html.EditorFor(m => m.Password) 
                    @Html.ValidationMessageFor(m => m.Password) 
                </li> 
                 <li> 
                    @Html.LabelFor(m => m.Email) 
                    @Html.TextBoxFor(m => m.Email) 
                    @Html.ValidationMessageFor(m => m.Email) 
                </li> 
                <li> 
                    @Html.LabelFor(m => m.BirthDate) 
                    @Html.EditorFor(m => m.BirthDate) 
                    @Html.ValidationMessageFor(m => m.BirthDate) 
                </li> 
                </ol> 
            <input type="submit" value="Register" /> 
        </fieldset> 
    }
    复制代码

    这个时候如果你不处理后端,只要客户端允许JS运行,就可以在客户端验证,而且是AJAX验证哦,不解释~

    备注:客户端验证在哪里开启与关闭呢?在web.config里边,true or false,你说了算!

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


    C、搞定后端验证

    有些人说在控制器里边写一个专门的Valid()方法验证,我说这不是作死的节奏啊,有肉还吃豆腐?呵呵,说的就是下面这个东东ModelState.IsValid

    复制代码
    [HttpPost] 
          public ActionResult Create(Register register) 
          { 
              if (ModelState.IsValid) 
              { 
       return RedirectToAction("Index", "Home"); 
              } 
              return View(register); 
          } 
    复制代码

    D、验证特性特别多,想要看的自己上网查,或者反编译上面的那个命名空间就可以看到!不过有两个特性比较特殊,是在System.Web.Mvc命名空间里边:
         RemoteAttribute和CompareAttribute,CompareAttribute的用法上面的A中已有,下面举个RemoteAttribute的例子,就是我们在网站注册的时候,要求用户名不能重复,可以用这个RemoteAttribute实现,是异步的~

    复制代码
    public class Employee
    {
          public int EmpId { get; set; }
          [DisplayName("Employee Name")]
          [Remote("IsEmployeeNameAvailable", "Validation")] //使用RemoteAttribute,指定验证的Controller和Action
          public String EmployeeName { get; set; }
    
    }
    复制代码

    然后你再写个Action就行了,由于比较简单这里就不再写了!
    警告:这个RemoteAttribute是只进行客户端验证的,服务器端不验证的,所以如果某个用户屏蔽了客户端js那就没用了

    注:正则表达式特性也很有用的,例如:

    [RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}”,ErrorMessage=”Email doesn’t look like a valid email address.”)]

    具体的正则表达式你可以上网搜~

    二、自定义数据注解特性验证

     

    先说说什么是双重验证?

    其实就是客户端验证加服务器端验证而已~

    为什么要双重验证?

    首先,客户端验证能够直接响应客户,减少了服务器压力的同时还提高了用户体验,但是你永远不能信任来自客户端的信息(用户可以关闭浏览器的脚本功能,让你的js验证彻底不起作用),所以服务器端验证也是必须的~

    常规验证可以通过上面列出的这些系统预定义ValidationAttribute特性来完成,但是在很多情况下我们需要通过创建自定义的ValidationAttribute特性来解决一些特殊的验证,而且这些自定义的特性在很多地方可以重用的!

    你需要做的就是重写ValidationAttribute里边的方法IsValid()而已

    举个栗子:

    复制代码
    using System.ComponentModel.DataAnnotations;
    using System.Text.RegularExpressions;
    
    namespace MvcValidation.Extension
    {
        public class EmailAttribute : ValidationAttribute
        {
            public const string reg = @"^[w-]+(.[w-]+)*@([w-]+.)+[a-zA-Z]+$";
    
            public EmailAttribute()
            {  
            }
    
            //重写基类方法
            public override bool IsValid(object value)
            {
                if (value == null)
                    return true;
    
                if (value is string)
                {
                    Regex regEx = new Regex(reg);
                    return regEx.IsMatch(value.ToString());
                }
                return false;
            }
        }
    }
    复制代码

    用的话,就是下面的样子:

    [Email]
     public string Email { get; set; }

    注意:
    此时的自定义的验证特性只支持后端验证,如果想支持前端jquery验证,还需要实现 IClientValidatable接口

    所以改写一下:

    复制代码
    using System.ComponentModel.DataAnnotations;
    using System.Text.RegularExpressions;
    using System.Web.Mvc;
    
    namespace MvcValidation.Extension
    {
        public sealed class EmailAttribute : ValidationAttribute, IClientValidatable
        {
            public const string reg = @"^[w-]+(.[w-]+)*@([w-]+.)+[a-zA-Z]+$";
    
            public EmailAttribute()
            {  
            }
    
            //重写基类方法
            public override bool IsValid(object value)
            {
                if (value == null)
                    return true;
    
                if (value is string)
                {
                    Regex regEx = new Regex(reg);
                    return regEx.IsMatch(value.ToString());
                }
                return false;
            }
    
            public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
            {
                ModelClientValidationRule rule = new ModelClientValidationRule
                {
                    ValidationType = "email",
                    ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
                };
                yield return rule;
            }
        }
    }
    复制代码

    注意:
    ValidationType属性的值一定要小写,否则报错。

    其实还没有结束呢,还要扩展JQuery函数(jQuery.validator.email.js文件)

    复制代码
    //扩展方法
    $.validator.addMethod("email", function (value, element) {
        if (value == false) {
            return true;
        }
        this.optional(element) || /^[w-]+(.[w-]+)*@([w-]+.)+[a-zA-Z]+$/i.test(value);
    });
    
    //扩展方法注册
    $.validator.unobtrusive.adapters.addBool("email");
    复制代码

    其实实现IClientValidatable之后,就是为前端的Email输入input标签添加了一个data-val-email属性而已,属性中的“email”就是ValidationType = "email"中的名字。

     

    三、带自我验证的模型 

    适用场景:不需要重用验证逻辑,只是针对某一个特定的模型进行验证。

    这些带自我验证的模型实现了接口IValidatableObject,该接口定义在“System.ComponentModel.DataAnnotations”命名空间下。

    public interface IValidatableObject
    {
        IEnumerable<ValidationResult> Validate(  ValidationContext validationContext);
    }

    举个栗子:

    复制代码
    public class Person: IValidatableObject
    {
        [DisplayName("姓名")]
        public string Name { get; set; }
        [DisplayName("性别")]
        public string Gender { get; set; }
        [DisplayName("年龄")]
        public int? Age { get; set; }
        public IEnumerable<ValidationResult> Validate( ValidationContext validationContext)
        {
            Person person = validationContext.ObjectInstance as Person;
            if (null == person)
            {
                yield break;
            }
            if(string.IsNullOrEmpty(person.Name))
            {
                yield return new ValidationResult("'Name'是必需字段", new string[]{"Name"});
            }
            if (string.IsNullOrEmpty(person.Gender))
            {
                yield return new ValidationResult("'Gender'是必需字段", new string[] { "Gender" });
            }
            else if (!new string[]{"M","F"}.Any( g=>string.Compare(person.Gender,g, true) == 0))
            {
                yield return new ValidationResult("有效'Gender'必须是'M','F'之一",   new string[] { "Gender" });
            }
            if (null == person.Age)
            {
                yield return new ValidationResult("'Age'是必需字段",    new string[] { "Age" });
            }
            else if (person.Age > 25 || person.Age < 18)
            {
                yield return new ValidationResult("'Age'必须在18到25周岁之间",    new string[] { "Age" });
            }            
        }
    }
    复制代码

    四、自定义验证的错误消息

    通过在自定义验证特性中重写FormatErrorMessage方法来实现:

    复制代码
    using System.ComponentModel.DataAnnotations;
    using System.Text.RegularExpressions;
    using System.Web.Mvc;
    
    namespace MvcValidation.Extension
    {
        public sealed class EmailAttribute : ValidationAttribute, IClientValidatable
        {
            public const string reg = @"^[w-]+(.[w-]+)*@([w-]+.)+[a-zA-Z]+$";
    
            public EmailAttribute()
            {  
            }
    
            //重写基类方法
            public override bool IsValid(object value)
            {
                if (value == null)
                    return true;
    
                if (value is string)
                {
                    Regex regEx = new Regex(reg);
                    return regEx.IsMatch(value.ToString());
                }
                return false;
            }
    
            public System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
            {
                ModelClientValidationRule rule = new ModelClientValidationRule
                {
                    ValidationType = "email",
                    ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
                };
                yield return rule;
            }
    /// <summary>        
    /// 格式化错误信息        
    /// </summary>        
    /// <param name="name">属性名</param>        
    /// <returns></returns>        
            public override string FormatErrorMessage(string name)        
    { return this.ErrorMessage ?? string.Format("{0}属性没有输入正确的Email", name);
    } } }
    复制代码

     最后,有一些验证还可以用JQuery实现,基本上属于js的东东,这里不再陈述~

    本人对MVC验证也只是略懂一二,所以就写这么多吧~

  • 相关阅读:
    chart控件多个ChartArea
    winform chart画折线,波形图,多条数据
    C# Chart 折线图 多条数据展示
    task一个任务结束后执行另一个操作
    C#多线程同步 读写锁ReaderWriterLock的用法
    C# 多线程文件读写整理总结
    vue解决跨域问题
    接前端页面
    使用vue+zrender绘制体温单 三测单(2)
    使用vue+zrender绘制体温单 三测单(1)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3822254.html
Copyright © 2011-2022 走看看