ASP.NET MVC 2 驗證消息本地化策略擴展
ASP.NET MVC2 結合System.ComponentModel.DataAnnotations 提供了一套非常有效的實體驗證框架。對于錯誤信息的處理,它默認提供了兩種選擇:
- 字符串常量
- 從程序集資源文件讀取
但是在我們這里,我們有一套自己的資源文件方案,也就是我們需要自己控件錯誤信息的本地化操作。由于在元數據,我們只能提供常量,無法進行字符串操作。一種比較直接和麻煩的辦法就是重寫所有的驗證規則,在驗證規則中對字符串常量進行本地化操作。
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public class CustomValidationAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
{
public CustomValidationAttribute(string message)
: base(() => message.Localize())
{
}
}
public class CustomValidationAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
{
public CustomValidationAttribute(string message)
: base(() => message.Localize())
{
}
}
但是這樣做,一方面會比較麻煩,所有的驗證規則我們都要進行重寫;另一方面我們在設計model時就是特別的小心使用我們自己重寫過的規則才能達到我們的目的,這將大大降低開發體驗。為此,今天特別再次對照MVC2的源碼,希望能找到一個可用的擴展點來解決這個問題。最終發現我們可以通過重寫DataAnnotationsModelValidatorProvider的GetValidators方法來達到我們希望的效果:
public class CustomDataAnnotationsModelValidatorProvider : System.Web.Mvc.DataAnnotationsModelValidatorProvider
{
protected override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable attributes)
{
foreach (ValidationAttribute attribute in attributes.OfType())
{
if (!string.IsNullOrWhiteSpace(attribute.ErrorMessage))
{
attribute.ErrorMessage = attribute.ErrorMessage.Localize();
}
}
var validators = base.GetValidators(metadata, context, attributes);
return validators;
}
}
{
protected override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable attributes)
{
foreach (ValidationAttribute attribute in attributes.OfType())
{
if (!string.IsNullOrWhiteSpace(attribute.ErrorMessage))
{
attribute.ErrorMessage = attribute.ErrorMessage.Localize();
}
}
var validators = base.GetValidators(metadata, context, attributes);
return validators;
}
}
代碼非常簡單,我們只是在調用GetValidators方法之前,對attribute的錯誤消息進行一次本地化操作處理即可。通過這一次處理,我們可以同步處理客戶端驗證消息和服務器端驗證消息的本地化。下面的工作就是用這個Provider來代替它的父類,在Global.asax添加下面的代碼即可完成:
ModelValidatorProviders.Providers.RemoveAt(0);
ModelValidatorProviders.Providers.Insert(0, new CustomDataAnnotationsModelValidatorProvider());
ModelValidatorProviders.Providers.Insert(0, new CustomDataAnnotationsModelValidatorProvider());
通過這樣一個小小的擴展,就可以很完美的達到我們的目的。不過,為了這個小擴展,卻花費了我們不少的時間。
全站熱搜