Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

asp.net core - How to specify error handler for a specific API controller?

I have an ASP.NET Core application that has MVC views but also few APIs, there is already error handling defined for the application. The ErrorController is returing an HTML view, I don't want to alter this behaviour. However, I'm introducing new API controller and I would like to decide what JSON (not HTML) is being returned if any unhandled exception is being thrown.

Can I specify error handler for a given controller so it returns JSON on 500 that I want?

question from:https://stackoverflow.com/questions/66066399/how-to-specify-error-handler-for-a-specific-api-controller

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

1 Answer

0 votes
by (71.8m points)

There are basically 2 ways to handle exceptions as a cross-cutting concern in asp.net core. One is by using IExceptionFilter (IAsyncExceptionFilter for async handling) and one is by using exception handler middleware. The exception filters are not able to handle all exceptions such as exception occurred in result execution (when serializing data, ...). So it's the most reliable to handle the exception using exception handler middleware.

You can find more about exception filter yourself, it's very easy to use for your scenario (targeting a specific controller) simply by decorating your controller class with an attribute. However here I would like to introduce how you can handle it using exception handler middleware which can be configured in the Configure method of the Startup class. Here we use IExceptionHandlerFeature to get the exception info (if any):

 //exception handler for errors in other controllers & pages ...
 app.UseExceptionHandler("/Error");
 //exception handler for specific controllers
 app.MapWhen(context => {
                var controller = context.GetRouteValue("controller")?.ToString();
                return controller?.ToLower() == "your_controller_name";
            }, subApp => {
                subApp.Run(async context =>
                {
                    var exceptionHandlerFeature = context.Features.Get<IExceptionHandlerFeature>();
                    var exception = exceptionHandlerFeature?.Error;
                    if (exception != null)
                    {
                        //prepare the error by your own
                        var error = new { Messsage = exception.Message };
                        context.Response.ContentType = "application/json";
                        //set status code of your choice
                        //context.Response.StatusCode = ;
                        //write JSON response containing the error
                        await context.Response.WriteAsync(JsonSerializer.Serialize(error));
                    }
                });
            });   

Note we use MapWhen to switch the pipeline to a terminal middleware (configured by subApp). That terminal middleware will intercept the request from being further processed by the other middlewares after it in the processing flow. You can see that the order of placing the UseExceptionHandler for other cases is important. It must be placed before the MapWhen due to how the middlewares are built along the request processing pipeline.

You can also create your own custom middelware into a separate class (following either convention-based or factory-based approach).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...