Service層的部份到目前為止已經介紹了基本的CRUD,搜索方面的自動處理和一些資料驗證的部份。是時候來切換一下看在View的部份框架還能夠幫到什麼。
在這一篇將會介紹所謂的Model Metadata,並且概念上來說如何用框架打造一些好用的功能,並且在下一篇來實作。
首先來看一下所謂的Model Metadata。當我們傳一個ViewModel到View的時候,Mvc其實有做一些處理,透過Reflection的方式產出這個ViewModel的Model Metadata。
有了這些Model Metadata,在View才能夠使用一些Html的Helper來產生一些html。例如,Html.ValidationMessageFor就會依照Model Metadata的ModelStateDictionary來顯示欄位的錯誤訊息。
另外一個例子就是,像我們在ViewModel欄位會定義DisplayAttribute讓使用Html.DisplayFor的時候,顯示的名稱不是Property欄位名稱,而是 DisplayAttribute設定的內容。
Html Helper能夠得到這些內容,其實都是從Model Metadata取得資料。因此,換個角度想,如果我們能夠在Model State裡面塞一些資訊,在View裡面就可以變得更加簡單,因此我們就來看一下框架要做到的效果是什麼。
Model Metadata基本上就是一個ViewModel欄位相關資訊,而如何告訴這些資訊是透過DataAnnoationation的Attribute來做到。
ModelMetadata如何產生
上面這張圖的上半段是介紹一般我們定義ViewModel的DataAnnotation之後,在View的呈現,Mvc的HtmlHelper就會幫我們產生出DataAnnotation所做的設定內容。
下面則是基本Mvc在背後幫我們做的事情。首先,在Mvc有一個ModelMetadataProvider(準確一點描述應該是一個DataAnnotationsModelMetadataProvider),會依照DataAnnotation產生出ModelMetadata。
有了這個ModelMetadata,HtmlHelper和EditorTemplates,就可以用這些資訊,顯示出這些內容。
到目前為止我們對於ModelMetadata有些概念之後,下一個問題就是,這個對於我們有什麼幫助?
我們先來思考一個問題,假設今天我有一個欄位代表著Email,請問我需要做什麼Mvc才會產生出html 5 的 email input?
答案是我們需要對哪一個property增加一個EmailAttribute。
可 是換一個角度想,如果一個欄位代表是email,這個欄位通常名稱一定會是xxxEmail,甚至可能就叫做Email。我們能不能夠就依照這個欄位名字 決定讓Mvc產生出html 5的email Input?而不需要自己額外用一個EmailAttribute說這是一個Email。
或者說假設今天我需要產生出來的表單是以TextArea顯示而不是用input的text顯示,以目前Mvc來說我們需要把Property加上DataTypeAttribute設定為「MultilineText」就可以。
假設我們整個團隊的Property命名規則就是,如果要用TextArea,Property 名稱一定要有TextArea,例如ContentTextArea,那不能夠依照Property名稱來決定這個欄位是TextArea嗎?
上面舉得兩個例子,其實都是在提到一個內容,那就是,UI顯示的內容可以進一步依照我們團隊自己的Convention(習慣),例如NamingConvention(命名習慣)去產生出正確的UI 內容,而不需要而外多加設定。
概念上面如下圖:
ExtensibleModelMetadataProvider示意圖
橘色的部分是框架的建設 造的。基本上,我們會有一個自訂的ModelMetadataProvider。這個ExtensibleModelMetadataProvider會 由DI注入一些Process的實作,這些實作才是實際上對ModelMetadata的處理。
有了這些Process的處理之後,ModelMetadata就會被改變。這個時候View顯示的時候就會依照這些ModelMetadata做呈現。
這一篇介紹了ModelMetadata的概念。有了ModelMetadata作為產生UI的一些額外資訊,在框架可以用Convention的方式來修改ModelMetadata達到產生對應的UI呈現。
在下一篇將會進入實際的實作。