2017年2月28日-----------乱码新手自学.net 之特性与验证

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

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

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

 1 @using (Html.BeginForm()) {
 2     @Html.ValidationSummary(true)
 3     <fieldset>
 4         <legend>Album</legend>
 5
 6         @Html.HiddenFor(model => model.AlbumId)
 7
 8         <div class="editor-label">
 9             @Html.LabelFor(model => model.GenreId, "Genre")
10         </div>
11         <div class="editor-field">
12             @Html.DropDownList("GenreId", String.Empty)
13             @Html.ValidationMessageFor(model => model.GenreId)
14         </div>
15
16         <div class="editor-label">
17             @Html.LabelFor(model => model.ArtistId, "Artist")
18         </div>
19         <div class="editor-field">
20             @Html.DropDownList("ArtistId", String.Empty)
21             @Html.ValidationMessageFor(model => model.ArtistId)
22         </div>
23
24         <div class="editor-label">
25             @Html.LabelFor(model => model.Title)
26         </div>
27         <div class="editor-field">
28             @Html.EditorFor(model => model.Title)
29             @Html.ValidationMessageFor(model => model.Title)
30         </div>
31
32         <div class="editor-label">
33             @Html.LabelFor(model => model.Price)
34         </div>
35         <div class="editor-field">
36             @Html.EditorFor(model => model.Price)
37             @Html.ValidationMessageFor(model => model.Price)
38         </div>
39
40         <div class="editor-label">
41             @Html.LabelFor(model => model.AlbumArtUrl)
42         </div>
43         <div class="editor-field">
44             @Html.EditorFor(model => model.AlbumArtUrl)
45             @Html.ValidationMessageFor(model => model.AlbumArtUrl)
46         </div>
47
48         <p>
49             <input type="submit" value="Save" />
50         </p>
51     </fieldset>
52 }

音乐商店编辑专辑的视图

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

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

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

前提: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(160)]
        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(1024)]
        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(160)]
        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个步骤,仅仅依靠特性就能对数据进行验证。大大地提高了编码效率,减少了编码量

 

时间: 2024-10-14 13:16:23

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

2017年3月28日下午学习日志

2017年3月28日下午复习了高等数学,继续看了张宇高等数学基础班课程视频第一章极限与连续部分极限的计算法则中数列极限的计算和连续与间断,第二遍听课过程中能巩固之前所学内容,不懂的问题得以解决,印象也更加深刻,对复习有很大的帮助,背英语单词100个.

2017 年9月28日 三级联动

我还不太会   所以借鉴一下别人的代码, 防止忘记 <!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title></title>        <style>                    </style>    </head>    <body>        年份:

老男孩教育每日一题-2017年3月28日-awk累计相加

假如现在有个文本,格式如下: a  1 b  3 c  2 d  7 b  5 a  3  g  2 f  6 d  9 即左边是随机字母,右边是随机数字,要求写个脚本使其输出格式为: a  4 b  8 c  2 d  16 f  6 g  2 即将相同的字母后面的数字加在一起,按字母的顺序输出. 答案: awk '{h[$1]=h[$1]+$2}END{for(pol in h)printpol,h[pol]}' array_add.txt 演示: [[email protected] aw

老男孩教育每日一题-2017年4月28日- MySQL主从复制常见故障及解决方法?

MySQL主从复制常见故障及解决方法? 1.1.1故障1:从库数据与主库冲突 show slave status; 报错:且show slave status\G Slave_I/O_Running:Yes Slave_SQL_Running:No Seconds_Behind_Master:NULL Last_error:Error 'Can't create database 'xiaoliu'; database exists' on query. Default   database:'

Python小程序练习(7个) 2017年9月28日---告诉自己多东西练习,而不是去空想

1.字符串拼接程序 str1 = input("请输入一个人的名字:") str2 = input("请输入一个国家名字:") print("世界这么大,{}想去看看{}.".format(str1,str2)) 2.整数数列求和 n = input("请输入整数N:") sum = 0 for i in range(int(n)): sum +=i+1 print("1到N求和结果:",sum) 3.九九

2017年安吉白茶3月28日采摘上市

3月18日,2017安吉白茶开采新闻发布会在上海金融信息中心举行.安吉官方宣布:今年安吉白茶的开采时间为3月28日,届时全县将有30%左右的茶园进入采摘期.(2017年安吉白茶3月28日采摘上市) 安吉白茶定于3月28日开采安吉白茶定于3月28日开采"决定春茶开采时间的关键因素是天气."安吉县委副书记.县长陈永华介绍:安吉白茶开采时间,根据茶芽萌动所需温度.光照.降水量的基本要求,结合安吉白茶核心保护区内部分茶园茶树生长情况监测分析最终确定的,今年安吉白茶有点姗姗来迟,开采时间比去年晚

【书阳谜友群】2017年4月13日吴锦平(三江)主擂谜会题

[书阳谜友群]2017年4月13日吴锦平(三江)主擂谜会题 1.端起杯心开怀(陈百强歌曲)不2.先生易志,早晚节不保(音响品牌3字)士必草3.雨中细柳长,庭前槐花开(音响品牌)魔雷4.画中疏柳白花开(电视剧插曲)留香5.“寄言二三子”(京剧演员3字)陈五儿6.“红树晚开花”(三字老歌)夜来香7.“篱边初见一枝新”(中超球员连比赛用语共4字)梅方首秀[面出宋陆游<射的山观梅>]8.“千金争致华轩下”(国名连首都共5字)意大利罗马[面出宋苏轼<申王画马图>]9.“烟横日落惊鸿起”(航空

2017年8月14日套题记录 | 普及组

写在前面 今天登洛谷发现离Noip剩下88天了??(虽然看起有点久),然后觉得似乎水了一个暑假什么也没做(虽然学了点数据结构和一些奇奇Gaygay的东西),于是打开题库发现去年Long Happy的集训套题我似乎没有提交过,那就一天一套题,顺便码个题解+心得(雾? T2.传作业 题目描述 某十三同学一日上学迟到,此时已经开始上早自习了,所以他只好请同学帮忙把作业传到组长那里.由于刚开学不久,某十三同学还没来得及认识所有同学,所以传作业时只好找熟悉的同学.已知某十三与组长之间有N个他熟悉的同学,并

2017年5月26日课堂笔记

2017年5月26日 星期五 晴 空气质量:中度污染 内容:JavaScript:初识js,按钮的点击事件,变量的使用,数据类型,typeof的使用, string的使用,数组的使用,运算符的运用,逻辑控制语句的使用 备注:5月28日补课堂笔记 一.初识js 老师代码: <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>初