如何为本地化目的覆盖Json.Net模型绑定异常消息?

时间:2019-07-11 14:14:16

标签: json asp.net-core-mvc asp.net-core-localization

我已经使用ModelBindingMessageProvider.SetValueIsInvalidAccessor和其他ModelBindingMessageProvider值覆盖了所有带有转换的模型绑定消息,以返回我的自定义资源字符串。

然后我发现了可悲的事实。如果我的API控制器以JSON形式接收数据,则不会使用ModelBindingMessageProvider验证消息。取而代之的是,Json.Net介入了,我得到了如下响应:

  "errors": {
    "countryId": [
      "Input string '111a' is not a valid number. Path 'countryId', line 3, position 23."
    ]
  },

我查看了Json.Net的GitHub来源-实际上,它似乎具有用行号等定义的确切错误消息。

因此,ModelState设法将它们拉入而不是使用自己的ModelBindingMessageProvider消息。

我试图禁用Json.Net错误处理:

.AddJsonOptions(options =>
                {
                 ...
                    options.SerializerSettings.Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
                    {
                        // ignore them all
                        args.ErrorContext.Handled = true;
                    };
                })

但这没什么区别。

是否可以捕获这些Json反序列化错误并将其重定向到ModelBindingMessageProvider,以便我的本地化消息正常工作?

1 个答案:

答案 0 :(得分:1)

  

是否有任何方法可以捕获这些Json反序列化错误,并且   将它们重定向到ModelBindingMessageProvider,以便我本地化   消息会起作用吗?

否,模型绑定和json输入不同,模型绑定器用于$,而JsonInputFormatter用于FromForm。他们遵循不同的方式。您无法自定义FromBody中的错误消息。

对于ModelBindingMessageProvider,您可以实现自己的JSON并更改错误消息,例如

  1. JsonInputFormatter

    CustomJsonInputFormatter
  2. 注册public class CustomJsonInputFormatter : JsonInputFormatter { public CustomJsonInputFormatter(ILogger<CustomJsonInputFormatter> logger , JsonSerializerSettings serializerSettings , ArrayPool<char> charPool , ObjectPoolProvider objectPoolProvider , MvcOptions options , MvcJsonOptions jsonOptions) : base(logger, serializerSettings, charPool, objectPoolProvider, options, jsonOptions) { } public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { var result = await base.ReadRequestBodyAsync(context); foreach (var key in context.ModelState.Keys) { for (int i = 0; i < context.ModelState[key].Errors.Count; i++) { var error = context.ModelState[key].Errors[i]; context.ModelState[key].Errors.Add($"This is translated error { error.ErrorMessage }"); context.ModelState[key].Errors.Remove(error); } } return result; } }

    CustomJsonInputFormatter
  3. 将本地化服务注册到 services.AddMvc(options => { var serviceProvider = services.BuildServiceProvider(); var customJsonInputFormatter = new CustomJsonInputFormatter( serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<CustomJsonInputFormatter>(), serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value.SerializerSettings, serviceProvider.GetRequiredService<ArrayPool<char>>(), serviceProvider.GetRequiredService<ObjectPoolProvider>(), options, serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value ); options.InputFormatters.Insert(0, customJsonInputFormatter); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } 中以自定义错误消息。