我的意图是在消息有效内容格式或数据无效时从服务器返回400状态代码。但是,在发送日期字段的值xyz123时,服务器将返回500状态代码。例外:
NodaTime.Text.UnparsableValueException: The value string does not match the required number from the format string "uuuu". Value being parsed: '^xyz123'. (^ indicates error position.)
at NodaTime.Text.ParseResult`1.GetValueOrThrow() in C:\Users\jon\Test\Projects\nodatime\build\tzdbupdate\tmp-2.4\nodatime\src\NodaTime\Text\ParseResult.cs:line 81
at NodaTime.Serialization.JsonNet.NodaConverterBase`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 2159
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 1032
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 2386
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Formatters.JsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
我希望可以将异常捕获并放入ModelState字典中。有没有一种方法可以在JsonInputFormatter或BodyModelBinder中注入此行为(即捕获异常),以便将其添加到ModelState中而不是使它们断开模型绑定?
作为一种解决方法,我正在使用错误处理中间件来捕获FormatException的中间件。但是,在这一点上,我不再拥有诸如JPATH之类的上下文信息来帮助用户或UI-Client。
可能的原因?:
单元测试以重现行为
public class ModelBindingErrorTest
{
private class ModelBindingErrorStartup
{
public void ConfigureServices(IServiceCollection services)
{
var mvcBuilder = services.AddMvc();
services.Configure<MvcJsonOptions>(options => options.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb));
//var mvcBuilder = services.AddMvcCore();
//mvcBuilder.AddJsonFormatters(jsonSerializerSettings => jsonSerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb));
mvcBuilder.AddApplicationPart(typeof(ModelBindingErrorStartup).Assembly);
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
[Fact]
public async Task Test()
{
var message = "The value string does not match the required number from the format string \"uuuu\". Value being parsed: \'^123xyz\'. (^ indicates error position.)";
try
{
var client = new TestServer(new WebHostBuilder().UseStartup<ModelBindingErrorStartup>()).CreateClient();
var response = await client.PostAsync(new Uri("/MainController/LocalDate", UriKind.Relative), new StringContent("{'Birthday':'123xyz'}", Encoding.UTF8, MediaTypeNames.Application.Json));
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.Equal(message, body);
}
catch (UnparsableValueException e)
{
Assert.Equal(message, e.Message);
// The Test Fails Here
Assert.False(true);
}
}
}
[Route("/MainController")]
public class MainController : Controller
{
[HttpPost("LocalDate")]
public object LocalDate([FromBody]Model model)
{
return ModelState["Birthday"].Errors[0].Exception.Message;
}
}
public class Model
{
public LocalDate Birthday { get; set; }
}
使用过的软件包