MVC3.0學習筆記之元模型元數據ModelMetaData以及模型元數據提供系統


模型元數據ModelMetaData是MVC中很重要的概念,它包括但不僅限於 模型的類型,模型包含了哪些屬性,屬性都是什么類型的,屬性上都有什么特性。

ASP.NET MVC3.0 提供了默認的模型元數據 DataAnnotationsModelMetadata 繼承自ModelMetadata(另外系統提供了默認的模型元數據提供器DataAnnotationsModelMetadataProvider)

public class DataAnnotationsModelMetadata : ModelMetadata

它的構造函數如下

public DataAnnotationsModelMetadata(DataAnnotationsModelMetadataProvider provider, Type containerType, Func modelAccessor, Type modelType, string propertyName, DisplayColumnAttribute displayColumnAttribute);

 

 

DataAnnotationsModelMetadata類有常用的幾個屬性

DisplayName 顯示名稱,DisplayFormatString格式字符串

TemplateHint 獲取一個值選擇使用哪個模版

 

對於DisplayName ,LabelFor<TModel, TValue> 方法中使用此屬性來生成標簽文本.  意思就是一旦我們的model上有定義了DispalyName特性,那么view中使用html.editForModel()方法就會自動為model的這個屬性顯示出label標簽"  <label for="username">名稱</label></

  

[Display( Name="名稱",Order=2)]   //order屬性改變在html頁面中的排列順序
  public string username { get; set; }

 

image

html源代碼:

<div class="editor-label"><label for="username">名稱</label></div>

<div class="editor-field"><input class="text-box single-line" data-val="true" data-val-maxwords="名稱 has too many words" data-val-maxwords-wordcount="2" data-val-required="名稱 字段是必需的。" id="username" name="username" type="text" value=""> <span class="field-validation-valid" data-valmsg-for="username" data-valmsg-replace="true"></span></div>

 

屬性username上用的Display特性就是System.ComponentModel.DataAnnotations.DisplayAttribute類提供一個通用特性,使您可以為實體分部類的類型和成員指定可本地化的字符串

 

另外還有一些特性來自System.Web.MVC 和 System.ComponentModel.DataAnnotations,名稱凡類似 XXXXAttribute的都為特性類,都有特定的使用范圍,有的限制模型屬性,有的限制Contrller,有的限制Action等等。

 

 

 

下面列舉了這2個命名空間下,內置的而且常用的特性類

1)System.Web.MVC空間下的

AcceptVerbsAttributeActionFilterAttributeActionNameAttributeAsyncTimeoutAttributeAuthorizeAttributeBindAttribute

HiddenInputAttribute 

ActionFilterAttribute  表示所有操作-篩選器特性的基類

HttpDeleteAttribute 類,表示一個特性,該特性用於限制操作方法,以便該方法僅處理 HTTP DELETE 請求

HttpGetAttributeHttpPostAttribute 表示特性,用於限制操作方法,僅限處理PUT請求

HttpPutAttribute  表示一個特性,該特性用於限制操作方法,以便該方法僅處理 HTTP PUT 請求。

 

例:ActionNameAttribute 指定action的實際actionname,用法如下

[ActionName()]

public ActionResult  Index()

 

例:HiddenInputAttribute類,表示一個特性,該特性用於指示是否應將屬性值或字段值呈現為隱藏 input 元素

[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Property, AllowMultiple = false, Inherited = true)]

public sealed class HiddenInputAttribute : Attribute

[HiddenInput]
public string zhanshi { get; set; }  //只隱藏了Input,但是label還是顯示了zhanshi

[HiddenInput(DisplayValue=false)]   //只生了 input hidden  zhanshi2 沒顯示
public string zhanshi2 { get; set; }

image

當DisplayValue設置為false時候,只為zhangshi2屬性生成了一個 <input type=”hidden”   name=”zhangshi2”  value>元素。但是zhangshi生成了2個元素,一個displayName元素,照常顯示,而input元素則隱藏了。

 

2)System.ComponentModel.DataAnnotations 空間下的特性類

AssociationAttribute  指定某個實體成員表示某種數據關系,如外鍵關系。

DataTypeAttribute 指定要與數據字段關聯的附加類型的名稱。   為屬性呈現html時候才有用,數據驗證的時候不使用這個,你懂的。

