Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
597 views
in Technique[技术] by (71.8m points)

c# - How do I customize ASP.Net Core model binding errors?

I would like to return only standardized error responses from my Web API (Asp.net Core 2.1), but I can't seem to figure out how to handle model binding errors.

The project is just created from the "ASP.NET Core Web Application" > "API" template. I've got a simple action defined as:

[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; }
}

If I make a request to this action with an invalid Guid (eg, https://localhost:44303/MyTest/asdf), I get back the following response:

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

I've got the following code in 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 is simply a class that converts errors to the correct shape I want to return and puts them into the response. It is not getting called at all for the model binding errors (no Exception is thrown and UseStatusCodePages is not called).

How do I hook into the model binding to provide a standardized error response across all actions in my project?

I've read a bunch of articles, but they all seem to either discuss global exception handling or validation errors.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's worth mentioning that ASP.NET Core 2.1 added the [ApiController] attribute, which among other things, automatically handles model validation errors by returning a BadRequestObjectResult with ModelState passed in. In other words, if you decorate your controllers with that attribute, you no longer need to do the if (!ModelState.IsValid) check.

Additionally, the functionality is also extensible. In Startup, you can add:

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

The above is just what already happens by default, but you can customize the lambda that InvalidModelStateResponseFactory is set to in order to return whatever you like.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...