模型与元数据(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的成员
    
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

//此属性可通过HiddenInputAttribute特性对元数据进行配置,TemplateHint的值=HiddenInput
//如果同时为mox或模型成员设置了UIHintAttribute和HiddenInputAttribute,默认UIHintAttribute的优先级最高

数据注解

特性运用在模型和模型的成员上,这样可以影响模型的元数据,而元数据也提供某些属性与特性进行关联。也即如果将某个类型放进ModelMetadata的构造函数就可以创建出该模型的元数据对象,这个对象提供一些属性或方法可以获取该模型的元数据信息。

UIHintAttribute特性

作用:ModelMetadata的TemplateHint属性表示运用在模型上的模板,这些模板可以是Html模板、WPF模板、MVC模板等等。此属性关联在模型上指定的UIHint特性。UIHint可以在一个模型、模型成员上运用多次,在MVC框架中,展示层的类型如果是Mvc则会优先使用该UIHint,如果没有指定展示层的类型则默认使用首次出现的UIHint

UIHintAttribute ( string UIHint , string PresentationLayer )             
UIHint
//模板的名称,对应于元数据的TemplateHint属性
PresentationLayer
//展示层的类型

示例:以下创建了一个DemoModel模型,在它的成员上运用了UIHint特性,其中Bar和Baz成员运用了多次UIHint,Bar的UIHint特性使用了Mvc,所以该特性指定的模板会被确定为最终要使用的模板。

public class DemoModel
{
    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信息

@model ModelMetadata

<!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的优先级更高。

//指示模型或模型成员通过Html模板生成类型为Hidden的Input元素(生成为隐藏域),对应于元数据的TemplateHint属性
HiddenInputAttribute ( bool DisplayValue ) 
DisplayValue
//一个bool值,指示该隐藏域的前面是否应以只读文本显示模型或模型成员的值,对应于元数据的HideSurroundingHtml属性

示例:使用Html.EditorFor方法将模型的成员以输入框的方式被创建,但设为隐藏域的成员将以隐藏域的方式被创建

public class DemoModel
{
    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 = "男" } );        
    }
}

在视图页面中做测试

@model MVC.Controllers.DemoModel
<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。

RequiredAttribute;( bool AllowEmptyStrings | string ErrorMessage |  )
AllowEmptyStrings
//获取或设置一个值,该值指示是否允许空字符串,默认false。
ErrorMessageString
//获取或设置在验证失败时显示的错误消息

DataTypeAttribute特性

作用:用于标注数据应显示的数据格式,比如时间、货币等等。

DataTypeAttribute; ( DataType dataType | string customDataType )
DataType
//一个DataType枚举,指定模型或模型成员显示的数据格式类型
CustomDataType 
//用户自定义的数据显示格式类型
DisplayFormat
//一个DisplayFormatAttribute特性,参看DisplayFormatAttribute特性
GetDataTypeName ( )
//如果需要自定义数据显示的格式类型,则通过从DataTypeAttribute派生,重写此虚方法。对应于元数据的DataTypeName属性
IsValid
//是否验证数据有效性
DisplayFormatAttribute特性
作用:格式化模型或模型成员的值
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特性

作用:指示模型或模型成员是否允为只读,如果同时在一个对象上运用Editable和ReadOnly,则Editable具有更高的优先级。
ReadOnlyAttribute;(bool IsReadOnly)
IsReadOnly
//是否只读,对应于元数据的IsReadOnly属性

DisplayName特性

作用:设置属性、事件、无参函数的显示名称。在System.ComponentModel命名空间。
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,如果有则会把异常抛到客户端,如果应用了此特性则不会验证

