问题1:什么叫Model元数据?html
Model元数据,是针对数据类型的一种描述信息。因为复杂类型(或者说类型嵌套的存在,好比CustomerModel中有一个属性为复杂类型Address)的存在,所以Model 元数据为树形结构:数据库
1 //namespace:System.Web.Mvc 2 public class ModelMetadata 3 { 4 //其它成员 5 6 //当前模型类型 7 //假若用数据库中树形结构解释,这个属性至关于Id 8 public Type ModelType { get; set; } 9 10 //当前模型类型所属类型 11 //假若用数据库中树形结构解释,这个属性至关于ParentId 12 public Type CotainerType { get; set; } 13 14 }
在ASP.NET MVC中对应被定义为类型 “ModelMetadata”,其做用主要体如今如下两个方面:框架
一、控制数据类型自己及其成员属性在界面上的呈现方式;测试
1 //namespace:System.Web.Mvc 2 public class ModelMetadata 3 { 4 //其它成员 5 6 //模型名称 7 public virtual string DisplayName { get; set; } 8 }
上面代码将MVC框架定义的Model元数据精简为一个属性,该属性用于呈现Model或者Model数据中元素在UI上的显示名称。这样说过于抽象,下面的的代码是咱们在MVC程序开发时候常写写的界面模型类:ui
1 //用户界面模型 2 public class CustomerModel 3 { 4 [DisplayName("用户姓名")] 5 public string Name{get;set;} 6 7 public string Gender{get;set;} 8 }
给CustomerModel的 Namei属性添加DisplayName 特性,Gender属性不作任何操做,假若在强类型视图上使用@Html.DisplayFor(d=>d.Name); @Html.DisplayFor(d=>d.Gender)显示用户信息,会发现Name会显示“用户姓名”,而Gender属性的显示仅仅是原样输出为Gender;spa
事实上,DisplayName特性就是经过改变ModelMetadata的DisplayName来达到这一效果,也就是说,特性的做用在于定制ModelMetadata。code
二、Model绑定和验证提供必不可少的元数据orm
绑定之后说起,至于验证,看下面代码:htm
1 //namespace:System.Web.Mvc 2 public class ModelMetadata 3 { 4 //其它成员 5 6 //是否必填 7 public virtual bool IsRequired{ get; set; } 8 }
1 1 //用户界面模型 2 2 public class CustomerModel 3 3 { 4 4 [Required] 5 5 public string Name{get;set;} 6 6 7 7 public string Gender{get;set;} 8 8 }
同理,Required特性定制了Model元数据中的IsRequired属性以达到针对模型的验证。对象
问题2:如何针对Model元数据进行定制?
问题1中说明了ModelMetadata类的各属性控制了数据在UI中的呈现、验证、绑定。那么如何获取或设置ModelMetadata类的各属性呢?答案是使用特性【Attribute】。
能够用于定制Model元数据的特性有如何:
一、UIHintAttribute
HtmlHelper定义了一系列模板方法,好比DisplayFor/Display、EditorFor/Editor,所谓模板方法,就是Model数据与HTML标签的封装。其效果相似于强类型的PartialView。
UIHintAttribute特性的做用就在于为Model中的属性或者字段显示指定模板,当UI出现@Html.DisplayFor(d=>d.Name)语句,ASP.NET MVC将会用UIHintAttribute指定的模板展现Model数据。
MVC有一套寻找模板的规则,默认吗没有指定模板状况下,MVC将从@DisplayFor(d=>d.Name) lamba表达式中获得Name的数据类型,根据该数据类型在预约义的目录下去寻找不一样的模板。而同一种数据类型模板,又能够分为编辑模板(EditorFor)、显示模板(DisplayFor)。假若指定了一个具体的模板名称,ASP.NET MVC 会自动采用该模板来生成最终的HTML。而指定的模板一般按显示模式定义在EditorTemplates目录或DisplayTemplates目录下。这些目录能够存在于Views/Shared、Views/{ControllerName}下;
能够作个测试。
首先定义数据模型:
1 public class CustomerModel 2 { 3 [UIHint("Name")] 4 public string Name { get; set; } 5 6 public string Gender { get; set; } 7 }
经过UIHint特性指定了显示模板为“Name”;
控制器中实例一个CustomerModel对象,并传递给视图View。
1 public ActionResult Index() 2 { 3 CustomerModel model = new CustomerModel() 4 { 5 Name = "小李", 6 Gender = "男" 7 }; 8 return View(model); 9 }
新建View以下:
1 <body> 2 <div> 3 @Html.DisplayFor(d=>d.Name)<br /> 4 @Html.DisplayFor(d => d.Gender) 5 </div> 6 </body> 7 </html>
主要Gender属性咱们并无指定显示模板,接着须要在DisplayTemplates目录下新建Name 视图:
@model string <h3 style="color:red;">我是自定义模板:@Html.TextBox(Model,Model)</h3>
最终运行结果以下:
APS.NET MVC预约义模板总共有这么几个:
模板名称 | 模板做用 | 模板说明 |
EmailAddress | Emal地址呈现 | 仅具备显示模式 |
HiddenInput | 显示模式下文本显示; 编辑模式下文本+一个隐藏的<inptu> |
HiddenInput(DisplayValue=false) 时,显示模式、编辑模式显示文本均消失。 |
Html | 将模型数据中包含的HTML原样呈现 | 仅限于显示模式,效果与Html.Raw()相同 |
Text与String | ---- | 显示模式下直接以文本的形式输出,编辑模式下对应一个单行文本框 |
MultilineText | 多行文本(<input type="text"/>) | 仅限于编辑模式 |
Password | 密码框 | 仅限于编辑模式 |
Decimal | 小数位统一化为两位小数 | 显示模式:文本;标记哦是:单行文本框 |
Boolean | ---- | 显示模式:一个checkbox,disabled=true;编辑模式:一个chekbox,加一个隐藏的checkbox,二者name相同,value相异 |
Colloection | 集合数据呈现 | …………………… |
Object | 备胎 | 找不到其它,最终就是它。根据元数据DisplayName生成一个<div> |
2.HiddenInputAttribute与ScaffoldColumnAttribute
经过应用HiddenInputAttribute,该特性的目标对象以只读的形式显示出来,若是不但愿显示,能够设置特性的DisplayValue为false([HiddenInput(DisplayValue=false)])。
经过应用ScaffoldColumnAttribute,该特性的目标对象不会出如今最终生成的Html中,区别与HiddenInputAttribute,HiddenInputAttribute目标元素会以type=hidden的形式出如今最终生成的Html当中;
3.DataTypeAttribute与DisplayFormatAttribute
这里的DataTypeAttribute不一样于CLR类型,而是经过系统定义的枚举类型:DataType来表示具备某种显示格式的数据类型。枚举DataType定义以下:
1 // 摘要: 2 // 表示与数据字段和参数关联的数据类型的枚举。 3 public enum DataType 4 { 5 // 摘要: 6 // 表示自定义的数据类型。 7 Custom = 0, 8 // 9 // 摘要: 10 // 表示时间上的一刻,以日期和当天的时间表示。 11 DateTime = 1, 12 // 13 // 摘要: 14 // 表示日期值。 15 Date = 2, 16 // 17 // 摘要: 18 // 表示时间值。 19 Time = 3, 20 // 21 // 摘要: 22 // 表示对象存在的一段连续时间。 23 Duration = 4, 24 // 25 // 摘要: 26 // 表示电话号码值。 27 PhoneNumber = 5, 28 // 29 // 摘要: 30 // 表示货币值。 31 Currency = 6, 32 // 33 // 摘要: 34 // 表示所显示的文本。 35 Text = 7, 36 // 37 // 摘要: 38 // 表示一个 HTML 文件。 39 Html = 8, 40 // 41 // 摘要: 42 // 表示多行文本。 43 MultilineText = 9, 44 // 45 // 摘要: 46 // 表示电子邮件地址。 47 EmailAddress = 10, 48 // 49 // 摘要: 50 // 表示密码值。 51 Password = 11, 52 // 53 // 摘要: 54 // 表示 URL 值。 55 Url = 12, 56 // 57 // 摘要: 58 // 表示图像的 URL。 59 ImageUrl = 13, 60 }
事实上,DataTypeAttribute是一个验证特性,MVC在数据绑按期间将会根据应用了DataTypeAttribute的目标元素验证。
DisplayFormatAttribure用于控制目标元素的显示形式。
4 其它
EditableAttribute与ReadOnlyAttributr控制目标元素的可读写性,二者实质等同,同时出现的状况下,前者具备更高的优先级;
DisplayAttribute与DisplayNameAttribute 为目标元素定义一些说明性文字。同时出现的状况下,前者具备更高的优先级;此外,因为DisplayAttribute设置的文字都是面向最终用户的,因此有必要对其斤西瓜本地化,因此该特性提供了ResourceType属性用于表明采用的资源文件类型。
RequiredAttribute顾名思义,其将目标元素设置为必需的数据成员。