本地化ASP.NET core模型绑定错误消息
默认错误消息:
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.
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.resx。名称可以是其他任何名称,但我们将使用它来创建本地化程序。
添加资源键 - 打开资源文件并添加要用于本地化错误消息的键和值。我使用了键和值
配置选项 - 在
ConfigureServices方法中,添加时Mvc,配置其选项以设置以下内容的消息访问者ModelBindingMessageProviderservices.AddMvc(options =>
{
IStringLocalizerFactory F = services.BuildServiceProvider().
GetService<IStringLocalizerFactory>();
IStringLocalizer L = F.Create("ModelBindingMessages",
"AspNetCoreLocalizationSample");
options.ModelBindingMessageProvider.
SetValueIsInvalidAccessor((x) => L["The value '{0}' is invalid."]);
options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor(
(x) =>L["The field {0} must be a number."]);
options.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor(
(x) => L["A value for the '{0}' property was not provided.", x]);
options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor(
(x, y) => L["The value '{0}' is not valid for {1}.", x, y]);
options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(
() => L["A value is required."]);
options.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor(
(x) => L["The supplied value is invalid for {0}.", x]);
options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
(x) => L["Null value is invalid.", x]);
}).AddDataAnnotationsLocalization()
.AddViewLocalization();
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]{new CultureInfo("en"), new CultureInfo("zh-cn")};
options.DefaultRequestCulture = new RequestCulture("en", "en");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});还要在
Configure方法开头添加此代码:var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("zh-CN") };
app.UseRequestLocalization(new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture(new CultureInfo("en")),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});- 关于属性DisplayAttribute
通过查看源码 在 Microsoft.AspNetCore.Mvc.DataAnnotations.Internal.DataAnnotationsMetadataProvider中有IDisplayMetadataProvider的实现
主要是判断DisplayName不为空和ResourceType为空的时候使用IStringLocalizerFactory
代码片段如下:var dataTypeAttribute = attributes.OfType<DataTypeAttribute>().
if (displayFormatAttribute == null && dataTypeAttribute != null)
{
displayFormatAttribute = dataTypeAttribute.DisplayFormat;
}
var displayMetadata = context.DisplayMetadata; // ConvertEmptyStringToNull
if (displayFormatAttribute != null)
{
displayMetadata.ConvertEmptyStringToNull = displayFormatAttribute.
ConvertEmptyStringToNull;
}
// DataTypeName
if (dataTypeAttribute == null)
{
if (displayFormatAttribute != null && !displayFormatAttribute.HtmlEncode)
{
displayMetadata.DataTypeName = DataType.Html.ToString();
}
}
else
{
displayMetadata.DataTypeName = dataTypeAttribute.GetDataTypeName();
} var containerType = context.Key.ContainerType ?? context.Key.ModelType;
IStringLocalizer localizer = null;
if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
{
localizer = _localizationOptions.DataAnnotationLocalizerProvider(containerType, _stringLocalizerFactory);
} // Description
if (displayAttribute != null)
{
if (localizer != null &&
!string.IsNullOrEmpty(displayAttribute.Description) &&
displayAttribute.ResourceType == null)
{
displayMetadata.Description = () => localizer[displayAttribute.Description];
}
else
{
displayMetadata.Description = () => displayAttribute.GetDescription();
}
} // DisplayFormatString
if (displayFormatAttribute != null)
{
displayMetadata.DisplayFormatString = displayFormatAttribute.DataFormatString;
} // DisplayName
// DisplayAttribute has precedence over DisplayNameAttribute.
if (displayAttribute?.GetName() == null)
{
if (displayNameAttribute != null)
{
if (localizer != null &&
!string.IsNullOrEmpty(displayNameAttribute.DisplayName))
{
displayMetadata.DisplayName = () => localizer[displayNameAttribute.DisplayName];
}
else
{
displayMetadata.DisplayName = () => displayNameAttribute.DisplayName;
}
}
}
else
{
if (localizer != null &&
!string.IsNullOrEmpty(displayAttribute.Name) &&
displayAttribute.ResourceType == null)
{
displayMetadata.DisplayName = () => localizer[displayAttribute.Name];
}
else
{
displayMetadata.DisplayName = () => displayAttribute.GetName();
}
} // EditFormatString
if (displayFormatAttribute != null && displayFormatAttribute.ApplyFormatInEditMode)
{
displayMetadata.EditFormatString = displayFormatAttribute.DataFormatString;
} // IsEnum et cetera
var underlyingType = Nullable.GetUnderlyingType(context.Key.ModelType) ?? context.Key.ModelType;
var underlyingTypeInfo = underlyingType.GetTypeInfo(); if (underlyingTypeInfo.IsEnum)
{
// IsEnum
displayMetadata.IsEnum = true; // IsFlagsEnum
displayMetadata.IsFlagsEnum = underlyingTypeInfo.IsDefined(typeof(FlagsAttribute), inherit: false); // EnumDisplayNamesAndValues and EnumNamesAndValues
//
// Order EnumDisplayNamesAndValues by DisplayAttribute.Order, then by the order of Enum.GetNames().
// That method orders by absolute value, then its behavior is undefined (but hopefully stable).
// Add to EnumNamesAndValues in same order but Dictionary does not guarantee order will be preserved. var groupedDisplayNamesAndValues = new List<KeyValuePair<EnumGroupAndName, string>>();
var namesAndValues = new Dictionary<string, string>(); IStringLocalizer enumLocalizer = null;
if (_localizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes)
{
if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
{
enumLocalizer = _localizationOptions.DataAnnotationLocalizerProvider(underlyingType, _stringLocalizerFactory);
}
}
else
{
enumLocalizer = _stringLocalizerFactory?.Create(underlyingType);
} var enumFields = Enum.GetNames(underlyingType)
.Select(name => underlyingType.GetField(name))
.OrderBy(field => field.GetCustomAttribute<DisplayAttribute>(inherit: false)?.GetOrder() ?? ); foreach (var field in enumFields)
{
var groupName = GetDisplayGroup(field);
var value = ((Enum)field.GetValue(obj: null)).ToString("d"); groupedDisplayNamesAndValues.Add(new KeyValuePair<EnumGroupAndName, string>(
new EnumGroupAndName(
groupName,
() => GetDisplayName(field, enumLocalizer)),
value));
namesAndValues.Add(field.Name, value);
} displayMetadata.EnumGroupedDisplayNamesAndValues = groupedDisplayNamesAndValues;
displayMetadata.EnumNamesAndValues = namesAndValues;
} // HasNonDefaultEditFormat
if (!string.IsNullOrEmpty(displayFormatAttribute?.DataFormatString) &&
displayFormatAttribute?.ApplyFormatInEditMode == true)
{
// Have a non-empty EditFormatString based on [DisplayFormat] from our cache.
if (dataTypeAttribute == null)
{
// Attributes include no [DataType]; [DisplayFormat] was applied directly.
displayMetadata.HasNonDefaultEditFormat = true;
}
else if (dataTypeAttribute.DisplayFormat != displayFormatAttribute)
{
// Attributes include separate [DataType] and [DisplayFormat]; [DisplayFormat] provided override.
displayMetadata.HasNonDefaultEditFormat = true;
}
else if (dataTypeAttribute.GetType() != typeof(DataTypeAttribute))
{
// Attributes include [DisplayFormat] copied from [DataType] and [DataType] was of a subclass.
// Assume the [DataType] constructor used the protected DisplayFormat setter to override its
// default. That is derived [DataType] provided override.
displayMetadata.HasNonDefaultEditFormat = true;
}
} // HideSurroundingHtml
if (hiddenInputAttribute != null)
{
displayMetadata.HideSurroundingHtml = !hiddenInputAttribute.DisplayValue;
} // HtmlEncode
if (displayFormatAttribute != null)
{
displayMetadata.HtmlEncode = displayFormatAttribute.HtmlEncode;
} // NullDisplayText
if (displayFormatAttribute != null)
{
displayMetadata.NullDisplayText = displayFormatAttribute.NullDisplayText;
} // Order
if (displayAttribute?.GetOrder() != null)
{
displayMetadata.Order = displayAttribute.GetOrder().Value;
} // Placeholder
if (displayAttribute != null)
{
if (localizer != null &&
!string.IsNullOrEmpty(displayAttribute.Prompt) &&
displayAttribute.ResourceType == null)
{
displayMetadata.Placeholder = () => localizer[displayAttribute.Prompt];
}
else
{
displayMetadata.Placeholder = () => displayAttribute.GetPrompt();
}
}
本地化ASP.NET core模型绑定错误消息的更多相关文章
- 理解ASP.NET Core - 模型绑定&验证(Model Binding and Validation)
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 模型绑定 什么是模型绑定?简单说就是将HTTP请求参数绑定到程序方法入参上,该变量可以是简单类 ...
- ASP.NET Core应用的错误处理[3]:ExceptionHandlerMiddleware中间件如何呈现“定制化错误页面”
DeveloperExceptionPageMiddleware中间件利用呈现出来的错误页面实现抛出异常和当前请求的详细信息以辅助开发人员更好地进行纠错诊断工作,而ExceptionHandlerMi ...
- ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”
在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...
- ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式
由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...
- ASP.NET MVC模型绑定的6个建议(转载)
ASP.NET MVC模型绑定的6个建议 发表于2011-08-03 10:25| 来源博客园| 31 条评论| 作者冠军 validationasp.netmvc.netasp 摘要:ASP.NET ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定
在My Blog中已经有了文章管理功能,可以发布和修改文章,但是对于文章内容来说,这里缺少最重要的排版功能,如果没有排版的博客很大程度上是无法阅读的,由于文章是通过浏览器查看的,所以文章的排版其实与网 ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)
上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...
- [转] ASP.NET MVC 模型绑定的功能和问题
摘要:本文将与你深入探究 ASP.NET MVC 模型绑定子系统的核心部分,展示模型绑定框架的每一层并提供扩展模型绑定逻辑以满足应用程序需求的各种方法. 同时,你还会看到一些经常被忽视的模型绑定技术, ...
- ASP.NET Core 异常和错误处理 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 异常和错误处理 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 异常和错误处理 上一章节中,我们学习了 ASP.NET Cor ...
随机推荐
- python IOError: windows directory not found at xxxxx win32
您需要修改 PATH 环境变量,将Python的可执行程序及额外的脚本添加到系统路径中.将以下路径添加到 PATH 中: C:\Python2.7\;C:\Python2.7\Scripts\;请打开 ...
- C语言生成程序问题
问题: 我用VS2013写好C语言程序调试运行后就在debug文件夹下生成了EXE文件,可以在本机运行.但是这个EXE文件在别的没装过VS2013的电脑上就不能直接运行,说丢失MSVCR120D.dl ...
- CentOS6.5 增加交换空间
在CentOS 6.5安装Oracle 11g的时候,提示交换空间不足,百度来下,找到来增加交换空间的方法,特此记录一下 增加交换空间有两种方法: 严格的说,在系统安装完后只有一种方法可以增加swap ...
- mysql case
1.table CREATE TABLE `lee`(`id` INT(10) NOT NULL auto_increment,`name` varchar(20) DEFAULT null,`bir ...
- Markdown简要规则
We believe that writing is about content, about what you want to say – not about fancy formatting. 我 ...
- Node内存限制与垃圾回收
对象分配 所有的JS对象都是通过堆来进行分配的.使用process.memoryUsage()查看使用情况Node.js 中文网文档 process.memoryUsage() { rss: , he ...
- SQl Server Tsql基本编程 ,循环语句 ,存储过程
一些比较重要但是不一定经常用的 句子 Tsql定义变量 declare @a int : 定义的变量前面必须用@,数据类型是SQL里的数据类型,执行的时候要把需要的有关联的代码一起执行,单独执行一条 ...
- Blender 软件 四视图布局的创建方法
Blender 软件 四视图布局的创建方法 我使用的Blender版本:Blender V 2.77 Q: 为什么要创建一个:四视图布局场景? A: 原因1:四视图布局最适合模型建模.原因2:在 Bl ...
- 算法Sedgewick第四版-第1章基础-1.4 Analysis of Algorithms-002如何改进算法
1. package algorithms.analysis14; import algorithms.util.In; import algorithms.util.StdOut; /******* ...
- Java-马士兵设计模式学习笔记-策略模式-模拟Comparable接口
一.情况 1.目标:要在专门用于排序数据的DataSorter.java中实现对所有A类,B类,C类,D类等等的排序 2.初步想法:DataSorter.java的代码如下 public class ...