ASP.NET 核心模型绑定错误消息本地化
ASP.NET Core Model Binding Error Messages Localization
我正在使用 ASP.NET Core,并尝试对应用程序进行本地化。我设法使用 new asp .net 核心资源来本地化控制器和视图,并使用 old 资源来本地化模型验证的错误消息.
但是,当错误消息未链接到模型字段注释(如 "Required")并且模型绑定的数据不正确(如需要数字的文本)时,我收到如下错误,我无法本地化:
"The value 'abc' is not valid for ID."
当我在 View
中为 ID
属性 输入 abc
时,由于无法对该字段进行模型绑定,并且它在附近显示验证消息字段,说 "The value 'abc' is not valid for ID."。这是我正在使用的 class:
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*/
}
我在网上找到的类似问题要么是针对旧的asp .net 版本,要么没有帮助我解决问题。
自定义框架模型绑定错误信息,需要为ModelBindingMessageProvider
的不同错误信息访问器设置自定义访问器。
例子
在这里您可以下载 post 中描述的完整源代码。该存储库包含 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.
除了以上信息,ASP.NETCore 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.
本地化 ASP.NET 核心模型绑定错误消息
要本地化 ASP.NET 核心模型绑定错误消息,请执行以下步骤:
创建资源文件 - 在解决方案的 Resources 文件夹下创建一个资源文件,并将文件命名为 ModelBindingMessages.fa.resx。名称可以是任何其他名称,但我们将使用它来创建本地化程序。在示例中,我使用了 fa(波斯)文化。
添加资源键 - 打开资源文件并添加要用于本地化错误消息的键和值。我使用了如下图所示的键和值:
我使用的密钥与原始消息一样,除了 ValueMustNotBeNull
的密钥与 ValueIsInvalid
相同,所以我使用 Null value is invalid. 为之。
配置选项 - 在ConfigureServices
方法中,添加Mvc
时,配置其选项以设置[=15的消息访问器=]:
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;
});
}
同时在 Configure
方法的开头添加此代码:
var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("fa") };
app.UseRequestLocalization(new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture(new CultureInfo("en")),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
ASP.NET Core 2.0
的重要说明
In ASP.NET Core 2.0, model binding message provider properties has got
read only, but a setter method for each property has been added.
For example, to set
ValueIsInvalidAccessor
, you should use SetValueIsInvalidAccessor()
method this way:
options.ModelBindingMessageProvider.SetValueIsInvalidAccessor (
(x) => L["The value '{0}' is invalid.", x]);
参考这个 post 详细描述 , and to this answer regarding , last but not least, considering the refered improved answer by Andrew Lock,本地化模型绑定错误消息的正确方法应该是创建一个实现 [=12] 的自定义配置 class =] 然后在启动时注册它如下:
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]);
}
}
}
最后在启动时注册新配置class:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureModelBindingLocalization>();
// ...
}
已在 .NET Core 3.1 和 .NET 5 中测试。
创建一个确定 UICulture
的私有方法
private string GetStringValidationError()
{
CultureInfo uiCultureInfo = Thread.CurrentThread.CurrentUICulture;
string errorMessaeg = string.Empty;
errorMessaeg = uiCultureInfo.ToString() == "ar" ? "هذا الحقل مطلوب" : "This field is required";
return errorMessaeg;
}
之后,您可以将此方法附加到 Func 委托作为 SetValueMustNotBeNullAccessor 方法的第一个参数,如下所示:
options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(value => GetStringValidationError());
我正在使用 ASP.NET Core,并尝试对应用程序进行本地化。我设法使用 new asp .net 核心资源来本地化控制器和视图,并使用 old 资源来本地化模型验证的错误消息. 但是,当错误消息未链接到模型字段注释(如 "Required")并且模型绑定的数据不正确(如需要数字的文本)时,我收到如下错误,我无法本地化:
"The value 'abc' is not valid for ID."
当我在 View
中为 ID
属性 输入 abc
时,由于无法对该字段进行模型绑定,并且它在附近显示验证消息字段,说 "The value 'abc' is not valid for ID."。这是我正在使用的 class:
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*/
}
我在网上找到的类似问题要么是针对旧的asp .net 版本,要么没有帮助我解决问题。
自定义框架模型绑定错误信息,需要为ModelBindingMessageProvider
的不同错误信息访问器设置自定义访问器。
例子
在这里您可以下载 post 中描述的完整源代码。该存储库包含 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.
除了以上信息,ASP.NETCore 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.
本地化 ASP.NET 核心模型绑定错误消息
要本地化 ASP.NET 核心模型绑定错误消息,请执行以下步骤:
创建资源文件 - 在解决方案的 Resources 文件夹下创建一个资源文件,并将文件命名为 ModelBindingMessages.fa.resx。名称可以是任何其他名称,但我们将使用它来创建本地化程序。在示例中,我使用了 fa(波斯)文化。
添加资源键 - 打开资源文件并添加要用于本地化错误消息的键和值。我使用了如下图所示的键和值:
我使用的密钥与原始消息一样,除了
ValueMustNotBeNull
的密钥与ValueIsInvalid
相同,所以我使用 Null value is invalid. 为之。配置选项 - 在
ConfigureServices
方法中,添加Mvc
时,配置其选项以设置[=15的消息访问器=]: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; }); }
同时在
Configure
方法的开头添加此代码:var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("fa") }; app.UseRequestLocalization(new RequestLocalizationOptions() { DefaultRequestCulture = new RequestCulture(new CultureInfo("en")), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures });
ASP.NET Core 2.0
的重要说明In ASP.NET Core 2.0, model binding message provider properties has got read only, but a setter method for each property has been added.
For example, to set
ValueIsInvalidAccessor
, you should useSetValueIsInvalidAccessor()
method this way:options.ModelBindingMessageProvider.SetValueIsInvalidAccessor ( (x) => L["The value '{0}' is invalid.", x]);
参考这个 post 详细描述
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]);
}
}
}
最后在启动时注册新配置class:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureModelBindingLocalization>();
// ...
}
已在 .NET Core 3.1 和 .NET 5 中测试。 创建一个确定 UICulture
的私有方法private string GetStringValidationError()
{
CultureInfo uiCultureInfo = Thread.CurrentThread.CurrentUICulture;
string errorMessaeg = string.Empty;
errorMessaeg = uiCultureInfo.ToString() == "ar" ? "هذا الحقل مطلوب" : "This field is required";
return errorMessaeg;
}
之后,您可以将此方法附加到 Func 委托作为 SetValueMustNotBeNullAccessor 方法的第一个参数,如下所示:
options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(value => GetStringValidationError());