只要一直走,慢点又何妨。

在使用MVC模式进行开发时,数据注解是经常使用的(模型之上操作),下面是我看书整理的一些常见的用法。

什么是验证,数据注解

验证

从全局来看,发现逻辑仅是整个验证的很小的一部分。验证首先需要管理用户友好(本地化)的与验证逻辑相关的错误提示消息;当验证失败时,在把这些错误提示消息呈现给用户界面上,当然还要向用户提供从验证失败中恢复的机制。

数据注解

注解是一种通用机制,可以用来向框架注入元数据,同时,框架不只驱动元数据的验证,还可以在生成显示和编辑模型的HTML标记时使用元数据。通俗的说就是模型上面的特定标识符(具有一定意义和作用)。

验证注解的使用

数据注解定义在一般在命名空间”System.ComponentModel.DataAnnotations”提供了服务器端验证的功能,在模型属性上使用时,框架也支持客户端验证。注解后面都是可以添加错误提示语的,ErrorMessage是每个验证特性中用来设置错误提示消息的参数,比如:

  1. [Required(ErrorMessage = "不能为空")]
  2. public int Age { get; set; }
  • Required

强调属性是必须的,不可为空。当属性中有一个是null或空时,会引发一个验证错误。

  1. [Required]
  2. public int Age { get; set; }
  • StringLength

要求必须输入名字的长度。参数可以限制最小的。如下:

  1. [StringLength(160,MinimumLength = 3)]
  2. public string Name { get; set; }
  • RegularExpression

正则表达式验证,比如邮箱等需要验证正则的地方。很是方便,这样就减少了服务端的验证。

  1. [RegularExpression(@"^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+",ErrorMessage = "邮箱输入有误,重新输入。")]
  2. public string Email { get; set; }
  • Range

用来指定数值类型值得最小值和最大值。主要为int类型服务。其余的也可以,需要使用构造函数的重载版本。Type参数来做。

  1. [Range(20,30,ErrorMessage = "年龄不符合要求")]
  2. public int Age { get; set; }

  1. [Range(typeof(decimal),"0.00","59.99")]
  2. public decimal Price { get; set; }

  • Compare

确定两个模型属性拥有一样的值。密码的验证(输入两次,看二者是否一样。),参数为前面模型的值。

  1. [Required(ErrorMessage = "密码不能为空")]
  2. public string Password { get; set; }
  3. [Compare("Password")]
  4. public string PasswordPalt { get; set; }
  • Remote

此特性利用服务器端的回调函数执行客户端的验证逻辑。通俗的说就是这个特性可以直接找到某个控制器的action并且执行其中的方法。


  1. /// <summary>
  2. /// 验证模型中输入的姓名是否和数据库中重复
  3. /// </summary>
  4. /// <returns></returns>
  5. public JsonResult CheckUserName(string username)
  6. {
  1. //数据库中的相关验证
  2. return Json(DateTime.Now.ToString(),JsonRequestBehavior.AllowGet);
  3. }

  1. [Remote("CheckUserName", "Admin")]
  2. public string UserName { get; set; }

上面控制器操作会利用与UserName属性同名的参数进行验证,同时返回一个javascript object Notaion(json)对象中的布尔类型值(0/1)

  • 自定义回复消息占位符

使用{0}占位符,来显示用户的输入,并且形成友好提示。

  1. [Range(20,30,ErrorMessage = "年龄{0}不符合要求")]
  2. public int Age { get; set; }

服务端的一些处理(验证与绑定)

ASP.NET MVC的验证特性是由模型绑定器,模型元数据,模型验证器和模型状态组成。

验证和模型绑定

  • 操作方法中添加参数

这里有一个隐式地执行模型绑定,一般我们都需要这样写,这样也安全,不会说暴露出来参数。

  • 利用UpdateModel或TryUpdateModel方法显式执行绑定

