ASP.NET核心模型绑定错误消息本地化

Mar*_*rko 21 .net c# localization asp.net-core asp.net-core-localization

我正在使用ASP.NET Core,并尝试本地化应用程序.我设法使用新的 asp .net核心资源来本地化控制器和视图,并使用资源来本地化错误消息以进行模型验证.但是,当错误消息未链接到模型字段注释(如"必需")并且模型绑定的数据不正确时(如预期数字的文本),我收到如下错误,我是无法本地化:

"值'abc'对ID无效."

当我进入abcID房地产View,因为模型绑定无法做到的领域,它显示为近场验证消息,称"值'ABC’是无效的ID." .这是我正在使用的课程:

public class Country : IHasID
{
    public int ID { get; set; }

    [Required(ErrorMessageResourceType = typeof(L.Val),
    ErrorMessageResourceName = "NameR")]
    [MaxLength(100, ErrorMessageResourceType = typeof(L.Val), 
    ErrorMessageResourceName = "Max")]
    public string Name { get; set; }

    /*Some other properties*/
}
Run Code Online (Sandbox Code Playgroud)

我在互联网上发现的类似问题要么针对较旧的asp .net版本,否则无法解决问题.

Rez*_*aei 47

要自定义框架模型绑定错误消息,您需要为其他错误消息访问器设置自定义访问者ModelBindingMessageProvider.

在这里,您可以下载本文所述内容的完整源代码.该存储库包含ASP.NET Core 2.0(VS 2017.3)ASP.NET Core 1.1(VS 2015)的示例:

在这里你可以看到实例:live:

默认错误消息

这些是框架在绑定到属性的模型失败时显示的默认错误消息:

MissingBindRequiredValueAccessor    A value for the '{0}' property was not provided.
MissingKeyOrValueAccessor           A value is required.
ValueMustNotBeNullAccessor          The value '{0}' is invalid. 
AttemptedValueIsInvalidAccessor     The value '{0}' is not valid for {1}.
UnknownValueIsInvalidAccessor       The supplied value is invalid for {0}.
ValueIsInvalidAccessor              The value '{0}' is invalid.
ValueMustBeANumberAccessor          The field {0} must be a number.
Run Code Online (Sandbox Code Playgroud)

除上述消息外,ASP.NET Core 2.0还包含以下消息:

MissingRequestBodyRequiredValueAccessor       A non-empty request body is required.
NonPropertyAttemptedValueIsInvalidAccessor    The value '{0}' is not valid.
NonPropertyUnknownValueIsInvalidAccessor      The supplied value is invalid.
NonPropertyValueMustBeANumberAccessor         The field must be a number.
Run Code Online (Sandbox Code Playgroud)

本地化ASP.NET核心模型绑定错误消息

若要本地化ASP.NET Core模型绑定错误消息,请按照下列步骤操作:

  1. 创建资源文件 - 在解决方案的Resources文件夹下创建资源文件,并将文件命名为ModelBindingMessages.fa.resx.名称可以是其他任何名称,但我们将使用它来创建本地化程序.在这个例子中,我使用了fa(波斯语)文化.

  2. 添加资源键 - 打开资源文件并添加要用于本地化错误消息的键和值.我使用了键和值,如下图所示:

    在此输入图像描述

    我使用的密钥就像原始消息,除了密钥与之ValueMustNotBeNull相同ValueIsInvalid,所以我使用Null值无效.为了它.

  3. 配置选项 - 在ConfigureServices方法中,添加时Mvc,配置其选项以设置以下内容的消息访问者ModelBindingMessageProvider:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddLocalization(options => { options.ResourcesPath = "Resources"; });
        services.AddMvc(options =>
        {
            var F = services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
            var L = F.Create("ModelBindingMessages", "AspNetCoreLocalizationSample");
            options.ModelBindingMessageProvider.ValueIsInvalidAccessor =
                (x) => L["The value '{0}' is invalid.", x];
            options.ModelBindingMessageProvider.ValueMustBeANumberAccessor =
                (x) => L["The field {0} must be a number.", x];
            options.ModelBindingMessageProvider.MissingBindRequiredValueAccessor =
                (x) => L["A value for the '{0}' property was not provided.", x];
            options.ModelBindingMessageProvider.AttemptedValueIsInvalidAccessor =
                (x, y) => L["The value '{0}' is not valid for {1}.", x, y];
            options.ModelBindingMessageProvider.MissingKeyOrValueAccessor =
                () => L["A value is required."];
            options.ModelBindingMessageProvider.UnknownValueIsInvalidAccessor =
                (x) => L["The supplied value is invalid for {0}.", x];
            options.ModelBindingMessageProvider.ValueMustNotBeNullAccessor =
                (x) => L["Null value is invalid.", x];
        })
        .AddDataAnnotationsLocalization()
        .AddViewLocalization();
        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]{new CultureInfo("en"), new CultureInfo("fa")};
            options.DefaultRequestCulture = new RequestCulture("en", "en");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });
    }
    
    Run Code Online (Sandbox Code Playgroud)

    还要在Configure方法开头添加此代码:

    var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("fa") };
    app.UseRequestLocalization(new RequestLocalizationOptions()
    {
        DefaultRequestCulture = new RequestCulture(new CultureInfo("en")),
        SupportedCultures = supportedCultures,
        SupportedUICultures = supportedCultures
    });
    
    Run Code Online (Sandbox Code Playgroud)

