zoukankan      html  css  js  c++  java
  • MVC系统学习4—ModelMetaData

    在Mvc R2中,新引入了一些扩展方法,如后面带一个for的方法,这些扩展方法会根据Model的属性自定生成相应的Html元素,如Html.EditFor(Model=>Model.IsApprove),当IsApproved为布尔类型时显示checkbox文本框,这样能简化我们的工作并且能够利用到ModelBinding。当我们调用Html.EditFor的时候,会调用到TemplateHelpers的方法去查找相应的模板,框架本来定义好了两个模板,就是DefaultDisplayTemplates和DefaultEditorTemplates分别对应着显示Display和Edit编辑。在TemplateHelpers里面定义着两个字典,键是类型名称,值是模板名称。这里就需要引出另外一个类,就是ModelMetaData。其是模型类型信息的包装,还有一些和显示相关的。ModelMetaDataProvider是负责从类型获取ModelMetaData。下图反映了ModelMetaData的真实情况。

          一.  ModelMetaDataProvider

          ModelMetaDataProvider是一个抽象类。下面一幅图能准确放映ModelMetaData和ModelMetaDataProvider的关系。在mvc框架下默认的ModelMetaDataProvider是DataAnnotationsModelMetadataProvider。我们也可以自己定义一个Provider,然后通过在Global文件中设置ModelMetadataProviders.Current实现我们自己的Provider。使用DataAnnotationsModelMetadataProvider的好处就是它内建支持.NET中的Data Annotation特性。怎么个内建支持法?他的CreateMetadata方法会查找作用在模型下的某些特性,这些特性是指System.ComponentModel.DataAnnotations命名空间下的元数据特性,通过给我们的MVC模型类或者类的属性添加这些特性能控制显示或者在验证时期作用。

           二.System.ComponentModel.DataAnnotations命名空间下的元数据特性

           1.DataTypeAttribute: 属性允许使用比数据库内部类型更加具体的类型来标记字段。类型名称选自 DataType 枚举类型。例如,可以将包含电子邮件地址的字符串数据字段指定为 EmailAddress 类型。字段模板随后将访问此信息,以修改数据字段的处理方式。

           2.DisplayFormatAttribute: 指定如何显示数据字段以及如何设置数据字段的格式。这里需要注意一点,这个特性只能作用于属性或者字段,NullDisplayText 是表示当属性为空的时候的显示方式。

           3.MetadataTypeAttribute: 指定要与数据模型类关联的元数据类。当我们可以将模型的定义和对模型MetaData的定义分开。

    public partial class Person   
     {   
         public int PersonId { get; set; }   
         public string FirstName { get; set; }   
         public string LastName { get; set; }   
         public DateTime BirthDate { get; set; }   
         public Address HomeAddress { get; set; }   
         public bool IsApproved { get; set; }   
    }
    
    [MetadataType(typeof(PersonMetadata))]   
     public partial class Person   
     {   
         // This class is only used as a source of metadata        
     private class PersonMetadata   
         {   
    
             [HiddenInput(DisplayValue = false)] public int PersonId { get; set; }   
    
                 [DisplayName("First name")] public string FirstName { get; set; }   
                [DisplayName("Last name")] public string LastName { get; set; }        
             // Also add any other properties for which you want to supply metadata   
         }   
     }

            接下来其他的都是比较容易的:

             4.此外还有一个DisplayName属性,其是在System.ComponentModel命名空间下的。用户控制显示是的字段名称。还有Mvc的HiddenInput用户控制以hidden隐藏域的形式显示。

            三.上面这些特性的作用

            前面已经有提到过,这些特性的作用是用在显示和验证。我们定义好模型利用Html.Html.EditorForModel()能帮助框架能帮助我们显示相应的编辑页面。而且当我们提交的时候,还能自动利用到ModelBinder,而那些验证的特性主要是在实现ModelBinder绑定功能的时候验证客户端的提交是否和模型中特性的定义一致,如果不一致ModelState的Error就会记录,ModelState的IsValid属性就为false。利用我为模型中的Name字段添加了特性Require,但是当我提交的时候,Name属性对应的表单值为空,则就会出错。可以得知在定义这些特性后,利用ModelBinder能自动帮助我们实现数据验证。

            四.Mvc自带的验证功能

            Mvc验证的相关类的框架大致如下图:

            这里的核心类是ModelValidator,其通过验证规则和提交的数据产生验证结果ModelValidationResult。而ModelValidatorProvider是根据ModelMetaData和ControllerContext以及Attribute生成ModelValidator的。继承自ModelValidatorProvider的三个子类分别重载实现了GetValidators方法。

            DataAnnotationsModelValidatorProvider:根据ModelMetaData和作用于Model的System.ComponentModel.DataAnnotations attributes 来产生验证规则。

            ClientDataTypeModelValidator:用法暂时还不是很明白

            DataErrorInfoModelValidatorProvider:用法也暂时不是很明白

            从上面可以得出ModelValidator是一个抽象类,具体的验证实现是由其子类实现的,下面有一副图能反映具体的类框架图。DataAnnotationModelValidator继承自Model-Validator,而泛型类DataAnnotationModelValidator<TAttribute>有继承自DataAnnotationModelValidator。接下来System.ComponentModel.DataAnnotations的各个验证特性分别会对应着一个继承自DataAnnotationModelValidator<TAttribute>的类。这里的用法会在另外一篇文章介绍!

            五.自定义模板:

            在前面讲过,当我们使用类似DisplayFor这样的Html辅助函数的时候,框架会根据呈现的模型的类型去查找相应的模板进行显示。我们也可以自己定义模板来显示某些类型。做法是在Shared下添加DisplayTemplates或者EditTemplates分别对应着显示和编辑模板。然后添加自定义控件,自定义控件的名称和模型或者类型名称一致。这样当进行显示的时候,自定的模板会先覆盖框架默认的模板。这里当然还要注意一点就是Mvc关于模板的选择顺序。以下列出的是从上到下的优先选择顺序。

    • 在EditorFor方法中显示指定的模板名称,Html.EditorFor(x => x.SomeProperty , “My Template”)。
    • 对应Model的元数据描述,比如在属性上添加特性[UIHint(“My Template”)]
    • Model的元数据描述的数据类型,比如[DataType(DataType.EmailAddress)]
    • 对应属性的真实.NET 类型
    • 对于可以被转化成string的简单类型,使用String模板
    • Model的父类属性也会被转化
    • 如果属性实现了IEnumable,将选择Collection模板
    • 最后使用Object模板
    明确个目标,一直走下去
  • 相关阅读:
    FireFox/Chrome不支持在前台js读后台Attributes.Add("DefaultValue")的属性
    IIS Web怪问题: Access is denied due to invalid credentials.
    转:OWC学习笔记电子表格(Spreadsheet)风格属性设置
    最全的CSS浏览器兼容问题整理(IE6.0、IE7.0 与 FireFox)
    转:[网站安全]避免在站点中通过URL参数做重定向
    [SQL Server 2005 BI]在.NET中创建SQL 2005 KPI
    即使asp:TreeView有几万个节点,也让IE不死的解决方法
    Visual Totals in MDX and Role Security
    css hack
    让Updatepanel中的控件触发整个页面Postback
  • 原文地址:https://www.cnblogs.com/fhlj/p/3615226.html
Copyright © 2011-2022 走看看