在 .NET Core 2.1 中使用 [FromBody] 时处理模型绑定错误

Way*_*e B 7 c# .net-core asp.net-core-webapi .net-core-2.1

我试图了解如何拦截和处理 .net 核心中的模型绑定错误。

我想做这个:

    // POST api/values
    [HttpPost]
    public void Post([FromBody] Thing value)
    {
        if (!ModelState.IsValid)
        {
            // Handle Error Here
        }
    }
Run Code Online (Sandbox Code Playgroud)

Where the Model for "Thing" is:

public class Thing
{
    public string Description { get; set; }
    public int Amount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

However if I pass in an invalid amount like:

{ 
   "description" : "Cats",
   "amount" : 21.25
}
Run Code Online (Sandbox Code Playgroud)

I get an error back like this:

{"amount":["Input string '21.25' is not a valid integer. Path 'amount', line 1, position 38."]}

Without the controller code ever being hit.

How can I customise the error being sent back? (as basically I need to wrap this serialisation error in a larger error object)

Way*_*e B 15

所以,我之前错过了这个,但我在这里找到了:

https://docs.microsoft.com/en-us/aspnet/core/web-api/index?view=aspnetcore-2.2#automatic-http-400-responses

如果你使用

[ApiController] 
Run Code Online (Sandbox Code Playgroud)

属性,它将自动处理序列化错误并提供 400 响应,相当于:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}
Run Code Online (Sandbox Code Playgroud)

您可以在 Startup.cs 中关闭此行为,如下所示:

services.AddMvc()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressModelStateInvalidFilter = true;
    });
Run Code Online (Sandbox Code Playgroud)

如果您想自定义响应,更好的选择是使用 InvalidModelStateResponseFactory,它是一个委托,采用 ActionContext 并返回一个 IActionResult,它将被调用以处理序列化错误。

看这个例子:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.InvalidModelStateResponseFactory = actionContext => 
    {
        var errors = actionContext.ModelState
            .Where(e => e.Value.Errors.Count > 0)
            .Select(e => new Error
            {
            Name = e.Key,
            Message = e.Value.Errors.First().ErrorMessage
            }).ToArray();

        return new BadRequestObjectResult(errors);
    }
});
Run Code Online (Sandbox Code Playgroud)