DisplayColumnAttribute    將所引用的表中顯示的列指定為外鍵列。
DisplayFormatAttribute    指定 ASP.NET 動態數據如何顯示數據字段以及如何設置數據字段的格式。
EditableAttribute    指示數據字段是否可編輯。
EnumDataTypeAttribute    使 .NET Framework 枚舉能夠映射到數據列。
FilterUIHintAttribute    表示一個特性,該特性用於指定列的篩選行為。
KeyAttribute    表示一個或多個用於唯一標識實體的屬性。
MetadataTypeAttribute    指定要與數據模型類關聯的元數據類。
RangeAttribute    指定數據字段值的數值范圍約束。
RegularExpressionAttribute    指定 ASP.NET 動態數據中的數據字段值必須與指定的正則表達式匹配。
RequiredAttribute    指定需要數據字段值。
ScaffoldColumnAttribute    指定類或數據列是否使用基架。
ScaffoldTableAttribute    指定類或數據表是否使用基架。
StringLengthAttribute    指定數據字段中允許的最小和最大字符長度。
TimestampAttribute    將列的數據類型指定為行版本。
UIHintAttribute    指定動態數據用來顯示數據字段的模板或用戶控件。
ValidationAttribute    作為所有驗證特性的基類。

下面例子針對DataTypeAttribute進行應用

[DataType(DataType.EmailAddress)] //表是貨幣值
       [Display(Order=1)] //html顯示的順序
       public string lastname { get; set; }

view:@Html.DisplayForModel()

呈現出的html代碼和外觀:image 點擊郵箱名稱就可以直接調用默認操作系統的郵件系統。

<div class="display-field"><a href="mailto:sdfsd@sina.com">sdfsd@sina.com</a></div>,即使model中lastname設置成不正確的email格式,也會展現出。

image html代碼:<a href="mailto:sdfsd">sdfsd</a>

 

Date    表示日期值。
Time    表示時間值。
Duration    表示對象存在的一段連續時間。
PhoneNumber    表示電話號碼值。
Currency    表示貨幣值。
Text    表示所顯示的文本。
Html    表示一個 HTML 文件。
MultilineText    表示多行文本。
EmailAddress    表示電子郵件地址。
Password    表示密碼值。
Url    表示 URL 值。
ImageUrl    表示圖像的 URL。

注意DataType不能重復對同一個屬性使用

例子:  

[DataType(DataType.DateTime)] //表是貨幣值
[Display(Order=1)]
public string lastname { get; set; }

lastname設置為 DateTime.Now.ToLongDateString()  =2014年4月1日

image

如何lastname能轉換為DateTime就轉換,不能轉換就按照原來的顯示。

 

 

 

上面就是常用的特性,有些特性是用來輔助將屬性或者元素呈現出來,有些還帶有驗證功能。

 

 

 

 

 

 

自定義模版,比如自定義控件,當某個屬性擁有了[UIHint("模版名稱")]特性,那么就會按照新的方式展示,不會按照默認的方式執行。

例:model:public string name{get;set;}  

view:@html.DisplayforModel()

image

最終為屬性name呈現的html元素為input輸入框,這個input輸入框就是默認的模版,當知道是string或者Int類型后,再沒設置其他模版的前提下,選擇默認的input元素。

 

如果我不想讓對string類型,在呈現的時候顯示input輸入框元素,那么我們可以自定義模版,然后在屬性上應用[UIHint(自定義的新模版)]就可以不使用默認的input元素了。

現在開始動手,假設將string類型的屬性呈現出另外的效果,比如display時候顯示 2個輸入,編輯時候顯示2個輸入框。

 

先新建2個文件夾,注意文件夾名稱必須是分別為DisplayTemplates,EditorTemplates

image 

然后在文件夾里建立2個相同名稱的view視圖 Data.cshtml。Data就是新定義的模版名稱。

代碼分別如下

DisplayTemplates/Data.cshtml

<script type="text/javascript">
    $(function () {
        $(".datepicker").datepicker({ "dateFormat": "yy-mm-dd" })
    });
</script>
@Html.TextBox("", String.Format("{0:yyyy-MM-dd}"
, ViewData.TemplateInfo.FormattedModelValue), new { @class = "datepicker" })

