Asp.net core ASP.NET核心自定义验证错误消息未本地化

Asp.net core ASP.NET核心自定义验证错误消息未本地化,asp.net-core,custom-attributes,asp.net-core-localization,Asp.net Core,Custom Attributes,Asp.net Core Localization,我想在自定义属性中实现本地化,以检查该属性是否为有效的IP地址或主机名。到目前为止,验证工作正常,但我的问题是,虽然我的本地语言已切换为德语,但我只收到默认的英语错误消息。我正在处理资源文件。我不想为此实现客户端验证。我知道有一种方法可以实现适配器,但如果我错了,请纠正我,这只是用于客户端验证 我的自定义验证类: public class IPAddressOrHostnameAttribute : ValidationAttribute { public IPAddressOrHos

我想在自定义属性中实现本地化,以检查该属性是否为有效的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;
    }
}
  [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; }
我的模型类:

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;
    }
}
  [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; }
我的startup类配置
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.
                })
本地化适用于默认属性,例如
Required
等,但不适用于我的自定义验证属性。我不知道我的代码出了什么问题。我已经阅读了stackoverflow文章,但我不明白为什么我的服务器端本地化验证不起作用。希望有人能帮助我,或者给我一个如何让它工作的例子,因为这个问题快把我逼疯了

我不想为此实现客户端验证。我知道有一种方法可以实现适配器,但如果我错了,请纠正我,这只是用于客户端验证

事实上,这不是事实。适配器并不意味着您必须使用客户端验证。请看

至于您的问题本身,您可以创建一个
适配器
,还可以创建一个
适配器提供程序
,以提供适配器:

公共类IPAddressOrHostnameAttributeAdapter:AttributeAdapterBase
{
公共IPAddressOrHostnameAttributeAdapter(IPAddressOrHostnameAttribute属性,IStringLocalizer stringLocalizer)
:base(属性,stringLocalizer)
{ }
公共重写void AddValidation(ClientModelValidationContext){}
公共重写字符串GetErrorMessage(ModelValidationContextBase validationContext)
{
返回GetErrorMessage(validationContext.ModelMetadata,validationContext.ModelMetadata.GetDisplayName());
}
}
公共类IPAddressOrHostnameAttributeAdapterProvider:IValidationAttributeAdapterProvider
{
private readonly IValizationAttributeAdapterProvider fallback=新的ValidationAttributeAdapterProvider();
public IAttributeAdapter GetAttributeAdapter(验证属性,IStringLocalizer stringLocalizer)
{
var attr=作为IPAddressOrHostnameAttribute的属性;
返回attr==null?
this.fallback.GetAttributeAdapter(属性,stringLocalizer):
新的IPAddressOrHostnameAttributeAdapter(attr,stringLocalizer);
}
}
此外,请确保此服务已在DI容器中注册:

services.AddSingleton();
最后,如果您使用querystring作为区域性提供程序,请不要忘记在表单操作中附加
culture=de

@{ var __culture = Context.Features.Get<IRequestCultureFeature>().RequestCulture.Culture.ToString(); }

<form asp-action="Create" asp-route-culture="@__culture">
    ....
</form>
@{var\uuu culture=Context.Features.Get().RequestCulture.culture.ToString();}
....

演示的屏幕截图

我不想为此实现客户端验证。我知道有一种方法可以实现适配器,但如果我错了,请纠正我,这只是用于客户端验证

事实上,这不是事实。适配器并不意味着您必须使用客户端验证。请看

至于您的问题本身,您可以创建一个
适配器
,还可以创建一个
适配器提供程序
,以提供适配器:

公共类IPAddressOrHostnameAttributeAdapter:AttributeAdapterBase
{
公共IPAddressOrHostnameAttributeAdapter(IPAddressOrHostnameAttribute属性,IStringLocalizer stringLocalizer)
:base(属性,stringLocalizer)
{ }
公共重写void AddValidation(ClientModelValidationContext){}
公共重写字符串GetErrorMessage(ModelValidationContextBase validationContext)
{
返回GetErrorMessage(validationContext.ModelMetadata,validationContext.ModelMetadata.GetDisplayName());
}
}
公共类IPAddressOrHostnameAttributeAdapterProvider:IValidationAttributeAdapterProvider
{
private readonly IValizationAttributeAdapterProvider fallback=新的ValidationAttributeAdapterProvider();
public IAttributeAdapter GetAttributeAdapter(验证属性,IStringLocalizer stringLocalizer)
{
var attr=作为IPAddressOrHostnameAttribute的属性;
返回attr==null?
this.fallback.GetAttributeAdapter(属性,stringLocalizer):
新的IPAddressOrHostnameAttributeAdapter(attr,stringLocalizer);
}
}
此外,请确保此服务已在DI容器中注册:

services.AddSingleton();
最后,如果您使用querystring作为区域性提供程序,请不要忘记在表单操作中附加
culture=de

@{ var __culture = Context.Features.Get<IRequestCultureFeature>().RequestCulture.Culture.ToString(); }

<form asp-action="Create" asp-route-culture="@__culture">
    ....
</form>
@{var\uuu culture=Context.Features.Get().RequestCulture.culture.ToString();}
....

演示的屏幕截图


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

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

如果您正在使用内置本地化服务,它将是
IStringLocalizer
,如果您正在使用自定义本地化服务,例如(MyLocalizer),您可以通过将其解析到
GetService(typeof(MyLocalizer))
方法来访问它。见以下示例:

protected override ValidationResult有效(对象值,ValidationContext ValidationContext)
{
var_localizationService=(IStringLocalizer)validationContext.GetService(typeof(IStringLocalizer));
var localizedError=_本地化服务[ErrorMessage];
//
//做你的特写