现在看asp.net MVC5自学已经到了第六章:数据注解与验证。

话得从以前看MVC music store(音乐商店项目)的源码说起,

最初看music store源码完全就是一脸懵逼,整个程序,找了半天,只看到控制器有少许逻辑代码,例如编辑专辑的视图里面,用户输入的title到底符不符合规范, VIEW里面即无相关验证的JS代码,又没有进行后台的数据判断。

 @using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Album</legend> @Html.HiddenFor(model => model.AlbumId) <div class="editor-label">
@Html.LabelFor(model => model.GenreId, "Genre")
</div>
<div class="editor-field">
@Html.DropDownList("GenreId", String.Empty)
@Html.ValidationMessageFor(model => model.GenreId)
</div> <div class="editor-label">
@Html.LabelFor(model => model.ArtistId, "Artist")
</div>
<div class="editor-field">
@Html.DropDownList("ArtistId", String.Empty)
@Html.ValidationMessageFor(model => model.ArtistId)
</div> <div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div> <div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div> <div class="editor-label">
@Html.LabelFor(model => model.AlbumArtUrl)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.AlbumArtUrl)
@Html.ValidationMessageFor(model => model.AlbumArtUrl)
</div> <p>
<input type="submit" value="Save" />
</p>
</fieldset>
}

音乐商店编辑专辑的视图

程序到底是怎么完成数据验证呢?

今天看了这一章对数据验证就有了大概的了解了。

===========================================================

前提:C# Attribute特性和反射

  翻到专辑的Model(实体类)里,我们看到Album类的定义是这样的。

public class Album
{
[ScaffoldColumn(false)]
public int AlbumId { get; set; } [DisplayName("Genre")]
public int GenreId { get; set; } [DisplayName("Artist")]
public int ArtistId { get; set; } [Required(ErrorMessage = "An Album Title is required")]
[StringLength()]
public string Title { get; set; } [Required(ErrorMessage = "Price is required")]
[Range(0.01, 100.00,
ErrorMessage = "Price must be between 0.01 and 100.00")]
public decimal Price { get; set; } [DisplayName("Album Art URL")]
[StringLength()]
public string AlbumArtUrl { get; set; } public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
public virtual List<OrderDetail> OrderDetails { get; set; }

  原来,模型类里面大量采用attribute特性

  关于Attribute特性我原先一直没有搞懂它到底是怎么运作的。写个方括号,括起来一个类,为什么就能让我的属性、方法、类有了限制?

  下面我首先简介一下Attribute特性的一些基本要点:

    1、特性类其实就是一个从Attribute基类继承而来的类。

    2、自定义Attribute只能在反射时生效。

  等等,第二个基本要点中:反射。它的定义就是反射指程序可以访问、检测和修改它本身状态或行为的一种能力。

  这也就是说,利用反射,我们可以得到一个类里面所有的特性。似乎我可以猜测到一点特性的运行原理了:我们可以在特性类中做文章,在反射时,获取了被标注的类的所有特性,运行这个这些特性的某些方法或者属性,就可以对这个被标注的类进行验证或者限制。

  

验证的运行原理:利用特性来进行验证。

  

 [StringLength()]
public string Title { get; set; }

  在上面一个属性中,有一个StringLengt(160)的特性,MVC书上称他为验证。

  // 摘要:
// 指定数据字段中允许的最小和最大字符长度。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public class StringLengthAttribute : ValidationAttribute
{
// 摘要:
// 使用指定的最大长度初始化 System.ComponentModel.DataAnnotations.StringLengthAttribute
// 类的新实例。
//
// 参数:
// maximumLength:
// 字符串的最大长度。
public StringLengthAttribute(int maximumLength); // 摘要:
// 获取或设置字符串的最大长度。
//
// 返回结果:
// 字符串的最大长度。
public int MaximumLength { get; }
//
// 摘要:
// 获取或设置字符串的最小长度。
//
// 返回结果:
// 字符串的最小长度。
public int MinimumLength { get; set; } // 摘要:
// 对指定的错误消息应用格式设置。
//
// 参数:
// name:
// 要进行格式设置的错误消息。
//
// 返回结果:
// 带有格式的错误消息。
//
// 异常:
// System.ArgumentOutOfRangeException:
// maximumLength 为负数。- 或 -maximumLength 小于 minimumLength。
public override string FormatErrorMessage(string name);
//
// 摘要:
// 确定指定的对象是否有效。
//
// 参数:
// value:
// 要验证的对象。
//
// 返回结果:
// 如果指定的对象有效,则为 true;否则为 false。
//
// 异常:
// System.ArgumentOutOfRangeException:
// maximumLength 为负数。- 或 -maximumLength 小于 System.ComponentModel.DataAnnotations.StringLengthAttribute.MinimumLength。
public override bool IsValid(object value);
}

  翻开它的元数据我们可以看到,它其实就是一个微软提供的自定义特性它继承自ValidationAttribute,ValidationAttribute又继承自Attribute

  通过元数据我们可以看到,它其中有一个重写的bool IsVlid(object value) 方法,它就是用来判断被标注的对象是否验证成功的入口。

  实际上,翻开ValidationAttribute的元数据,IsValid方法提供了很多重载版,验证特性要成功,最少都要重写一个方法,在方法里进行逻辑判断,确定是否验证成功。

==========================================================================================

MVC特性验证的原理

  以下是书上的解释:

  1、asp.net mvc框架可以自动绑定模型,如果控制器带了参数,MVC运行时会隐式地根据参数类型的标识符,从GET或者POST来的键值对里面找相同名字的键填充值。当然,控制器不带参数,也可以通过tryupdatemodel,或者updatemodel两个方法来完成模型绑定。