EditTemplates/Data.cshtml

@Html.DropDownList("",MvcApplication1.Sample_ModelMeta.DropDownListMenu.年齡選項(),"請選擇年齡")

 

model中設置模版

public class user
{
[UIHint("Data")]
 public string lastname { get; set; }
}

view: 第一個是編輯,第2個是展示

 @Html.DisplayFor(model=>model.lastname,"Data")
 @Html.EditorFor(model=>model.lastname,"Data")

action中設置lastname=DateTime.Now

html代碼:

<div>
   
顯示:<input id="lastname" name="lastname" type="text" value="2014/4/2">
<script type="text/javascript">
    $(function () {
        $(".datepicker").datepicker({ "dateFormat": "yy-mm-dd" })
    });
</script>
編輯:<input class="datepicker hasDatepicker" id="lastname" name="lastname" type="text" value="2014/4/2">
   
   
    </div>

效果圖: 使用EditorFor呈現的是一個輸入框,當你點擊后可以選擇時間。這個時間控件是Jquery Ui中的,所以view要引用jquery.ui.cs

image

 

MVC查找模版的路徑先為當前controller同名的view文件夾下查找,找不到了,再最后是shared文件夾中查找,如果沒找到任何模版,則還是按照默認顯示)

 

 

 

 

 

元數據定制,就是在屬性上添加自定義特性,可以設置元數據。 例如 自定義[displayText]特性

至於如何自定義,首先我們要查看系統默認存在的一些特性的類的結構

  public class DisplayTextAttribute:Attribute,IMetadataAware

 

繼承Attribute類和IMetadataAware接口,實現接口中的OnMetadatAware接口

 public void OnMetadataCreated(ModelMetadata metadata)
        {
            this.DisplayName=this.DisplayName??(metadata.PropertyName??metadata.ModelType.Name);
             if(null==this.ResourceType)
             {
                 metadata.DisplayName=this.DisplayName;
                 return ;
             }
      
       PropertyInfo property=this.ResourceType.GetProperty(this.DisplayName, BindingFlags.NonPublic|BindingFlags.Public| BindingFlags.Static);
             //PropertyInfo property = metadata.ModelType.GetProperty(this.DisplayName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
       metadata.DisplayName = "我把所有列名都改了";//property.GetValue(null, null).ToString();
       metadata.TemplateHint="MultilineText";
        }

在方法中,我們可以設置模型元數據的信息 ,比如此處我將DisplayName都設置成了“xxx”,並設置了模版 為MultilineText。

[DisplayText]
public string Name { get; set; }

效果展示:@html.displayForModel()   為Name呈現一個 label內容為“我把所有列名都改了”,而且輸入框顯示的是多行模式。

 

 

 

 

元數據提供系統,ASP.net提供了一個可插拔的模型元數據提供系統DataAnAnnotationModelMetaProvder,可插拔的意思就是可以自定義然后替換掉默認的元數據提供系統。

若要自定義,請繼承ModelMetadataProvider類,實現3個方法。

 

下面是部分自定義元數據提供系統CustomerMetaProvider類

 

namespace MvcApplication1.CustomerMetaProvider
{
    public class CustomerMetadataProvider : ModelMetadataProvider
    {
        public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType)
        {
            throw new NotImplementedException();
        }
        public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName)
        {
            throw new NotImplementedException();
        }
        public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType)
        {
            throw new NotImplementedException();
        }
    }
    public class Contact
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string EmailAddress { get; set; }
    }
}

 

應用上面的提供系統,要在Global.asax.cs   的Application_Start中加上一句  ModelMetadataProviders.Current = new CustomModelMetadataProviderWithConfig();

這樣就要MVC項目中當模型綁定和為屬性呈現元素時候都要從上面自定義的元數據提供系統提供ModelMetaData,所以上面的3個方法一定要重寫。

本例子沒實現這3個方法,待補充!

 

 

 

 

至此,模型元數據的意義,模型元數據定制,自定義模型元數據提供系統,以及自定義html模版 都研究完成。

再加上簽名的 模型綁定器,自定義驗證特性,自定義驗證特性的客戶端驗證都已完成。

目前還剩下 自定義值提供器 和 自定義視圖模版和視圖結構。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM