ASP.NET MVC 內建的資料標註驗證屬於 Model 驅動:驗證規則直接標註在 Model 類別或屬性上。這導致同一個 Model 在不同業務情境下(如不同職位應徵者的年齡、技能要求不同)無法套用不同規則,嚴重限制 Model 重用彈性。
透過擴充 MVC 驗證管線,實作「一個 Model,多組驗證規則,依情境切換」的機制。
自訂 RangeValidatorAttribute(繼承 ValidationAttribute),新增 RuleName 屬性區分規則集:
public class Person
{
[DisplayName("姓名")]
public string Name { get; set; }
[DisplayName("性別")]
public string Gender { get; set; }
[DisplayName("年齡")]
[RangeValidator(10, 20, RuleName = "Rule1", ErrorMessage = "{0}必須在{1}和{2}之間!")]
[RangeValidator(20, 30, RuleName = "Rule2", ErrorMessage = "{0}必須在{1}和{2}之間!")]
[RangeValidator(30, 40, RuleName = "Rule3", ErrorMessage = "{0}必須在{1}和{2}之間!")]
public int Age { get; set; }
}
Age 屬性同時套用三組規則,分別對應 Rule1 (10-20歲)、Rule2 (20-30歲)、Rule3 (30-40歲)。
自訂 ValidationRuleAttribute 標註於 Controller 或 Action,指定當前情境使用的規則名稱。Action 層級優先於 Controller 層級:
[ValidationRule("Rule3")] // 預設使用 Rule3
public class HomeController : RuleBasedController
{
public ActionResult Index() { ... } // 使用 Rule3
[ValidationRule("Rule1")]
public ActionResult Rule1() { ... } // 使用 Rule1
[ValidationRule("Rule2")]
public ActionResult Rule2() { ... } // 使用 Rule2
}
繼承 DataAnnotationsModelValidatorProvider,覆寫 GetValidators:
ControllerContext.RouteData.DataTokens 或 ActionDescriptor 取得當前 ValidationRule 名稱。RuleName 符合的 ValidationAttribute。ModelValidator。View 使用標準 Html.EditorForModel(),配合 jquery.validate.unobtrusive.js,自動產生對應規則的 data-val-* 屬性,無需修改前端程式碼。

透過擴充 ModelValidatorProvider 與自訂驗證屬性,打破傳統 Model 驗證的單一規則限制,實現真正的情境驅動驗證,大幅提升 Model 重用性與系統維護性。