MVC - Ajax的更多相关文章

  1. MVC Ajax Helper或jQuery异步方式加载部分视图

    Model: namespace MvcApplication1.Models { public class Team { public string Preletter { get; set; } ...

  2. MVC Ajax.BeginForm重复提交解决方法

    mvc使用MVC Ajax.BeginForm提交的时候有重复提交结果的时候检查相关js文件引用情况, 其中mvc4注意 1 2 3 4 @Scripts.Render("~/bundles ...

  3. ASP.NET MVC Ajax.ActionLink 简单用法

    ASP.NET MVC 项目中,如何使用类似于 iframe 的效果呢?或者说 Ajax 局部刷新,比如下面操作: 我们想要的效果是,点击 About 链接,页面不刷新(地址栏不变),然后下面的内容进 ...

  4. 爱上MVC~ajax调用分部视图session超时页面跳转问题

    回到目录 这个问题出现了很多年了,都没有解决,问题是这样的,有一个需要授权才可以访问的分部视图,在一个view中使用ajax的方法去调用它,然后更新页面的局部DIV,这时,如果你长时间不操作,sess ...

  5. spring mvc ajax 提交复杂数组类型

    The server refused this request because the request entity is in a format not supported by the reque ...

  6. Asp.Net MVC ajax调用 .net 类库问题

    如果你还在为 ajax 调用 .net 类库还束手无策的话,相信这篇博客将帮助你解决这个世纪问题! 因为Visual Studio 内置了asp.net mvc ,不过当你添加asp.net mvc项 ...

  7. Asp.Net MVC Ajax

    将ASP.NET MVC中的form提交改为ajax提交 在ASP.NET MVC视图中通过 @using (Html.BeginForm()) 产生的是form表单提交代码,可以用javascrip ...

  8. .net mvc ajax list post

    http://stackoverflow.com/questions/13242414/passing-a-list-of-objects-into-an-mvc-controller-method- ...

  9. Spring MVC ajax:post/get 的具体实现

    Post 方式 1.自动注入 a. pom.xml ---- 配置Maven,添加必要的jar包 <!--用于 String-JSONObject 转换 --> <dependenc ...

  10. Mvc Ajax提交多个checkbox,也说绑定和提交select

    Ajax Mvc的 checkbox 后端必须是List<T> ,T是ID类型,一般int 或guid 模型必须初始化List<T> 防止客户端没有提交任何值时空引用的问题,如 ...

随机推荐

  1. 《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现2

    原文:<ArcGIS Engine+C#实例开发教程>第七讲 图层符号选择器的实现2 摘要:在第七讲 图层符号选择器的实现的第一阶段中,我们完成了符号选择器窗体的创建与调用.在第二阶段中, ...

  2. uml类图的几种关系

    UML类图几种关系的总结   在UML类图中,常见的有以下几种关系: 泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregati ...

  3. Linux 线程优先级

    http://www.cnblogs.com/imapla/p/4234258.html http://blog.csdn.net/lanseshenhua/article/details/55247 ...

  4. 【原创】MIPS浅议之——中断系统之我见

    最近,准确的说应该是最近两个月的时间,我都在研究MIPS的异常与中断.或者可以说,最近这两个月,我才真正了解中断系统的整个结构和处理流程以及为什么要这样做?这段时间我最大的体会就是以前我们在“计算机组 ...

  5. Leap Years

    Description: In this kata you should simply determine, whether a given year is a leap year or not. I ...

  6. FORM Save : ORA-01403 FRM-40735 ORA-06502

    症状: FORM开发后挂上服务器后,运行保存按键提示: ORA-01403: 未找到任何数据 ----------------------------------------------------- ...

  7. open MMT.distributions = null on transaction type: WIP Lot Split

    open MMT.distributions = null on transaction type:  WIP Lot Split       打开物料事务处理界面,发现事务处理类型为:WIP Lot ...

  8. lnmp.org一键安装包

    LNMP安装快速导航:LNMP安装提示,LNMP安装教程.安装失败处理.虚拟主机管理.可选组件.LNMP文件目录说明.状态管理. 系统需求: CentOS/Debian/Ubuntu Linux系统 ...

  9. c语言输入与输出库函数#include<stdio.h>

    last modified: 2010-05-28 输入与输出<stdio.h> 头文件<stdio.h>定义了用于输入和输出的函数.类型和宏.最重要的类型是用于声明文件指针的 ...

  10. MySQL锁机制

    一.概况MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking):BDB存储引擎采用 ...