我正在使用ASP.NET Core,并尝试本地化该应用程序。我设法使用 new asp .net核心资源来本地化控制器和视图,并使用旧资源来本地化错误消息以进行模型验证。 但是,当错误消息未链接到模型字段注释(例如"必需")并且模型绑定的数据不正确时(如预期数字的文本),我收到如下错误,我无法本地化:
"价值' abc'对于ID无效。"
当我在abc
中为ID
属性输入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*/
}
我在互联网上发现的类似问题是针对较旧的asp .net版本,否则无法帮助我解决问题。
答案 0 :(得分:40)
要自定义框架模型绑定错误消息,您需要为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.
除上述消息外,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.
要本地化ASP.NET Core模型绑定错误消息,请按照下列步骤操作:
创建资源文件 - 在解决方案的 Resources 文件夹下创建资源文件,并将文件命名为 ModelBindingMessages.fa.resx 。名称可以是其他任何名称,但我们将使用它来创建本地化程序。在这个例子中,我使用了 fa (波斯语)文化。
添加资源键 - 打开资源文件,添加要用于本地化错误消息的键和值。我使用了键和值,如下图所示:
我使用的密钥与原始邮件类似,但ValueMustNotBeNull
的密钥与ValueIsInvalid
相同,所以我使用 Null值无效。。
配置选项 - 在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."];
options.ModelBindingMessageProvider.ValueMustBeANumberAccessor =
(x) => L["The field {0} must be a number."];
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的重要说明
在ASP.NET Core 2.0中,模型绑定消息提供程序属性已获得 只读,但已添加每个属性的setter方法。
例如,要设置
ValueIsInvalidAccessor
,您应该使用SetValueIsInvalidAccessor()
方法这样:options.ModelBindingMessageProvider.SetValueIsInvalidAccessor ( (x) => L["The value '{0}' is invalid."]);
答案 1 :(得分:1)
参考详细描述the side effects for using BuildServiceProvider inside ConfigureServices的帖子以及有关resolving services inside ConfigureServices的答案,最后但并非最不重要的是,考虑到refered improved answer by Andrew Lock,定位模型绑定错误的正确方法消息应该通过创建实现IConfigureOptions<T>
的自定义配置类,然后在启动时按如下所示进行注册:
public class ConfigureModelBindingLocalization : IConfigurationOptions<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]);
}
}
}
最后在启动时注册新的配置类:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureModelBindingLocalization>();
// ...
}
答案 2 :(得分:0)
在 .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());