ASP.NET Core Authentication Attribute Attribute

I am trying to implement localization in a custom validation attribute in asp.net core 1.0. This is my simplified view model:

public class EditPasswordViewModel { [Required(ErrorMessage = "OldPasswordRequired")] [DataType(DataType.Password)] [CheckOldPassword(ErrorMessage = "OldPasswordWrong")] public string OldPassword { get; set; } } 

The localization of "OldPasswordRequired" is working fine. However, the localization of my user attribute does not work and always returns the message "OldPasswordWrong". This is the code:

 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 is always equal to "OldPasswordWrong", and FormatErrorMessage always returns "OldPasswordWrong". What am I doing wrong? I use the new localizations of asp.net master data annotations, so I do not use the ErrorMessageResourceName and ErrorMessageResourceType attributes (I don't have ViewModel.Designer.cs).

+9
source share
3 answers

Implement the 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 adapter provider (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 a provider in Startup.cs:

 services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>(); 

Credits on this blog: https://blogs.msdn.microsoft.com/mvpawardprogram/2017/01/03/asp-net-core-mvc/

+15
source

The answer from Ramin is the correct answer. But I decided to go the other way, so I do not need 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]; } } 

A service can be registered as single in the Startup class.

 services.AddSingleton<ErrorMessageTranslationService>(); 

If you need to consider these verification attributes in another assembly, simply create an interface for this translation service, which can be referenced by all the verification attributes you created.

+2
source

You need to specify the culture. What will formaterrormesage do? Will they cultivate the culture?

Check this link

0
source

Source: https://habr.com/ru/post/1265432/


All Articles