这个实际项目中使用的很少,一般都是通过隐式进行转换的。


  1. [HttpPost,ActionName("Create")]
  2. public ActionResult CreatePost(Student model)
  3. {
  4. var model2 = new Student();
  5. UpdateModel(model2);
  6. if (TryUpdateModel(model2))
  7. {
  8.  
  9. }
  10. return View(model);
  11. }

可以看到参数中的为隐式转换,里面的model2为显式转换。if中的返回的是bool类型。模型绑定器一旦使用新值完成对模型属性的更新,就会利用当前的 模型元数据获得模型的所有验证器。MVC运行时提供了一个验证器(DataAnnotationsModelValidator)来与数据注解一同工作,这个模型验证器会找到所有的验证特性并执行它们包含的验证逻辑,模型绑定器捕获所有失败的验证规则并把它们放入模型状态中。

编程的一个重要原则是不能相信用户的输入

验证与模型状态

模型绑定的副产品是模型状态,也就是我们服务端验证的ModelState,此状态中不仅包含用户的输入,也含有每个相关属性的所有错误(与模型状态本身有关的错误),有错误,ModelState.IsValid就返回false。从而我们就可以进行验证。

  1. public ActionResult CreatePost(Student model)
  2. {
  3. var s=ModelState.IsValidField("UserName");
  4. var ss=ModelState["UserName"].Errors.Count;
  5. var userName = ModelState["UserName"].Errors[0].ErrorMessage; //获取错误消息
  6. if (ModelState.IsValid) //返回bool类型
  7. {
  8. }
  9. return View(model);
  10. }

显示和编辑注解

  • Display

显示模型属性设置友好的“显示名称”

  1. [Display(Name = "姓名")]
  2. [StringLength(160,MinimumLength = 3)]
  3. public string Name { get; set; }
  • ScaffoldColumn

可以隐藏HTML的辅助方法

  1. [ScaffoldColumn(false)]
  2. public string Address { get; set; }
  • DisplayFormat

处理属性各种格式化选项,当属性包含空值,可以提供可选的显示文本。也可以为包含标记的属性关闭HTML编码。还可以运行时指定一个应用于属性值的格式化字符串。

  1. [DisplayFormat(ApplyFormatInEditMode = true,DataFormatString = "{0:c}")]
  2. public decimal Total { get; set; }
  • ReadOnly

可以确保默认的模型绑定器不使用请求中的新值来更新属性。

  • DataType

运行时提供关于属性的特定用途信息。String类型的属性可应用于很多场合--可以保存e-mail地址,URL或密码。

  1. [Required(ErrorMessage = "密码不能为空")]
  2. [DataType(DataType.Password)]
  3. public string Password { get; set; }

  • UIHint

给运行时提供一个模版名称,以备调用模版辅助方法渲染输出时使用。

自定义验证逻辑

  1. 将验证逻辑封装在自定义的数据注解中。
  2. 将验证逻辑封装在模型对象中。

把验证逻辑封装在自定义的数据注解中可以轻松地实现在多个模型中重用逻辑。需要在特性内部编写代码以应对不同类型的模型中。

自定义注解

所有的验证注解特性最终都派生自基类ValidationAttribute,它是个抽象类,在System.ComponentMode.DataAnnotation中定义。同样自定义的验证逻辑必须派生自ValidationAttribute的类。且重写IsValid方法(方法里面实现我们相应的逻辑)。

需求:限制用户输入地址中单词数量,设定一个最大值。

  1. /// <summary>
  2. /// 自定义模型验证
  3. /// 输入数字的单词最大数量
  4. /// </summary>
  5. public class MaxWordsAttribute:ValidationAttribute
  6. {
  7. private readonly int _maxWord;
  8. public MaxWordsAttribute(int maxWord)
  9. {
  10. _maxWord = maxWord;
  11. }
  12. protected override ValidationResult IsValid(object value,ValidationContext validationContext)
  13. {
  14. if (value!=null)
  15. {
  16. //将输入转换为string类型
  17. var valueAsString = value.ToString();
  18. //使用split(' ')空格来分隔输入值,统计生成字符串的数量。对数目比较验证。
  19. if (valueAsString.Split(' ').Length>_maxWord)
  20. {
  21. return new ValidationResult("单词超过长度"); //string类型
  22. }
  23. }
  24. return ValidationResult.Success; //bool类型
  25. }
  26. }

