[多國語系] MVC ViewModel自動載入語系資源-驗證訊息

    繼前一篇[多國語系] MVC ViewModel自動載入語系資源,此篇要講的是把一些常用的驗證自動加上語系,例:Required、Range...等。在基本的情況下我們在Property冠上Required,只要使用者未填值下按下Submit就會出現內建的錯誤訊息,如下:
中文 英文
image image

而要加上自訂的語系的話則需要再指定ErrorMessageResourceNameErrorMessageResourceType
image

改善目標

  • 不要設定語系名稱及語系型別
  • 自動為驗證Property跟資源檔作結合

1.先為資源名稱規則化

如下圖所示:以Model+底線+Property+驗證特性來命名
image

2.實作相關的驗證Adapter

如下目前只列出實作RequiredAttributeAdapter,其他請參考原始碼,程式重點:先判斷是否已有自行設定ErrorMessage,沒有則取資源檔,而取回若為空值則回傳系統內建訊息
   public class LocalizedRequiredAttributeAdapter : RequiredAttributeAdapter
    {
        public LocalizedRequiredAttributeAdapter( ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute)
            : base(metadata, context, attribute) { }

        
        public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
        {
            string errorMessage = null;
            if (this.Attribute.ErrorMessage == null && (this.Attribute.ErrorMessageResourceName == null || this.Attribute.ErrorMessageResourceType == null))
                errorMessage = MvcApplication.GlobalResourceStringProvider.GetModelString(Metadata.ContainerType, Metadata.PropertyName, "Required");

            if (string.IsNullOrEmpty(errorMessage))
                errorMessage = ErrorMessage; //取不到則還原成預設值
            return new[] { new ModelClientValidationRequiredRule(errorMessage) };
        }
    }

3.在Global.asax註冊相關的Adapter

 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            ResourceStringProvider rp = new ResourceStringProvider(Local.ResourceManager);
            ModelMetadataProviders.Current = new LocalizedModelMetadataProvider(rp);
            GlobalResourceStringProvider = rp;

           //註冊Adapter
            DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredAttribute), typeof(LocalizedRequiredAttributeAdapter));
            DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(StringLengthAttribute), typeof(LocalizedStringLengthAttributeAdapter));
            DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RangeAttribute), typeof(LocalizedRangeAttributeAdapter));
            DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(System.ComponentModel.DataAnnotations.CompareAttribute), typeof(LocalizedCompareAttributeAdapter));

        }

4.大功告成-顯示結果


針對要驗證的屬性不用再指定語系名稱及型別
 public class ProductModel
    {
        public int ProductId { get; set; }

        [StringLength(3)]
        [Required]
        public string ProductName { get; set; }

        public DateTime CreateDate { get; set; }

        [Range(100D, 300.55D)]
        public decimal Price { get; set; }

        public int Qty { get; set; }

        [Compare("Qty")]
        public int Qty_Old { get; set; }
    }

image

參考來源


http://thatextramile.be/blog/2011/04/customizing-asp-net-mvcs-required-property-validation-messages/
http://social.msdn.microsoft.com/Forums/en-US/77514514-8375-480a-a905-e636eed20064/aspnet-mvc-validate-?forum=236

本篇原始碼
https://github.com/kimx/LocalizedModelProviderLab/

這個網誌中的熱門文章

[.NET Core] 將專案發行至IIS

[TFS] 分支與合併