代码之家  ›  专栏  ›  技术社区  ›  skolima

如何自定义ASP.NET核心模型绑定错误?

  •  9
  • skolima  · 技术社区  · 7 年前

    我只想从我的web api(asp.net core 2.1)返回标准化的错误响应,但是我似乎不知道如何处理模型绑定错误。

    该项目刚从“ASP.NET核心Web应用程序”>“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; }
    }
    

    如果我使用无效的guid请求此操作(例如, https://localhost:44303/MyTest/asdf ,我得到以下回复:

    {
        "id": [
            "The value 'asdf' is not valid."
        ]
    }
    

    我有以下代码 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()
    }
    

    JsonErrorMiddleware 只是一个类,它将错误转换为我想要返回的正确形状并将它们放入响应中。它根本不会因为模型绑定错误而被调用(否 Exception 被扔了出去 UseStatusCodePages 不被调用)。

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

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

    1 回复  |  直到 7 年前
        1
  •  29
  •   Chris Pratt    7 年前

    值得一提的是,ASP.NET Core2.1添加了 [ApiController] 属性,它通过返回 BadRequestObjectResult 具有 ModelState 进来了。换句话说,如果用该属性装饰控制器,则不再需要执行 if (!ModelState.IsValid) 检查一下。

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

    services.Configure<ApiBehaviorOptions>(o =>
    {
        o.InvalidModelStateResponseFactory = actionContext =>
            new BadRequestObjectResult(actionContext.ModelState);
    });
    

    以上只是默认情况下已经发生的事情,但是您可以在那里定制lambda InvalidModelStateResponseFactory 设置为以便返回您喜欢的任何内容。