我目前正在使用MVC4数据注释来处理验证.我正在开发一个非常国际化的网站,因此我将所有文本保存在资源文件中.
我还想在资源文件中保留正则表达式以进行验证,这样我就可以使用相同的代码来检查,例如,Post Codes(UK)和Zip Codes(US),只需使用不同的RegEx(以及不同名称的资源等) ).
我有以下属性已经从资源文件中提取错误消息.我怎样才能从资源文件中获取正则表达式?
[RegularExpression(@"^[\w]{1,2}[0-9]{1,2}[\w]?\s?[0-9]{1,2}[\w]{1,2}$",ErrorMessageResourceType = typeof(Resources.ValidationMessages),ErrorMessageResourceName = "validPostcode")]
编辑(再次)
我现在在哪里
在Global.asax.cs中,我添加了以下行以确保调用客户端验证
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(LocalisedAttribute),typeof(RegularExpressionAttributeAdapter));
[Localised(typeof(Resources.FormValidation),"postcodeRegEx","postcodeMsg")]
最后,本地化正则表达式验证的属性扩展
public class LocalisedAttribute : RegularExpressionAttribute { public LocalisedAttribute(Type resource,string regularExpression,string errorMessage) : base(GetRegex(regularExpression)) { ErrorMessageResourceType = resource; ErrorMessageResourceName = errorMessage; } private static string GetRegex(string value) { return Resources.FormValidation.ResourceManager.GetString(value); } }
这是有效的,但只是我第一次在启动应用程序时使用它.
我将打开另一个问题来解决这个问题 – 它与原始请求没有直接关系,似乎与大多数人的实现没有关系,似乎并不特定于数据注释.
解决方法
我已经有一些扩展的RegularExpressionAttribute实现,允许使用资源进行正则表达式模式.看起来像:
public class RegularExpressionExAttribute : RegularExpressionAttribute,IClientValidatable { private Regex regex { get; set; } private string pattern; private string resourceName; private Type resourceType; /// <summary> /// constructor,calls base with ".*" basic regex /// </summary> /// <param name="resName">resource key</param> /// <param name="resType">resource type</param> public RegularExpressionExAttribute(string resName,Type resType) : base(".*") { resourceName = resName; resourceType = resType; } /// <summary> /// override RegularExpressionAttribute property /// </summary> public new string Pattern { get { SetupRegex(); return pattern; } } /// <summary> /// loads regex from resources /// </summary> private void SetupRegex() { ResourceAccessor ra = new ResourceAccessor(resourceName,resourceType); pattern = ra.resourceValue; regex = new Regex(pattern); } /// <summary> /// override validation with our regex /// </summary> /// <param name="value">string for validation</param> /// <returns></returns> public override bool IsValid(object value) { SetupRegex(); string val = Convert.ToString(value); if (string.IsNullOrEmpty(val)) return true; var m = regex.Match(val); return (m.Success && (m.Index == 0)); } public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata MetaData,ControllerContext controllerContext) { yield return new ModelClientValidationRegexRule(base.ErrorMessageString,this.Pattern); } }
此外,它还使用ResourceAccessor类从资源中获取正则表达式
public class ResourceAccessor { private string resourceName; private Type resourceType; private Func<string> accessor; private string _resourceValue; public ResourceAccessor(string resourceName,Type resourceType) { this.resourceName = resourceName; this.resourceType = resourceType; } public string resourceValue { get { SetupAccessor(); return accessor(); } } private void SetupAccessor() { if (accessor != null) //already set return; string localValue = _resourceValue; bool flag1 = !string.IsNullOrEmpty(resourceName); bool flag2 = !string.IsNullOrEmpty(localValue); bool flag3 = resourceType != (Type)null; if (flag1 == flag2) { throw new InvalidOperationException("Can't set resource value"); } if (flag3 != flag1) { throw new InvalidOperationException("Resource name and type required"); } if (flag1) PropertyLookup(); else { accessor = (Func<string>)(() => localValue); } } private void PropertyLookup() { if (resourceType == (Type)null || string.IsNullOrEmpty(resourceName)) { throw new InvalidOperationException("Resource name and type required"); } PropertyInfo property = resourceType.GetProperty(resourceName,BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (property != (PropertyInfo)null) { MethodInfo getMethod = property.GetGetMethod(true); if (getMethod == (MethodInfo)null || !getMethod.IsAssembly && !getMethod.IsPublic) property = (PropertyInfo)null; } if (property == (PropertyInfo)null) { throw new InvalidOperationException("Resource type doesn't have property"); } else if (property.PropertyType != typeof(string)) { throw new InvalidOperationException("Resource type must be string"); } else { accessor = (Func<string>)(() => (string)property.GetValue((object)null,(object[])null)); } } }
以下是使用示例:
public class SignUpInput { [RegularExpressionEx("EmailValidationRegex",typeof(LocalizedResources),ErrorMessageResourceType = typeof(Messages),ErrorMessageResourceName = "invalidEmail")] public string Email { get; set; } }