  2、在模型绑定之后,下一步就是反射被绑定后的模型,反射获取这个模型对象的验证特性,也就是例如[StringLength(160)]这些特性。

  3、得到所有验证特性之后,就调用这些验证特性类的isvalid方法,对被绑定属性进行验证。

  4、MVC运行时会捕捉所有isvalid方法返回值为false的验证规则,并把他们加入到ModelState中。

  5、如果ModelState中有任何一个验证的失败信息,ModelState的isValid属性都将设定为False。

  6、在前端视图中,我们就可以调用一个辅助方法: @Html.ValidationMessageFor(model => model.GenreId),去ModelState中找这个错误,辅助方法会自动根据ModelState中的错误信息拼装包含你传入的数据抛出的验证错误的HTML。

  如此一来,通过这6个步骤,仅仅依靠特性就能对数据进行验证。大大地提高了编码效率,减少了编码量

 

2017年2月28日-----------乱码新手自学.net 之特性与验证的更多相关文章

  1. 2017年2月22日-----------乱码新手自学.net 之Entity Framework 增删改

    由于我是自学的,没有人教,在网上查资料也查不到个所以然.问大神们也是爱理不理的. 所以这篇随笔纯粹源自于我自己的认识.是否真正正确我也没有把握. 如果有什么错误,请大神们给予指正 ========== ...

  2. 2017年2月16日-----------乱码新手自学.net 之MVC模型

    第二篇博文,最近学习的内容还是回到了正题:ASP.NET MVC5之上.虽然EF学了个一知半解,但是用这点知识,看MVC5的MODEL部分应该还是够了.尽管周末还要恶补一下EF才行. (一)MVC简述 ...

  3. 2017年3月14日-----------乱码新手自学.net 之Authorize特性与Forms身份验证(登陆验证、授权小实例)

    有段时间没写博客了,最近工作比较忙,能敲代码的时间也不多. 我一直有一个想法,想给单位免费做点小软件,一切思路都想好了,但是卡在一个非常基础的问题上:登陆与授权. 为此,我看了很多关于微软提供的Ide ...

  4. 2017年8月28日 HTML/CSS 语法(待填坑)

    今天这种节日真的是 ----------------------------------------------------------- HTML  

  5. 2017年4月28日16:40:40 log

    //TODO order  CreateOrderServiceHandler  generateManagementCustomer 子活动名称和uid

  6. 2017年3月28日15:59:16 终于明白spring这套鬼东西是怎么玩的了

    先说重点,新东家公司的项目框架没有一样是我之前用过的,首先pm和我说的是一套微服务的概念,微服务不同于传统的功能模块实现,他将服务松散化分不到各个系统之间,这样也是实现分散压力的一种. 微服务是由sp ...

  7. 2017年11月28日 C#进程和线程

    进程 需要放using System.Diagnostics;才可以用进程 用时的方法名为Process 用两个按钮一个为选择文件夹一个为打开可以打开系统内的进程. 注意:打开时一定要用进程名 Pro ...

  8. 2017年6月28日 python爬虫学习

    1.写入csv文件2.lxml的用法3.自定义字典类的方法4.bytes解码得到str,str编码得到bytes5.json 1 import csv import lxml.html class S ...

  9. 2017年1月2日 星期一 --出埃及记 Exodus 21:28

    2017年1月2日 星期一 --出埃及记 Exodus 21:28 "If a bull gores a man or a woman to death, the bull must be ...

随机推荐

  1. CodeForces - 1005E2:Median on Segments (General Case Edition) (函数的思想)

    You are given an integer sequence a1,a2,…,ana1,a2,…,an. Find the number of pairs of indices (l,r)(l, ...

  2. 【Lintcode】095.Validate Binary Search Tree

    题目: Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is define ...

  3. 解决Response输出时乱码

    Response ServletResponse – 通用的response提供了一个响应应该具有的最基本的属性和方法 | |- HttpServletResponse – 在ServletRespo ...

  4. CentOS虚拟机通过主机WIFI上网

    0 环境简介 环境如下: (1)宿主机为WIN7系统,连接内网,同时通过本机的WIFI上外网: (2)虚拟机为VMWare12下的CentOS7系统. 1 虚拟机设置 选择NAT 模式: 2 宿主机W ...

  5. XJar: Spring-Boot JAR 包加/解密工具,避免源码泄露以及反编译

    XJar: Spring-Boot JAR 包加/解密工具,避免源码泄露以及反编译 <?xml version="1.0" encoding="UTF-8" ...

  6. codec can't decode byte 0xe6 in position 0: ordinal not in range

    ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)] 错误: 实例 "linux-cor ...

  7. 如何解决 Matlab 画图时中文显示乱码的问题?

    使用的是win10系统,从前几个月某一天,我的matlab的figure里的中文都变成了口口.很是郁闷,还以为是动到了什么配置引起的. 前几天更新了matlab 2018b,发现还有这个问题.就觉得不 ...

  8. c/c++语言实现tesseract ocr引擎编程实例

    编译下面的程序操作系统必须在安装了tesseract库和leptonica库才可以 Basic example c++ code: #include <tesseract/baseapi.h&g ...

  9. 给出每个员工每年薪水涨幅超过5000的员工编号emp_no、薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列。

    题目描述 给出每个员工每年薪水涨幅超过5000的员工编号emp_no.薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列. 提示:在s ...

  10. codevs 1086 栈(Catalan数)

    题目描述 Description 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). ...