在博客园里有这篇帖子讲的已经很全面了,但是我认为还不够优雅,整个看起来好混乱,像国外这位老兄的帖子处理的就很整洁,简单记录如下:
通常的国际化处理方法
public class User { [Required(ErrorMessageResourceName = "Validation_Required", ErrorMessageResourceType = typeof(ModelTranslations))] [LocalizedDisplayNameAttribute("User_Id", NameResourceType=typeof(ModelTranslations))] public int Id { get; set; } [Required(ErrorMessageResourceName = "Validation_Required", ErrorMessageResourceType = typeof(ModelTranslations))] [StringLength(40, ErrorMessageResourceName = "Validation_StringLength", ErrorMessageResourceType = typeof(ModelTranslations))] [LocalizedDisplayNameAttribute("User_FirstName", NameResourceType=typeof(ModelTranslations))] public string FirstName { get; set; } [Required(ErrorMessageResourceName = "Validation_Required", ErrorMessageResourceType = typeof(ModelTranslations))] [StringLength(40, ErrorMessageResourceName = "Validation_StringLength", ErrorMessageResourceType = typeof(ModelTranslations))] [LocalizedDisplayNameAttribute("User_LastName", NameResourceType=typeof(ModelTranslations))] public string LastName { get; set; } }
可以看出来很混乱。
public class User { [Required] [LocalizedDisplayNameAttribute("User_Id")] public int Id { get; set; } [Required] [StringLength(40)] [LocalizedDisplayNameAttribute("User_FirstName")] public string FirstName { get; set; } [Required] [StringLength(40)] [LocalizedDisplayNameAttribute("User_LastName")] public string LastName { get; set; } }
是不是整洁多了,但是这个整洁的代价就是要背后要写代码的
public class RequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute { private string _displayName; public RequiredAttribute() { ErrorMessageResourceName = "Validation_Required"; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { _displayName = validationContext.DisplayName; return base.IsValid(value, validationContext); } public override string FormatErrorMessage(string name) { var msg = LanguageService.Instance.Translate(ErrorMessageResourceName); return string.Format(msg, _displayName); } }
这个是验证属性的实现代码。
ublic class LocalizedDisplayNameAttribute : DisplayNameAttribute { private PropertyInfo _nameProperty; private Type _resourceType; public LocalizedDisplayNameAttribute(string className, string propertyName) : base(className + (propertyName == null ? "_Class" : ("_" + propertyName))) { } public override string DisplayName { get { return LanguageService.Instance.Translate(base.DisplayName) ?? "**" + base.DisplayName + "**"; } } }
这是实现DisplayName属性的实现代码
public class LanguageService { private static LanguageService _instance = new LanguageService(); private List<ResourceManager> _resourceManagers = new List<ResourceManager>(); private LanguageService() { } public static LanguageService Instance { get { return _instance; } } public void Add(ResourceManager mgr) { _resourceManagers.Add(mgr); } public string Translate(string key) { foreach (var item in _resourceManagers) { var value = item.GetString(key); if (value != null) return value; } return null; } }
这是上述类依赖的管理资源的代码。
但上述的解决办法对于客户端验证还是有问题,以下是一个简单的实现
public class RequiredAttributeAdapter : DataAnnotationsModelValidator<RequiredAttribute> { public RequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute) : base(metadata, context, attribute) { } public static void SelfRegister() { DataAnnotationsModelValidatorProvider .RegisterAdapter( typeof (RequiredAttribute), typeof (RequiredAttributeAdapter)); } public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() { return new[] { new ModelClientValidationRequiredRule(ErrorMessage) }; } }
然后在Global.asax里加一句
RequiredAttributeAdapter.SelfRegister();
Technorati 标签: ASP.NET MVC 验证 国际化
完。