ASP.NET Core 自定义验证错误消息未本地化

San*_*dro 1 custom-attributes asp.net-core asp.net-core-localization

我想在自定义属性中实现本地化,以检查该属性是否是有效的 IP 地址或主机名。到目前为止,验证工作正常,但我的问题是,尽管我的本地切换为德语,但我只收到默认的英语错误消息。我正在处理资源文件。我不想为此实现客户端验证。我知道有实现适配器的方法,但如果我错了,请纠正我,这仅用于客户端验证。

我的自定义验证类:

public class IPAddressOrHostnameAttribute : ValidationAttribute
{
     public IPAddressOrHostnameAttribute(string propertyName, object desiredvalue, string errorMessage)
    {
        PropertyName = propertyName;
        DesiredValue = desiredvalue;
        ErrorMessage = errorMessage;
    }

    private string PropertyName { get; }
    private object DesiredValue { get; }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        var instance = context.ObjectInstance;
        var type = instance.GetType();
        var propertyValue = type.GetProperty(PropertyName).GetValue(instance, null);
        if (propertyValue.ToString() == DesiredValue.ToString() && value != null)
        {
            if (Regex.IsMatch(value.ToString(), AckConstants.VALIDIPADDRESSREGEX)
                || Regex.IsMatch(value.ToString(), AckConstants.VALIDHOSTNAMEREGEX))
            {
                return ValidationResult.Success;
            }

            return new ValidationResult(ErrorMessage);
        }

        return ValidationResult.Success;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的模型类:

  [Required(ErrorMessage = "The field {0} is required")]
        [RegularExpression(@"^\S*$", ErrorMessage = "No white spaces allowed.")]
        [IPAddressOrHostname(nameof(IsFileAdapter), true, "Please enter a valid IP address or hostname")]
        [IPAddress(nameof(IsFileAdapter), false, "Please enter a valid IP address")]
        [Display(Name = "Destination")]
        public string Destination { get; set; }
Run Code Online (Sandbox Code Playgroud)

我的启动类配置DataAnnotationLocalizerProvider

services
                .AddMvc()
                .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix,
                    opts => { opts.ResourcesPath = "Resources"; })
                .AddDataAnnotationsLocalization(options =>
                {
                    options.DataAnnotationLocalizerProvider = (type, factory) =>
                        factory.Create(typeof(SharedResource)); // SharedResource is the class where the DataAnnotations (translations) will be stored.
                })
Run Code Online (Sandbox Code Playgroud)

本地化适用于默认属性,例如 egRequired等,但不适用于我的自定义验证属性。我不知道我的代码有什么问题。我已经阅读了ASP.NET Core 自定义验证属性本地化的 stackoverflow 帖子,但我不明白为什么我的服务器端本地化验证不起作用。希望有人可以帮助我或给我一个如何让它工作的例子,因为这个问题让我发疯。

Laz*_*iya 5

创建一个适配器可能是一个解决方案,但它太昂贵了!您必须创建适配器,然后创建适配器提供程序,然后您需要在启动时注册它!这是太多的工作。

更短的解决方案是通过ValidationContext.GetService以下方式在自定义验证属性中获取本地化服务:

如果您使用的是内置的本地化服务将是IStringLocalizer,如果你使用的是定制的本地化服务如(MyLocailzer),您可以通过它来解析的访问GetService(typeof(MyLocaizer))方法。请参阅以下示例:

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    var _localizationService = (IStringLocalizer)validationContext.GetService(typeof(IStringLocalizer));

    var localizedError = _localizationService[ErrorMessage];

    //
    // do your custom validation
    //
    // if validation result is wrong
        return new ValidationResult(localizedError);

    // if validation result is correct
    return ValidationResult.Success;
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句, ValidationAttribute 已经具有ErrorMessage属性,因此您不必在自定义属性中定义它。

public IPAddressOrHostnameAttribute(string propertyName, object desiredvalue /*, string errorMessage*/)
    {
        PropertyName = propertyName;
        DesiredValue = desiredvalue;
        // ErrorMessage = errorMessage;
    }

Run Code Online (Sandbox Code Playgroud)

像其他属性一样使用它:

[IPAddressOrHostname(nameof(IsFileAdapter), true, ErrorMessage = "Please enter a valid IP address or hostname")]
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢@Laz Ziya 的回答,它对我完成工作有很大帮助。我正在使用共享资源。我不得不稍微延长你的线路,但现在可以了。`var localizationService = (IStringLocalizer)validationContext.GetService(typeof(IStringLocalizer<SharedResource>)); var localizedError = 本地化服务[ErrorMessage];` (3认同)
  • 就我而言,我必须这样做才能工作 - var _localizationService = (IStringLocalizer<MyCustomClass>)validationContext.GetService(typeof(IStringLocalizer<MyCustomClass>)); (2认同)