我正在尝试在asp.net core 1.0中的自定义验证属性中实现本地化。这是我简化的viewmodel:
public class EditPasswordViewModel
{
[Required(ErrorMessage = "OldPasswordRequired")]
[DataType(DataType.Password)]
[CheckOldPassword(ErrorMessage = "OldPasswordWrong")]
public string OldPassword { get; set; }
}
“OldPasswordRequired”的本地化工作正常。但是,我的自定义属性的本地化不起作用,并始终返回“OldPasswordWrong”消息。这是代码:
public class CheckOldPasswordAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object classInstance, ValidationContext validationContext)
{
if (oldPasswordSaved == oldPasswordTyped) //simplified
{
return ValidationResult.Success;
}
else
{
string errorMessage = FormatErrorMessage(ErrorMessageString);
return new ValidationResult(errorMessage);
}
}
}
ErrorMessageString始终为“OldPasswordWrong”,FormatErrorMessage始终返回“OldPasswordWrong”。我究竟做错了什么? 我正在使用新的asp.net核心数据注释本地化,所以我没有使用ErrorMessageResourceName和ErrorMessageResourceType属性(我没有任何ViewModel.Designer.cs)。
答案 0 :(得分:12)
实施适配器以进行本地化:
public class RequiredIfAttributeAdapter : AttributeAdapterBase<RequiredIfAttribute>
{
public RequiredIfAttributeAdapter(RequiredIfAttribute attribute, IStringLocalizer stringLocalizer) : base(attribute, stringLocalizer) {}
public override void AddValidation(ClientModelValidationContext context) {}
public override string GetErrorMessage(ModelValidationContextBase validationContext)
{
return GetErrorMessage(validationContext.ModelMetadata, validationContext.ModelMetadata.GetDisplayName());
}
}
为适配器实现提供程序:
public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
{
private readonly IValidationAttributeAdapterProvider _baseProvider = new ValidationAttributeAdapterProvider();
public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
{
if (attribute is RequiredIfAttribute)
return new RequiredIfAttributeAdapter(attribute as RequiredIfAttribute, stringLocalizer);
else
return _baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
}
}
在Startup.cs中注册提供程序:
services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
此博客的致谢:https://blogs.msdn.microsoft.com/mvpawardprogram/2017/01/03/asp-net-core-mvc/
答案 1 :(得分:3)
拉明的答案是正确的答案。但是我决定走另一条路,因此在很多情况下都不必编写适配器和适配器提供程序。
这个想法是将特定的字符串本地化程序包装在服务接口中,然后从验证属性本身获取它。
public class CPFAttribute: ValidationAttribute
{
public CPFAttribute()
{
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string cpf;
try
{
cpf = (string)value;
}
catch (Exception)
{
return new ValidationResult(GetErrorMessage(validationContext));
}
if (string.IsNullOrEmpty(cpf) || cpf.Length != 11 || !StringUtil.IsDigitsOnly(cpf))
{
return new ValidationResult(GetErrorMessage(validationContext));
}
return ValidationResult.Success;
}
private string GetErrorMessage(ValidationContext validationContext)
{
if (string.IsNullOrEmpty(ErrorMessage))
{
return "Invalid CPF";
}
ErrorMessageTranslationService errorTranslation = validationContext.GetService(typeof(ErrorMessageTranslationService)) as ErrorMessageTranslationService;
return errorTranslation.GetLocalizedError(ErrorMessage);
}
}
然后可以将服务创建为:
public class ErrorMessageTranslationService
{
private readonly IStringLocalizer<SharedResource> _sharedLocalizer;
public ErrorMessageTranslationService(IStringLocalizer<SharedResource> sharedLocalizer)
{
_sharedLocalizer = sharedLocalizer;
}
public string GetLocalizedError(string errorKey)
{
return _sharedLocalizer[errorKey];
}
}
该服务可以在Startup类中注册为单例。
services.AddSingleton<ErrorMessageTranslationService>();
如果需要将这些验证属性分解为另一个程序集,则只需为此翻译服务创建一个接口即可,您创建的所有验证属性都可以引用该接口。
答案 2 :(得分:0)
您需要指定文化。 formaterrormesage会做什么?它会处理文化吗?