ASP.NET MVC 預設僅解析 Model 類別及其屬性上的 ValidationAttribute。若能直接標註於 Action 參數,將解決兩大痛點:
int、string 等無法加上屬性。ModelValidator 建立時基於 ModelMetadata(描述型別/屬性),完全忽略 ParameterDescriptor 上的屬性。需擴充管線使參數屬性參與驗證。
覆寫 GetParameterValue,在繫結參數前將 ParameterDescriptor 暫存至 ControllerContext.RouteData.DataTokens,繫結後移除:
public class ParameterValidationActionInvoker : ControllerActionInvoker
{
protected override object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
try
{
controllerContext.RouteData.DataTokens.Add("ParameterDescriptor", parameterDescriptor);
return base.GetParameterValue(controllerContext, parameterDescriptor);
}
finally
{
controllerContext.RouteData.DataTokens.Remove("ParameterDescriptor");
}
}
}
public class ParameterValidationAsyncActionInvoker : AsyncControllerActionInvoker
{
protected override object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
try
{
controllerContext.RouteData.DataTokens.Add("ParameterDescriptor", parameterDescriptor);
return base.GetParameterValue(controllerContext, parameterDescriptor);
}
finally
{
controllerContext.RouteData.DataTokens.Remove("ParameterDescriptor");
}
}
}
在 Global.asax 或 Controller 工廠中替換預設 Invoker:
ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
// 或在 Controller 建構子指定
public HomeController() { this.ActionInvoker = new ParameterValidationActionInvoker(); }
繼承 DataAnnotationsModelValidatorProvider,覆寫 GetValidators:
ControllerContext.RouteData.DataTokens["ParameterDescriptor"] 取得 ParameterDescriptor。parameterDescriptor.GetCustomAttributes(true) 獲取參數上的 ValidationAttribute。ModelValidator。public ActionResult Register(
[Required(ErrorMessage = "請輸入帳號")]
[StringLength(20, ErrorMessage = "帳號長度不可超過 20 字元")]
string username,
[Required(ErrorMessage = "請輸入密碼")]
[DataType(DataType.Password)]
string password)
{
// 參數層級驗證自動生效
}
透過自訂 ActionInvoker 攔獲 ParameterDescriptor 並存入 RouteData.DataTokens,配合擴充 ModelValidatorProvider 讀取參數屬性,成功將 ValidationAttribute 擴展至 Action 參數層級,靈活解決原生型別驗證與多情境驗證需求。