第一个参数要验证对象中的值。后面进行逻辑的判断。这样做这里的错误提示不能显示到前台。我们需要修改下,使用ValidationAttrubute的ErrorMessage属性来自定义提示错误消息。

修改之后


  1. public class MaxWordsAttribute:ValidationAttribute
  2. {
  3. private readonly int _maxWord;
  4. public MaxWordsAttribute(int maxWord)
  5. :base("{0} has too many words")
  6. {
  7. _maxWord = maxWord;
  8. }
  9. protected override ValidationResult IsValid(object value,ValidationContext validationContext)
  10. {
  11. if (value!=null)
  12. {
  13. //将输入转换为string类型
  14. var valueAsString = value.ToString();
  15. //使用split(' ')空格来分隔输入值,统计生成字符串的数量。对数目比较验证。
  16. if (valueAsString.Split(' ').Length>_maxWord)
  17. {
  18. var errorMessage = FormatErrorMessage(validationContext.DisplayName);
  19. return new ValidationResult(errorMessage);
  20. }
  21. }
  22. return ValidationResult.Success; //bool类型
  23. }
  24. }

  1. [MaxWords(5)]
  2. public string Address { get; set; }

这样效果就会将我们基类中的错误信息显示出来。

我们可以模型基础上添加自定义错误显示。

  1. [MaxWords(5,ErrorMessage = "你输入的单词数超界限,请重新输入。")]
  2. public string Address { get; set; }

这里需要注意这里的执行顺序,它是先执行模型上面的验证,接着在到控制器中的action中去的。利用ModelState.IsValid来进行验证。

自验证模型(IValidatableObject)

自验证模型是指一个知道如何验证自身的模型对象,可以让类实现IVaalidatableObject接口来实现对自身的验证。

  1. public class Information:IValidatableObject
  2. {
  3. public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
  4. {
  5. if (UserName!=null&&UserName.Split(' ').Length>5)
  6. {
  7. yield return new ValidationResult("单词超界限了");
  8. }
  9. }
  10. [Display(Name = "用户名")]
  11. public string UserName { get; set; }
  12. }


其实书上面是在错误返回值中返回的是string类型的数组,如下

  1. yield return new ValidationResult("单词超界限了",new []{"UserName"});

可以我不知道从那里取出来这个错误消息。只能单独的显示出来。其实把错误消息放在数组中可以进行多模型的验证,从而统一将错误显示出来。

自己的感觉要是需要模型验证,最好还是进行第一种方法,最起码代码看起来干净,第二种给人的感觉是很乱,但是第二种适合比较模型多的场合。

我就是我,颜色不一样的烟火。

