MVC中的客戶端及服務端模型驗證信息都以ModelMetadata類型作為承載,在獲得屬性的ModelMetadata之后(還不知道怎么獲取ModelMetadata的童鞋請自行惡補),我們可以輕松得到一些我們在模型中定義的特性,比如顯示名稱、是否只讀、是否必須、注釋、數據類型等,但是並不包括Range和StringLength這兩個需要驗證的特性,我把ModelMetadata對象翻個底朝天也沒找到設置的值。
於是乎,只能通過反射來獲取特性的定義信息了,以下代碼能夠獲取到該屬性定義的所有特性:
var attrs = metadata.ContainerType.GetProperty(metadata.PropertyName).CustomAttributes;
然后我們遍歷之,尋找我們要的類型,這里以Range為例:
foreach (var f in attrs) { if (f.AttributeType == typeof(RangeAttribute) && f.ConstructorArguments[0].ArgumentType != typeof(Type)) { //TODO:對其取值 } }
代碼中首先判斷類型是否一致,接着判斷第一個構造參數是否不為Type類型(Range特性有三個構造函數,其中第一個參數為Type類型的max和min值可以是任何類型,在這里我們不需處理這個構造函數的數據,只對另外兩種傳輸int或double的構造函數感興趣)。
然后就可以取值了:
double Min = ((IConvertible)f.ConstructorArguments[0].Value).ToDouble(null); double Max = ((IConvertible)f.ConstructorArguments[1].Value).ToDouble(null);
這里我們需要double類型的值,所以不管傳入的是int還是double類型參數,統一使用轉換的方式轉換為double。
這樣我們就可以在發往客戶端頁面中進行基本的限制了:
<input type="number" name="points" min="@Min" max="@Max" />
同理可以取來StringLength的信息用來限制文本輸入框的可輸入字符長度:
<input maxlength="@Length">
還可以結合JS寫一些自定義的客戶端驗證。
服務端的模型驗證不用我們操心,這兩個特性會在驗證時正確觸發的。
使用這個技巧,你還可以實現一些自定義的特性,以控制客戶端的頁面功能。