本地化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 模型绑定错误消息,请按照下列步骤操作:

  1. 创建资源文件 - 在解决方案的Resources文件夹下创建资源文件,并将文件命名为ModelBindingMessages.resx名称可以是其他任何名称,但我们将使用它来创建本地化程序。

  2. 添加资源键 - 打开资源文件并添加要用于本地化错误消息的键和值。我使用了键和值

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

  4.  1    services.AddMvc(options =>
     2             {
     3                 IStringLocalizerFactory F = services.BuildServiceProvider().
     4                 GetService<IStringLocalizerFactory>();
     5                 IStringLocalizer L = F.Create("ModelBindingMessages",
     6                     "AspNetCoreLocalizationSample");
     7                 options.ModelBindingMessageProvider.
     8                 SetValueIsInvalidAccessor((x) => L["The value '{0}' is invalid."]);
     9                 options.ModelBindingMessageProvider.SetValueMustBeANumberAccessor(
    10                     (x) =>L["The field {0} must be a number."]);
    11                 options.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor(
    12                     (x) => L["A value for the '{0}' property was not provided.", x]);
    13                 options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor(
    14                     (x, y) => L["The value '{0}' is not valid for {1}.", x, y]);
    15                 options.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(
    16                     () => L["A value is required."]);
    17                 options.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor(
    18                     (x) => L["The supplied value is invalid for {0}.", x]);
    19                 options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
    20                     (x) => L["Null value is invalid.", x]);
    21             }).AddDataAnnotationsLocalization()
    22     .AddViewLocalization();
    23     services.Configure<RequestLocalizationOptions>(options =>
    24     {
    25         var supportedCultures = new[]{new CultureInfo("en"), new CultureInfo("zh-cn")};
    26         options.DefaultRequestCulture = new RequestCulture("en", "en");
    27         options.SupportedCultures = supportedCultures;
    28         options.SupportedUICultures = supportedCultures;
    29     });

     

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

    1 var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("zh-CN") };
    2 app.UseRequestLocalization(new RequestLocalizationOptions()
    3 {
    4     DefaultRequestCulture = new RequestCulture(new CultureInfo("en")),
    5     SupportedCultures = supportedCultures,
    6     SupportedUICultures = supportedCultures
    7 });

     

  6.  

    关于属性DisplayAttribute 

    通过查看源码 在 Microsoft.AspNetCore.Mvc.DataAnnotations.Internal.DataAnnotationsMetadataProvider中有IDisplayMetadataProvider的实现
    主要是判断DisplayName不为空和ResourceType为空的时候使用IStringLocalizerFactory 
    代码片段如下:
      1    var dataTypeAttribute = attributes.OfType<DataTypeAttribute>(). 
      2 if (displayFormatAttribute == null && dataTypeAttribute != null)
      3             {
      4                 displayFormatAttribute = dataTypeAttribute.DisplayFormat;
      5             }
      6             var displayMetadata = context.DisplayMetadata;
      7 
      8             // ConvertEmptyStringToNull
      9             if (displayFormatAttribute != null)
     10             {
     11                 displayMetadata.ConvertEmptyStringToNull = displayFormatAttribute.
     12                     ConvertEmptyStringToNull;
     13             }
     14             // DataTypeName
     15             if (dataTypeAttribute == null)
     16             {
     17                 if (displayFormatAttribute != null && !displayFormatAttribute.HtmlEncode)
     18                 {
     19                     displayMetadata.DataTypeName = DataType.Html.ToString();
     20                 }
     21             }
     22             else
     23             {
     24                 displayMetadata.DataTypeName = dataTypeAttribute.GetDataTypeName();
     25             }
     26 
     27             var containerType = context.Key.ContainerType ?? context.Key.ModelType;
     28             IStringLocalizer localizer = null;
     29             if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
     30             {
     31                 localizer = _localizationOptions.DataAnnotationLocalizerProvider(containerType, _stringLocalizerFactory);
     32             }
     33 
     34             // Description
     35             if (displayAttribute != null)
     36             {
     37                 if (localizer != null &&
     38                     !string.IsNullOrEmpty(displayAttribute.Description) &&
     39                     displayAttribute.ResourceType == null)
     40                 {
     41                     displayMetadata.Description = () => localizer[displayAttribute.Description];
     42                 }
     43                 else
     44                 {
     45                     displayMetadata.Description = () => displayAttribute.GetDescription();
     46                 }
     47             }
     48 
     49             // DisplayFormatString
     50             if (displayFormatAttribute != null)
     51             {
     52                 displayMetadata.DisplayFormatString = displayFormatAttribute.DataFormatString;
     53             }
     54 
     55             // DisplayName
     56             // DisplayAttribute has precedence over DisplayNameAttribute.
     57             if (displayAttribute?.GetName() == null)
     58             {
     59                 if (displayNameAttribute != null)
     60                 {
     61                     if (localizer != null &&
     62                         !string.IsNullOrEmpty(displayNameAttribute.DisplayName))
     63                     {
     64                         displayMetadata.DisplayName = () => localizer[displayNameAttribute.DisplayName];
     65                     }
     66                     else
     67                     {
     68                         displayMetadata.DisplayName = () => displayNameAttribute.DisplayName;
     69                     }
     70                 }
     71             }
     72             else
     73             {
     74                 if (localizer != null &&
     75                     !string.IsNullOrEmpty(displayAttribute.Name) &&
     76                     displayAttribute.ResourceType == null)
     77                 {
     78                     displayMetadata.DisplayName = () => localizer[displayAttribute.Name];
     79                 }
     80                 else
     81                 {
     82                     displayMetadata.DisplayName = () => displayAttribute.GetName();
     83                 }
     84             }
     85 
     86             // EditFormatString
     87             if (displayFormatAttribute != null && displayFormatAttribute.ApplyFormatInEditMode)
     88             {
     89                 displayMetadata.EditFormatString = displayFormatAttribute.DataFormatString;
     90             }
     91 
     92             // IsEnum et cetera
     93             var underlyingType = Nullable.GetUnderlyingType(context.Key.ModelType) ?? context.Key.ModelType;
     94             var underlyingTypeInfo = underlyingType.GetTypeInfo();
     95 
     96             if (underlyingTypeInfo.IsEnum)
     97             {
     98                 // IsEnum
     99                 displayMetadata.IsEnum = true;
    100 
    101                 // IsFlagsEnum
    102                 displayMetadata.IsFlagsEnum = underlyingTypeInfo.IsDefined(typeof(FlagsAttribute), inherit: false);
    103 
    104                 // EnumDisplayNamesAndValues and EnumNamesAndValues
    105                 //
    106                 // Order EnumDisplayNamesAndValues by DisplayAttribute.Order, then by the order of Enum.GetNames().
    107                 // That method orders by absolute value, then its behavior is undefined (but hopefully stable).
    108                 // Add to EnumNamesAndValues in same order but Dictionary does not guarantee order will be preserved.
    109 
    110                 var groupedDisplayNamesAndValues = new List<KeyValuePair<EnumGroupAndName, string>>();
    111                 var namesAndValues = new Dictionary<string, string>();
    112 
    113                 IStringLocalizer enumLocalizer = null;
    114                 if (_localizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes)
    115                 {
    116                     if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
    117                     {
    118                         enumLocalizer = _localizationOptions.DataAnnotationLocalizerProvider(underlyingType, _stringLocalizerFactory);
    119                     }
    120                 }
    121                 else
    122                 {
    123                     enumLocalizer = _stringLocalizerFactory?.Create(underlyingType);
    124                 }
    125 
    126                 var enumFields = Enum.GetNames(underlyingType)
    127                     .Select(name => underlyingType.GetField(name))
    128                     .OrderBy(field => field.GetCustomAttribute<DisplayAttribute>(inherit: false)?.GetOrder() ?? 1000);
    129 
    130                 foreach (var field in enumFields)
    131                 {
    132                     var groupName = GetDisplayGroup(field);
    133                     var value = ((Enum)field.GetValue(obj: null)).ToString("d");
    134 
    135                     groupedDisplayNamesAndValues.Add(new KeyValuePair<EnumGroupAndName, string>(
    136                         new EnumGroupAndName(
    137                             groupName,
    138                             () => GetDisplayName(field, enumLocalizer)),
    139                         value));
    140                     namesAndValues.Add(field.Name, value);
    141                 }
    142 
    143                 displayMetadata.EnumGroupedDisplayNamesAndValues = groupedDisplayNamesAndValues;
    144                 displayMetadata.EnumNamesAndValues = namesAndValues;
    145             }
    146 
    147             // HasNonDefaultEditFormat
    148             if (!string.IsNullOrEmpty(displayFormatAttribute?.DataFormatString) &&
    149                 displayFormatAttribute?.ApplyFormatInEditMode == true)
    150             {
    151                 // Have a non-empty EditFormatString based on [DisplayFormat] from our cache.
    152                 if (dataTypeAttribute == null)
    153                 {
    154                     // Attributes include no [DataType]; [DisplayFormat] was applied directly.
    155                     displayMetadata.HasNonDefaultEditFormat = true;
    156                 }
    157                 else if (dataTypeAttribute.DisplayFormat != displayFormatAttribute)
    158                 {
    159                     // Attributes include separate [DataType] and [DisplayFormat]; [DisplayFormat] provided override.
    160                     displayMetadata.HasNonDefaultEditFormat = true;
    161                 }
    162                 else if (dataTypeAttribute.GetType() != typeof(DataTypeAttribute))
    163                 {
    164                     // Attributes include [DisplayFormat] copied from [DataType] and [DataType] was of a subclass.
    165                     // Assume the [DataType] constructor used the protected DisplayFormat setter to override its
    166                     // default.  That is derived [DataType] provided override.
    167                     displayMetadata.HasNonDefaultEditFormat = true;
    168                 }
    169             }
    170 
    171             // HideSurroundingHtml
    172             if (hiddenInputAttribute != null)
    173             {
    174                 displayMetadata.HideSurroundingHtml = !hiddenInputAttribute.DisplayValue;
    175             }
    176 
    177             // HtmlEncode
    178             if (displayFormatAttribute != null)
    179             {
    180                 displayMetadata.HtmlEncode = displayFormatAttribute.HtmlEncode;
    181             }
    182 
    183             // NullDisplayText
    184             if (displayFormatAttribute != null)
    185             {
    186                 displayMetadata.NullDisplayText = displayFormatAttribute.NullDisplayText;
    187             }
    188 
    189             // Order
    190             if (displayAttribute?.GetOrder() != null)
    191             {
    192                 displayMetadata.Order = displayAttribute.GetOrder().Value;
    193             }
    194 
    195             // Placeholder
    196             if (displayAttribute != null)
    197             {
    198                 if (localizer != null &&
    199                     !string.IsNullOrEmpty(displayAttribute.Prompt) &&
    200                     displayAttribute.ResourceType == null)
    201                 {
    202                     displayMetadata.Placeholder = () => localizer[displayAttribute.Prompt];
    203                 }
    204                 else
    205                 {
    206                     displayMetadata.Placeholder = () => displayAttribute.GetPrompt();
    207                 }
    208             }

     


     
  7.    


posted @ 2018-09-13 11:47  SpeakHero  阅读(1286)  评论(0编辑  收藏  举报