ASP.NET MVC5----常见的数据注解和验证的更多相关文章

  1. asp.net mvc常用的数据注解和验证以及entity framework数据映射

    终于有时间整理一下asp.net mvc 和 entity framework 方面的素材了. 闲话少说,步入正题: 下面是model层的管理员信息表,也是大伙比较常用到的,看看下面的代码大伙应该不会 ...

  2. ASP.NET MVC5中的数据注解

    ASP.NET MVC5中Model层开发,使用的数据注解有三个作用: 数据映射(把Model层的类用EntityFramework映射成对应的表) 数据验证(在服务器端和客户端验证数据的有效性) 数 ...

  3. ASP.NET MVC5中的数据注解(转载)

    ASP.NET MVC5中Model层开发,使用的数据注解有三个作用: 数据映射(把Model层的类用EntityFramework映射成对应的表) 数据验证(在服务器端和客户端验证数据的有效性) 数 ...

  4. 【ASP.NET MVC系列】浅谈数据注解和验证

    [ASP.NET MVC系列]浅谈数据注解和验证   [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google C ...

  5. MVC5 数据注解和验证

    ①利用数据注解进行验证 ②创建自定义的验证逻辑 ③模型元数据注解的用法 ①先创建数据源 1,创建我们的Model  Order 2,创建控制器带EF 选择模型为Order 当你运行的时候会报错,需要代 ...

  6. MVC学习手册之数据注解与验证

    MVC学习手册之数据注解与验证 新建一个MVC5的WEB应用程序,VS2013会自动生成一段代码,以下是Account控制器下Register.cshtml 页面的代码: @model WebAppl ...

  7. [Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则

    目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...

  8. MVC中的数据注解和验证

    数据注解和验证 用户输入验证在客户端浏览器中需要执行验证逻辑. 在客户端也需要执行. 注解是一种通用机制, 可以用来向框架注入元数据, 同时, 框架不只驱动元数据的验证, 还可以在生成显示和编辑模型的 ...

  9. ASP.NET MVC5(四):数据注解和验证

    前言 用户输入验证的工作,不仅要在客户端浏览器中执行,还要在服务端执行.主要原因是客户端验证会对输入数据给出即时反馈,提高用户体验:服务器端验证,主要是因为不能完全信任用户提供的数据.ASP.NET ...

随机推荐

  1. JS里面Data日期格式转换

    var format = function(time, format){     var t = new Date(time);     var tf = function(i){return (i  ...

  2. C#多线程之线程池篇2

    在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...

  3. iOS逆向工程之KeyChain与Snoop-it

    今天博客的主题是Keychain, 在本篇博客中会通过一个登陆的Demo将用户名密码存入到KeyChain中,并且查看一下KeyChain中存的是什么东西,把这些内容给导出来.当然本篇博客的重点不是如 ...

  4. 代码的坏味道(17)——夸夸其谈未来性(Speculative Generality)

    坏味道--夸夸其谈未来性(Speculative Generality) 特征 存在未被使用的类.函数.字段或参数. 问题原因 有时,代码仅仅为了支持未来的特性而产生,然而却一直未实现.结果,代码变得 ...

  5. Java 中获取类路径 classpath 的方法

    System.out.println("++++++++++++++++++++++++"); String path = System.getProperty("jav ...

  6. 【repost】JS中的异常处理方法分享

    我们在编写js过程中,难免会遇到一些代码错误问题,需要找出来,有些时候怕因为js问题导致用户体验差,这里给出一些解决方法 js容错语句,就是js出错也不提示错误(防止浏览器右下角有个黄色的三角符号,要 ...

  7. Flume1 初识Flume和虚拟机搭建Flume环境

    前言:       工作中需要同步日志到hdfs,以前是找运维用rsync做同步,现在一般是用flume同步数据到hdfs.以前为了工作简单看个flume的一些东西,今天下午有时间自己利用虚拟机搭建了 ...

  8. Nodejs之MEAN栈开发(七)---- 用Angular创建单页应用(下)

    上一节我们走通了基本的SPA基础结构,这一节会更彻底的将后端的视图.路由.控制器全部移到前端.篇幅比较长,主要分页面改造.使用AngularUI两大部分以及一些优化路由.使用Angular的其他指令的 ...

  9. [免费了] SailingEase .NET Resources Tool (.NET 多语言资源编辑器)

    这是我2010年左右,写 Winform IDE (http://www.cnblogs.com/sheng_chao/p/4387249.html)项目时延伸出的一个小项目. 最初是以共享软件的形式 ...

  10. CSharpGL(17)重构CSharpGL

    CSharpGL(17)重构CSharpGL CSharpGL用起来我自己都觉得繁琐了,这是到了重构的时候. 下载 CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https ...