ASP.NET MVC - 模型与元数据(进阶)
模型与元数据(Model & Model Metadata)
ASP.NET MVC中有一个模型的概念,实际上模型就是一个类型,Model表示的就是最终要绑定到View视图页面上的数据而已。
模型元数据
模型元数据用ModelMetadata类表示,它描述Model自身的类型、成员的类型、自身和成员的特性等信息,它的作用有两点:1.控制模型在视图上的呈现方式。2.为模型绑定验证逻辑。ModelMetadata元数据对象描述了与它关联在一起的Model的数据结构,以及Model的每个数据成员的一些特性。正是有了Model元数据的存在,才使模板化HTML的呈现机制成为可能。要创建一个模型的元数据,只需要在ModelMetadata构造函数中将Model的类型作为参数传递进去即可。ModelMetadata支撑了ASP.NET MVC的Model验证体系,因为针对Model的验证规则正是定义在Model元数据中。
ModelMetadata ( ModelMetadataProvider provider , Type containerType , Func<object> modelAccessor , Type modelType , string propertyName );
//构造函数,传递Model的类型作为参数创建出Model的元数据对象
Provider
//Model元数据的提供程序。
ModelType
//模型的类型。
IsComplexType
//是否是复杂类型。复杂类型即不是基元类型和值类型的引用类型
//如果Model支持从基元字符串转换为类类型,则IsComplexType将为fale,这可以通过TypeConverterAttribute特性描述当前Model是否可由字符串转为为Model类型
//如果是,则IsComplexType返回false
//示例:
[ TypeConverter ( typeof ( AnimalTypeConvert ) )]
public class Animal
{
public string Name { get; set; }
}
public class AnimalTypeConvert : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom ( ITypeDescriptorContext context , Type sourceType )
{
return sourceType == typeof ( string );
}
public override object ConvertFrom ( ITypeDescriptorContext context , CultureInfo culture , object value )
{
if ( value is string )
{
Animal a = new Animal { Name = value.ToString ( ) };
return a;
}
return base.ConvertFrom ( context , culture , value );
}
}
//测试:
string animal = "蚂蚁";
AnimalTypeConvert AnimalTypeConvert = new AnimalTypeConvert ( );
Animal a = ( Animal ) AnimalTypeConvert.ConvertFrom ( animal );
string name = a.Name; //print 蚂蚁
IsNullableValueType
//如果该类型可为 null,则为 true;否则为 false
ContainerType
//包容当前类型的类型,比如Animal包含Person类型,则Person的ContainerType为Animal
IsReadOnly
//该模型是否是只读的
IsRequired
//如果该模型是必需的,则为 true;否则为 false。
PropertyName
//模型的名称
Properties
//用于描述模型属性的模型元数据对象的集合。
AdditionalValues
//包含有关模型的其他元数据的字典,可通过在模型或模型成员上运用System.Web.Mvc.AdditionalMetadataAttribute特性来为它们增加自定义用于描述信息的属性
TemplateHint
//一个提示,建议要为此模型使用哪种模板。
FromLambdaExpression<TParameter, TValue> ( Expression<Func<TParameter , TValue>> expression , ViewDataDictionary<TParameter> viewData );
//从模型的 System.Linq.Expressions.Expression 参数返回元数据
GetValidators ( ControllerContext context );
//模型的验证程序的列表。
TemplateHint
//获取应用在元数据上的模板,比如Html模板、WPF模板、MVC模板,此属性可通过UIHintAttribute特性对元数据进行配置,TemplateHint的值=UIHintAttribute.UIHint
数据注解
特性运用在模型和模型的成员上,这样可以影响模型的元数据,而元数据也提供某些属性与特性进行关联。也即如果将某个类型放进ModelMetadata的构造函数就可以创建出该模型的元数据对象,这个对象提供一些属性或方法可以获取该模型的元数据信息。
UIHintAttribute特性
作用:ModelMetadata的TemplateHint属性表示运用在模型上的模板,这些模板可以是Html模板、WPF模板、MVC模板等等。此属性关联在模型上指定的UIHint特性。UIHint可以在一个模型、模型成员上运用多次,在MVC框架中,展示层的类型如果是Mvc则会优先使用该UIHint,如果没有指定展示层的类型则默认使用首次出现的UIHint
UIHint
//模板的名称,对应于元数据的TemplateHint属性
PresentationLayer
//展示层的类型
示例:以下创建了一个DemoModel模型,在它的成员上运用了UIHint特性,其中Bar和Baz成员运用了多次UIHint,Bar的UIHint特性使用了Mvc,所以该特性指定的模板会被确定为最终要使用的模板。
{
public string Foo { get; set; }
[UIHint ( "Template A" )]
[UIHint ( "Template B" , "Mvc" )]
public string Bar { get; set; }
[UIHint ( "Template A" )]
[UIHint ( "Template B" )]
[UIHint ( "Template C" )]
public string Baz { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index ( )
{
ModelMetadata modelMetadat = new ModelMetadata ( ModelMetadataProviders.Current , null , null , typeof ( DemoModel ) , null );
return View ( modelMetadat );
}
}
在视图中读取DemoModel的属性成员的元数据的TemplateHint信息
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<style>
body{padding:;margin:;font:normal 12px/24px "\5FAE\8F6F\96C5\9ED1";color:#444;text-align: center;}
table{width:500px;border:;margin:100px auto ;text-align:center;border-collapse:collapse;border-spacing:;}
table th{background: #09007c;font-weight:normal;line-height:30px;font-size:14px;color:#FFF;}
table tr:nth-child(odd){background:#F4F4F4;}
table td:nth-child(even){color:#C00;}
table tr:nth-child(5){background:#73B1E0;color:#FFF;}
table tr:hover{background:#73B1E0;color:#FFF;}
table td,table th{border:1px solid #EEE;}
</style>
</head>
<body>
<table>
@{
<tr>
<th>DemoModel的属性</th>
<th>元数据TemplateHint</th>
</tr>
foreach ( var p in Model.Properties )
{
<tr>
@{
<td>@p.PropertyName</td>
<td>@(p.TemplateHint??"N/A")</td>
}
</tr>
}
}
</table>
</body>
</html>
HiddenInputAttribute特性
作用:当使用Html.EditorFor()方法时,将运用了HiddenInput特性的模型或模型成员生成为隐藏域,HiddenInput对应于元数据的TemplateHint,而HiddenInput的DisplayValue则对应于元数据的HideSurroundingHtml。如果一个模型或模型成员上同时运用了UIHint和HiddenInput,默认UIHint的优先级更高。
HiddenInputAttribute ( bool DisplayValue )
DisplayValue
//一个bool值,指示该隐藏域的前面是否应以只读文本显示模型或模型成员的值,对应于元数据的HideSurroundingHtml属性
示例:使用Html.EditorFor方法将模型的成员以输入框的方式被创建,但设为隐藏域的成员将以隐藏域的方式被创建
{
public string name { get; set; }
[HiddenInput] //生成隐藏域且显示age的值
public string age { get; set; }
[HiddenInput ( DisplayValue = false )] //生成隐藏域且不显示gender的值
public string gender { get; set; }
}
public class DefaultController : Controller
{
public ActionResult Index()
{
return View ( new DemoModel { name = "sam" , age = "19" , gender = "男" } );
}
}
在视图页面中做测试
<form>
@Html.EditorFor ( m => m.name )
@Html.EditorFor ( m => m.age )
@Html.EditorFor ( m => m.gender )
</form>
ScaffoldColumnAttribute特性
作用:ScaffoldColumn指示当调用Html.EditorFor、Html.DisplayFor()方法创建编辑(input)、文本(label)时,运用了此特性的模型或模型成员将不会显示,也即EditorFor()、DisplayFor()方法将变得无效。经测试此特性没有效果,原因不明。ScaffoldColumn特性对应于元数据的ShowForDisplay、ShowForEdit属性。
RequiredAttribute特性
作用:使属性为必填项,与DataTypeAttribute一样,它们都派生自ValidationAttribute。
AllowEmptyStrings
//获取或设置一个值,该值指示是否允许空字符串,默认false。
ErrorMessageString
//获取或设置在验证失败时显示的错误消息
DataTypeAttribute特性
作用:用于标注数据应显示的数据格式,比如时间、货币等等。
DataType
//一个DataType枚举,指定模型或模型成员显示的数据格式类型
CustomDataType
//用户自定义的数据显示格式类型
DisplayFormat
//一个DisplayFormatAttribute特性,参看DisplayFormatAttribute特性
GetDataTypeName ( )
//如果需要自定义数据显示的格式类型,则通过从DataTypeAttribute派生,重写此虚方法。对应于元数据的DataTypeName属性
IsValid
//是否验证数据有效性
DisplayFormatAttribute ( HtmlEncode | NullDisplayText | ConvertEmptyStringToNull | ApplyFormatInEditMode | DataFormatString )
HtmlEncode
//默认情况下,模型或模型成员的值如果包含Html则会在视图上显示时应用Html格式,此属性可指示是否需要编码Html,默认false(应用Html格式),设为true则会将Html显示为可见的字符串
NullDisplayText
//指示模型或模型成员的值为null时应显示的字符,对应于元数据的NullDisplayText属性
ConvertEmptyStringToNull
//指示模型或模型成员的值为""时,是否转换为null,对应于元数据的ConvertEmptyStringToNull属性
ApplyFormatInEditMode
//指示模型或模型成员的值处于编辑模式时,是否格式化模型或模型成员的值
DataFormatString
//搭配ApplyFormatInEditMode使用,提供在编辑模式下格式化模型或模型成员的值
DisplayAttribute特性(System.ComponentModel.DataAnnotations)
作用:为在用户界面中使用的实体类型和成员指定可本地化的字符串,这些信息是展示给用户看见的数据。类似的有DisplayNameAttribute,但后者只提供简单的功能。
DisplayAttribute; (string Prompt | string Description | string Name | string ShortName | int Order | Type ResourceType )
ResourceType
//本地化显示的资源文件类型,参考:多国语言的简单实现
Name
//为模型或模型成员设置在视图上显示的名称,也即定义别名。对应于元数据的DisplayName属性
ShortName
//为模型或模型成员设置在视图上显示的简短的名称,也即定义简短的别名。对应于元数据的ShortDisplayName属性
Description
//为模型或模型成员设置描述性文本,对应于元数据的Description属性
Order
//为模型或模型成员设置排序权重,默认10000。对应于元数据的Order属性
Prompt
//为模型或模型成员设置一个水印,此水印将会呈现在视图上
GetName()
//返回一个值,用于在 UI 中的字段的显示。对应于元数据的DisplayName属性
GetShortName()
//类似GetName方法,返回一个值,用于在UI中的字段的简洁显示。对应于元数据的ShortDisplayName属性
GetDescription()
//获取描述信息,对应于元数据的Description属性
GetOrder()
//获取对列排序所采取的顺序,默认值10000,对应于元数据的Order属性
GetPrompt()
//获取在UI中的水印的显示,对应于元数据的Watermark属性
例子:
namespace WebErp.Controllers
{
public class Animal
{
[Display(Name ="姓名")] //如果没有应用Display特性,则试图页面将显示'AnimalName'而非'姓名'
public string AnimalName { get; set; }
}
public class DefaultController : Controller
{
public ActionResult Test()
{
return View();
}
}
}
@model WebErp.Controllers.Animal <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
<style>
body{background:black;color:white;font-size:12px;font-family:Arial;}
</style>
</head>
<body>
<div>
@Html.EditorForModel()
</div>
</body>
</html>
EditableAttribute特性(对应元数据的IsReadOnly)
作用:指示模型或模型成员是否允许被编辑
EditableAttribute;(bool allowEdit)
AllowEdit
//是否允许编辑,对应于元数据的IsReadOnly属性
ReadOnlyAttribute特性
ReadOnlyAttribute;(bool IsReadOnly)
IsReadOnly
//是否只读,对应于元数据的IsReadOnly属性
DisplayName特性
DisplayNameAttribute;( string displayName )
DisplayName
//设置属性、事件、无参函数的显示名称。对应于元数据的DisplayName
在模型上应用自定义特性
IMetadataAware接口
如果将某个类型(模型)放进ModelMetadata的构造函数就可以创建出该模型的元数据对象,这个对象就代表了该模型的元数据。它提供一些属性或方法来返回该模型的元数据信息。在模型上应用的数据注解(特性)也会被提取出来用于初始化元数据对象。而假如你想为模型增加一些自定义的元数据或修改已经应用在模型上的某些元数据,那么你可以考虑使用AdditionalMetadataAttribute或AllowHtmlAttribute特性,这两个特性都实现了IMetadataAware接口,IMetadataAware接口提供OnMetadataCreate方法,该方法要求接收一个ModelMetadata对象(模型的元数据)作为参数,这样,就可以在OnMetadataCreate方法中(创建ModelMetadata时)增加一些元数据或修改已经应用在模型上的某些元数据。
AdditionalMetadataAttribute特性
作用:此特性类实现了IMetadataAware接口以支持其他自定义的元数据。
AdditionalMetadataAttribute; (string name | object value)
name
//自定义元数据的名称
value
//自定义元数据的值
AllowHtmlAttribute特性
作用:为了防止用户通过脚本注入攻击应用程序(XSS)所提供的一道验证开关。
AllowHtmlAttribute;()
//ASP.NET MVC默认会验证提交的数据是否包含Html,如果有则会把异常抛到客户端,如果应用了此特性则不会验证
ASP.NET MVC - 模型与元数据(进阶)的更多相关文章
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)
上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...
- [转] ASP.NET MVC 模型绑定的功能和问题
摘要:本文将与你深入探究 ASP.NET MVC 模型绑定子系统的核心部分,展示模型绑定框架的每一层并提供扩展模型绑定逻辑以满足应用程序需求的各种方法. 同时,你还会看到一些经常被忽视的模型绑定技术, ...
- ASP.NET MVC模型绑定的6个建议(转载)
ASP.NET MVC模型绑定的6个建议 发表于2011-08-03 10:25| 来源博客园| 31 条评论| 作者冠军 validationasp.netmvc.netasp 摘要:ASP.NET ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定
在My Blog中已经有了文章管理功能,可以发布和修改文章,但是对于文章内容来说,这里缺少最重要的排版功能,如果没有排版的博客很大程度上是无法阅读的,由于文章是通过浏览器查看的,所以文章的排版其实与网 ...
- ASP.NET MVC - 模型验证
ASP.NET MVC - 模型验证(Model verification) 模型验证原理浅析 模型验证用到了模型绑定器.模型验证器(System.Web.Mvc.DataAnnotationsMod ...
- asp.net mvc 模型验证组件——FluentValidation
asp.net mvc 模型验证组件——FluentValidation 示例 using FluentValidation; public class CustomerValidator: Abst ...
- asp.net Mvc 模型绑定项目过多会导致页面运行时间卡
asp.net Mvc 模型绑定项目过多会导致页面运行时间卡的问题. 解决方式就是采用ModelView方式进行精简,已减少模型绑定及验证的时间.
- 扩展 ASP.NET MVC 模型扩展 – ASP.NET MVC 4 系列
大部分人不能将核心运行时(System.Web 中的类)和 ASP.NET Web Forms 应用程序平台(System.Web.UI 中的类)区分开来. ASP.NET ...
- Asp.Net MVC 模型验证详解-实现客户端、服务端双重验证
概要 在asp.net webform开发中经常会对用户提交输入的信息进行校验,一般为了安全起见大家都会在客户端进行Javascript(利于交互).服务端双重校验(安全).书写校验代码是一个繁琐的过 ...
随机推荐
- springmvc 学习笔记
@Autowired,@RequestMapping,@RequestParam 使用该注解,引入对象时, 可以省略setter getter.减少代码显示. @AutowiredSimService ...
- 离线提取目标机hash
##看了大佬的文章学习到一个姿势在此将其记录一下复现过程 github项目地址:https://github.com/SecureAuthCorp/impacket.git python setup ...
- Java基础构造方法和this关键字整理
构造方法 8.1构造方法介绍 构造方法的格式: 修饰符 构造方法名(参数列表) { } l 构造方法的体现: n 构造方法没有返回值类型.也不需要写返回值.因为它是为构建对象的,对象创建完,方法就 ...
- HDU 1045(炮台安置 DFS)
题意是在 n*n 的方格中进行炮台的安置,炮台不能处于同一行或同一列(类似于八皇后问题),但若是炮台间有墙壁阻挡,则可以同时安置这对炮台.问图中可以安放的最大炮台数目. 用深搜的方法,若此处为空地,则 ...
- 跨域请求传递Cookie问题
问题描述 前后端完全分离的项目,前端使用Vue + axios,后端使用SpringMVC,容器为Tomcat. 使用CORS协议解决跨域访问数据限制的问题,但是发现客户端的Ajax请求不会自动带上服 ...
- Kudu系列: Kudu主键选择策略
每个Kudu 表必须设置Pimary Key(unique), 另外Kudu表不能设置secondary index, 经过实际性能测试, 本文给出了选择Kudu主键的几个策略, 测试结果纠正了我之前 ...
- JAVA方法调用中的解析与分派
JAVA方法调用中的解析与分派 本文算是<深入理解JVM>的读书笔记,参考书中的相关代码示例,从字节码指令角度看看解析与分派的区别. 方法调用,其实就是要回答一个问题:JVM在执行一个方法 ...
- MyEclipse2017 隐藏回车换行符
Preferences->Text Editor->Show Whitespace characters(configure visibility)->Transparency Le ...
- 一次针对多台服务器交互式主机命令采集Python脚本编写
[环境介绍] 系统环境:Linux + Python 2.7.10(监控主机) [背景描述] 需求:每次节假日或者重要时间时,需要对数据库主机信息进行检查,比如主机空间使用率之类.有时候需要执 ...
- 数据库面试题之COUNT(*),COUNT(字段),CONUT(DISTINCT 字段)的区别
COUNT(*).明确的返回数据表中的数据个数,是最准确的 COUNT(列),返回数据表中的数据个数,不统计值为null的字段 COUNT(DISTINCT 字段) 返回数据表中不重复的的数据个数,不 ...