ASP.NET Core 2.0的重要说明

在ASP.NET Core 2.0中,模型绑定消息提供程序属性已只读,但已添加每个属性的setter方法.

例如,要设置 ValueIsInvalidAccessor,您应该以SetValueIsInvalidAccessor() 这种方式使用方法:

options.ModelBindingMessageProvider.SetValueIsInvalidAccessor (
    (x) => L["The value '{0}' is invalid.", x]);
Run Code Online (Sandbox Code Playgroud)

  • 对不起,但在Core 2.0中,这种方法不适用于[Required]注释生成的验证消息.似乎错误字符串'XYZ字段是必需的'不能以这种方式翻译. (3认同)
  • 添加了@RemarkLima github存储库.https://github.com/r-aghaei/AspNetCoreLocalizationSample (2认同)
  • 是的,@ RezaAghaei,您是对的。我建议您在此处添加答案,某些注释不能使用“ ModelBindingMessageProvider”方法进行翻译,但是在注释中需要一个静态ErrorMessage字符串来触发翻译。`[Required]`案例就是其中之一,可能是大多数人到此为止的案例。我花了几个小时才能理解这一点。 (2认同)

Laz*_*iya 9

参考这篇文章,详细描述了在ConfigureServices中使用BuildServiceProvider的副作用,以及关于解决ConfigureServices中的服务的答案,最后但并非最不重要的一点是,考虑到Andrew Lock引用的改进答案,本地化模型绑定错误的正确方法消息应该通过创建一个实现的自定义配置类IConfigureOptions<T>,然后在启动时注册它,如下所示:

public class ConfigureModelBindingLocalization : IConfigureOptions<MvcOptions>
{
    private readonly IServiceScopeFactory _serviceFactory;
    public ConfigureModelBindingLocalization(IServiceScopeFactory serviceFactory)
    {
        _serviceFactory = serviceFactory;
    }

    public void Configure(MvcOptions options)
    {
        using(var scope = _serviceFactory.CreateScope())
        {
            var provider = scope.ServiceProvider;
            var localizer = provider.GetRequiredService<IStringLocalizer>();

            options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, y) => 
                localizer["The value '{0}' is not valid for {1}.", x, y]);

            options.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor((x) => 
                localizer["A value for the '{0}' parameter or property was not provided.", x]);

            options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => 
                localizer["A value is required."]);

           options.ModelBindingMessageProvider.SetMissingRequestBodyRequiredValueAccessor(() =>
               localizer["A non-empty request body is required."]);

           options.ModelBindingMessageProvider.SetNonPropertyAttemptedValueIsInvalidAccessor((x) =>
               localizer["The value '{0}' is not valid.", x]);

           options.ModelBindingMessageProvider.SetNonPropertyUnknownValueIsInvalidAccessor(() =>
               localizer["The supplied value is invalid."]);

           options.ModelBindingMessageProvider.SetNonPropertyValueMustBeANumberAccessor(() =>
               localizer["The field must be a number."]);

           options.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor((x) =>
               localizer["The supplied value is invalid for {0}.", x]);

           options.ModelBindingMessageProvider.SetValueIsInvalidAccessor((x) =>
               localizer["The value '{0}' is invalid.", x]);

           options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor((x) =>
               localizer["The field {0} must be a number.", x]);

           options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor((x) =>
               localizer["The value '{0}' is invalid.", x]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后在启动时注册新的配置类:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureModelBindingLocalization>();

    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 这是 asp.net core 5 的有效答案 (3认同)
  • 想补充一点,如果您使用 Orchestra PO 本地化,您可以声明一个空类并调用 `IStringLocalizer` 并注入它并使用它而不是 `localizer` 变量 (2认同)