我开始使用ASP.NET核心使用常规的ASP.NET Web API多年后,我的新的REST API的项目。我没有看到处理ASP.NET中的核心Web API异常的好方法。我试图执行异常处理过滤器/属性:
I started using ASP.NET Core for my new REST API project after using regular ASP.NET Web API for many years. I don't see a good way to handle exceptions in ASP.NET Core Web API. I tried to implement exception handling filter/attribute:
public class ErrorHandlingFilter : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { if (context?.Exception != null) { HandleExceptionAsync(context); context.ExceptionHandled = true; } } private static void HandleExceptionAsync(ExceptionContext context) { var exception = context.Exception; if (exception is MyNotFoundException) SetExceptionResult(context, exception, HttpStatusCode.NotFound); else if (exception is MyUnauthorizedException) SetExceptionResult(context, exception, HttpStatusCode.Unauthorized); else if (exception is MyException) SetExceptionResult(context, exception, HttpStatusCode.BadRequest); else SetExceptionResult(context, exception, HttpStatusCode.InternalServerError); } private static void SetExceptionResult(ExceptionContext context, Exception exception, HttpStatusCode code) { context.Result = new JsonResult(new ApiResponse(exception)) { StatusCode = (int)code }; } }和这里是我的启动注册过滤器:
And here is my Startup filter registration:
services.AddMvc(options => { options.Filters.Add(new AuthorizationFilter()); options.Filters.Add(new ErrorHandlingFilter()); });
我遇到的问题是,如果发生异常我 AuthorizationFilter 它不是由 ErrorHandlingFilter 处理。这似乎不可思议我,因为我认为执行顺序应该是这样的:
The issue I was having is that if exception occurred in my AuthorizationFilter it's not being handled by ErrorHandlingFilter. This seems weird for me because I think the execution order should be like that:
ExceptionHandlingFilter { AuthorizationFilter, AnyOtherFilters ... { App { } } } // <-- handle all exceptions that occur in the scope.
如何让我的应用程序的工作这样?
How can make my app work like that?
推荐答案经过多次实验,我可以说中间件是最适合在ASP中的异常处理.NET的核心Web API。它处理应用程序异常,以及发生在过滤器异常。
Full example of Exception Handling Middleware
After many experiments I can say that middleware is the best for exception handling in ASP.NET Core Web API. It handles application exceptions as well as exceptions that occur in filters.
请参阅异常处理的中间件类。无需实现接口或继承任何东西。唯一的规则:公共异步任务调用(...)方法必须存在。 。如果需要,可以在构造函数中注入依赖
Please see exception handling middleware class. No need to implement interface or inherit anything. The only rule: public async Task Invoke(...) method must be present. You can inject dependencies in constructor if needed.
public class ErrorHandlingMiddleware { private readonly RequestDelegate next; public ErrorHandlingMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { try { await next(context); } catch (Exception ex) { await HandleExceptionAsync(context, ex); } } private static async Task HandleExceptionAsync(HttpContext context, Exception exception) { if (exception == null) return; var code = HttpStatusCode.InternalServerError; if (exception is MyNotFoundException) code = HttpStatusCode.NotFound; else if (exception is MyUnauthorizedException) code = HttpStatusCode.Unauthorized; else if (exception is MyException) code = HttpStatusCode.BadRequest; await WriteExceptionAsync(context, exception, code).ConfigureAwait(false); } private static async Task WriteExceptionAsync(HttpContext context, Exception exception, HttpStatusCode code) { var response = context.Response; response.ContentType = "application/json"; response.StatusCode = (int)code; await response.WriteAsync(JsonConvert.SerializeObject(new { error = new { message = exception.Message, exception = exception.GetType().Name } })).ConfigureAwait(false); } }
我在MVC中之前把它注册启动类:
app.UseMiddleware(typeof(ErrorHandlingMiddleware)); app.UseMvc();如果异常发生时,网络API响应体看起来像:
If exception occur, Web API response body looks like that:
{ "error": { "message": "Facebook authentication token is not valid.", "exception": "MyUnauthorizedException" } }更多推荐
ASP.NET核心Web API异常处理
发布评论