如何自定义ASP.Net Core模型绑定错误?

Bri*_*ian 13 c# asp.net-core asp.net-core-middleware asp.net-core-webapi

我想从Web API(Asp.net Core 2.1)中仅返回标准化的错误响应,但我似乎无法弄清楚如何处理模型绑定错误.

该项目只是从"ASP.NET Core Web Application">"API"模板创建的.我有一个简单的动作定义为:

[Route("[controller]")]
[ApiController]
public class MyTestController : ControllerBase
{
    [HttpGet("{id}")]
    public ActionResult<TestModel> Get(Guid id)
    {
        return new TestModel() { Greeting = "Hello World!" };
    }
}

public class TestModel
{
    public string Greeting { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用无效的Guid(例如https://localhost:44303/MyTest/asdf)向此操作发出请求,我会收到以下响应:

{
    "id": [
        "The value 'asdf' is not valid."
    ]
}
Run Code Online (Sandbox Code Playgroud)

我有以下代码Startup.Configure:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    JsonErrorMiddleware.CreateSingleton(env);

    if (!env.IsDevelopment())
    {
        app.UseHsts();
    }

    app
        .UseHttpsRedirection()
        .UseStatusCodePages(async ctx => { await JsonErrorMiddleware.Instance.Invoke(ctx.HttpContext); })
        .UseExceptionHandler(new ExceptionHandlerOptions() { ExceptionHandler = JsonErrorMiddleware.Instance.Invoke })
        .UseMvc()
}
Run Code Online (Sandbox Code Playgroud)

JsonErrorMiddleware只是一个类,它将错误转换为我想要返回的正确形状并将它们放入响应中.它根本没有被调用模型绑定错误(没有Exception被抛出并且UseStatusCodePages没有被调用).

如何挂钩模型绑定以在我的项目中的所有操作中提供标准化的错误响应?

我读了很多文章,但他们似乎都在讨论全局异常处理或验证错误.

Chr*_*att 31

值得一提的是,ASP.NET 2.1的核心增加了[ApiController]属性,除其他事项外,自动返回处理模型验证错误BadRequestObjectResultModelState传入.换句话说,如果你装饰与属性的控制器,不再需要做if (!ModelState.IsValid)校验.

此外,该功能也是可扩展的.在Startup,您可以添加:

services.Configure<ApiBehaviorOptions>(o =>
{
    o.InvalidModelStateResponseFactory = actionContext =>
        new BadRequestObjectResult(actionContext.ModelState);
});
Run Code Online (Sandbox Code Playgroud)

以上就是默认情况下已经发生的事情,但您可以自定义InvalidModelStateResponseFactory设置为的lambda ,以便返回您喜欢的内容.

  • 仅当您使用 **PostConfigure** 而不是 Configure 时才有效(从 ASP.NET Core 3.1.8 开始) (4认同)
  • 为了完整起见 - ApiBehaviorOptions 仅适用于装饰了 ApiController 属性的控制器!这也意味着还必须提供控制器本身的 Route 属性,并且绑定的方式也将发生变化。此处链接中提供的详细信息:/sf/ask/3215887251/#52830010 (2认同)