I\'m trying to implement localization in a custom validation attribute in asp.net core 1.0. This is my simplified viewmodel:
public class EditPasswordViewMod
The answer from Ramin is the correct answer. But I decided to take another path, so I don't have to write adapters and adapter providers for many cases.
The idea is to wrap your specific string localizer in a service interface, and get it from the validation attribute itself.
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);
}
}
Then the service can be created as:
public class ErrorMessageTranslationService
{
private readonly IStringLocalizer<SharedResource> _sharedLocalizer;
public ErrorMessageTranslationService(IStringLocalizer<SharedResource> sharedLocalizer)
{
_sharedLocalizer = sharedLocalizer;
}
public string GetLocalizedError(string errorKey)
{
return _sharedLocalizer[errorKey];
}
}
The service can be registered as a singleton, in the Startup class.
services.AddSingleton<ErrorMessageTranslationService>();
If these validation attributes need to be factored to another assembly, just create an interface for this translation service that can be referenced by all validation attributes you create.
You need to specify the culture. What does formaterrormesage will do? Will it handle the culture?
Check this link
Implement an adapter for localization:
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());
}
}
Implement a provider for the adapter(s):
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);
}
}
Register the provider in Startup.cs:
services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
Credits to this blog: https://blogs.msdn.microsoft.com/mvpawardprogram/2017/01/03/asp-net-core-mvc/