對於Model驗證,理想的設計應該是場景驅動的,而不是Model(類型)驅動的,也就是對於同一個Model對象,在不同的使用場景中可能具有不同的驗證規則。舉個簡單的例子,對於一個表示應聘者的數據對象來說,針對應聘的崗位不同,肯定對應聘者的年齡、性別、專業技能等方面有不同的要求。但是ASP.NET MVC的Model驗證確是Model驅動的,因為驗證規則以驗證特性的形式應用到Model類型及其屬性上。這樣的驗證方式實際上限制了Model類型在基於不同驗證規則的使用場景中的重用。通過上一篇文章《將ValidationAttribute應用到參數上》的擴展我們將驗證特性直接應用在參數上變成了可能,這從一定程度上解決了這個問題,但是只能解決部分問題,因為應用到參數的驗證特性只能用於針對參數類型級別的驗證,而不能用於針對參數類型屬性級別的驗證(源代碼從這裡下載)。
一、同一個Model在采用不同的驗證規則
現在我們通過利用對ASP.NET MVC的擴展來實現一種基於不同驗證規則的Model驗證。為了讓讀者對這種認證方式有一個感官的認識,我們來看看這個擴展最終實現怎樣的驗證效果。在通過Visual Studio的ASP.NET MVC 項目模板創建的空Web應用中,我們定義了如下一個Person類型作為Model。
1: public class Person
2: {
3: [DisplayName("姓名")]
4: public string Name { get; set; }
5:
6: [DisplayName("性別")]
7: public string Gender { get; set; }
8:
9: [DisplayName("年齡")]
10: [RangeValidator(10, 20, RuleName = "Rule1", ErrorMessage = "{0}必須在{1}和{2}之間!")]
11: [RangeValidator(20, 30, RuleName = "Rule2", ErrorMessage = "{0}必須在{1}和{2}之間!")]
12: [RangeValidator(30, 40, RuleName = "Rule3", ErrorMessage = "{0}必須在{1}和{2}之間!")]
13: public int Age { get; set; }
14: }
在表示年齡的Age屬性上應用了三個RangeValidatorAttribute(不是RangeAttribute),它們對應針對年齡的三種不同的驗證規則,RuleName屬性表示規則名稱。三種驗證規則(Rule1、Rule2和Rule3)分別要求年齡分別在10到20、20到30和30到40歲之間。
然後我們定義了具有如下定義HomeController,它具有三組Action方法(Index、Rule1和Rule2)。方法Rule1、Rule2和HomeController類上應用了一個ValidationRuleAttribute特性用於指定了當前采用的驗證規則。用於指定驗證規則的ValidationRuleAttribute特性可以同時應用於Controller類型和Action方法上,應用於後者的ValidationRuleAttribute特性具有更高的優先級。針對HomeController的定義,Action方法Index、Rule1和Rule2分別采用的驗證規則為Rule3、Rule1和Rule2。
1: [ValidationRule("Rule3")]
2: public class HomeController : RuleBasedController
3: {
4: public ActionResult Index()
5: {
6: return View("person", new Person());
7: }
8: [HttpPost]
9: public ActionResult Index(Person person)
10: {
11: return View("person", person);
12: }
13:
14: [ValidationRule("Rule1")]
15: public ActionResult Rule1()
16: {
17: return View("person", new Person());
18: }
19: [HttpPost]
20: [ValidationRule("Rule1")]
21: public ActionResult Rule1(Person person)
22: {
23: return View("person", person);
24: }
25:
26: [ValidationRule("Rule2")]
27: public ActionResult Rule2()
28: {
29: return View("person", new Person());
30: }
31: [HttpPost]
32: [ValidationRule("Rule2")]
33: public ActionResult Rule2(Person person)
34: {
35: return View("person", person);
36: }
37: }
定義在HomeController中的6個方法均將創建的/接收的Person對象呈現到名為Person的View中,該View的定義如下所示。這是一個將Person類型作為Model的強類型View,在該View中我們將作為Model的Person對象以編輯模式呈現在一個表單中,並在表單中提供一個提交按鈕。
1: @model Person
2: @using (Html.BeginForm())
3: {
4: @Html.EditorForModel()
5: <input type="submit" value="保存" />
6: }
現在運行我們的程序,並通過在浏覽器中指定相應的地址分別訪問定義在HomeController的三個Action(Index、Rule1和Rule2),一個用於編輯個人信息的表單會呈現出來。然後我們根據三個Action方法采用的驗證規則輸入不合法的年齡,然後點擊“保存”按鈕,我們會看到輸入的年齡按照對應的規則被驗證了,具體的驗證效果如下圖所示。