ASP.NET Core Web API 异常处理

编程入门 行业动态 更新时间:2024-10-19 03:25:13
本文介绍了ASP.NET Core Web API 异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

在使用常规 ASP.NET Web API 多年后,我将 ASP.NET Core 用于我的新 REST API 项目.我没有看到任何处理 ASP.NET Core Web API 异常的好方法.我试图实现一个异常处理过滤器/属性:

I am using ASP.NET Core for my new REST API project after using regular ASP.NET Web API for many years. I don't see any good way to handle exceptions in ASP.NET Core Web API. I tried to implement an exception handling filter/attribute:

public class ErrorHandlingFilter : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { 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 不会对其进行处理.我原以为它会在那里被捕获,就像它与旧的 ASP.NET Web API 一起工作一样.

The issue I was having is that when an exception occurs in my AuthorizationFilter it's not being handled by ErrorHandlingFilter. I was expecting it to be caught there just like it worked with the old ASP.NET Web API.

那么如何捕获所有应用程序异常以及来自操作过滤器的任何异常?

So how can I catch all application exceptions as well as any exceptions from Action Filters?

推荐答案

快速简便的解决方案.

只需在 ASP.NET 路由之前将此中间件添加到您的中间件注册中即可.

Quick and Easy Solution.

Simply add this middleware before ASP.NET routing into your middleware registrations.

app.UseExceptionHandler(c => c.Run(async context => { var exception = context.Features .Get<IExceptionHandlerPathFeature>() .Error; var response = new { error = exception.Message }; await context.Response.WriteAsJsonAsync(response); })); app.UseMvc(); // or .UseRouting() or .UseEndpoints()

为日志记录和其他目的启用依赖注入.

第 1 步.在您的启动中,注册您的异常处理路由:


Enable Dependency Injection for logging and other purposes.

Step 1. In your startup, register your exception handling route:

// It should be one of your very first registrations app.UseExceptionHandler("/error"); // Add this app.UseEndpoints(endpoints => endpoints.MapControllers());

第 2 步. 创建将处理所有异常并产生错误响应的控制器:

Step 2. Create controller that will handle all exceptions and produce error response:

[AllowAnonymous] [ApiExplorerSettings(IgnoreApi = true)] public class ErrorsController : ControllerBase { [Route("error")] public MyErrorResponse Error() { var context = HttpContext.Features.Get<IExceptionHandlerFeature>(); var exception = context.Error; // Your exception var code = 500; // Internal Server Error by default if (exception is MyNotFoundException) code = 404; // Not Found else if (exception is MyUnauthException) code = 401; // Unauthorized else if (exception is MyException) code = 400; // Bad Request Response.StatusCode = code; // You can use HttpStatusCode enum instead return new MyErrorResponse(exception); // Your error model } }

一些重要的注意事项和观察:

A few important notes and observations:

  • 您可以将您的依赖项注入到控制器的构造函数中.
  • [ApiExplorerSettings(IgnoreApi = true)] 是必需的.否则,它可能会打破你的 Swashbuckle 招摇
  • 同样,app.UseExceptionHandler("/error"); 必须是您的 Startup Configure(...) 方法中最重要的注册之一.将它放在方法的顶部可能是安全的.
  • app.UseExceptionHandler("/error") 和控制器 [Route("error")] 中的路径应该相同,以允许控制器处理从异常处理程序中间件重定向的异常.
  • You can inject your dependencies into the Controller's constructor.
  • [ApiExplorerSettings(IgnoreApi = true)] is needed. Otherwise, it may break your Swashbuckle swagger
  • Again, app.UseExceptionHandler("/error"); has to be one of the very top registrations in your Startup Configure(...) method. It's probably safe to place it at the top of the method.
  • The path in app.UseExceptionHandler("/error") and in controller [Route("error")] should be the same, to allow the controller handle exceptions redirected from exception handler middleware.

这是链接 到 Microsoft 官方文档.

Here is the link to official Microsoft documentation.

实现您自己的响应模型和异常.这个例子只是一个很好的起点.每个服务都需要以自己的方式处理异常.使用所描述的方法,您可以完全灵活地控制异常处理并从您的服务返回正确的响应.

Implement your own response model and exceptions. This example is just a good starting point. Every service would need to handle exceptions in its own way. With the described approach you have full flexibility and control over handling exceptions and returning the right response from your service.

错误响应模型的一个例子(只是给你一些想法):

An example of error response model (just to give you some ideas):

public class MyErrorResponse { public string Type { get; set; } public string Message { get; set; } public string StackTrace { get; set; } public MyErrorResponse(Exception ex) { Type = ex.GetType().Name; Message = ex.Message; StackTrace = ex.ToString(); } }

对于更简单的服务,您可能希望实现如下所示的 http 状态代码异常:

For simpler services, you might want to implement http status code exception that would look like this:

public class HttpStatusException : Exception { public HttpStatusCode Status { get; private set; } public HttpStatusException(HttpStatusCode status, string msg) : base(msg) { Status = status; } }

可以通过这种方式从任何地方抛出:

This can be thrown from anywhere this way:

throw new HttpStatusCodeException(HttpStatusCode.NotFound, "User not found");

那么您的处理代码可以简化为:

Then your handling code could be simplified to just this:

if (exception is HttpStatusException httpException) { code = (int) httpException.Status; }

HttpContext.Features.Get() WAT?

ASP.NET Core 开发人员接受了中间件的概念,其中功能的不同方面(例如 Auth、MVC、Swagger 等)在请求处理管道中分开并按顺序执行.每个中间件都可以访问请求上下文,并且可以根据需要写入响应.如果以与 MVC 异常相同的方式处理来自非 MVC 中间件的错误很重要,那么从 MVC 中进行异常处理是有意义的,我发现这在现实世界的应用程序中非常普遍.所以因为内置异常处理中间件不是MVC的一部分,MVC本身对此一无所知,反之亦然,异常处理中间件并不真正知道异常来自哪里,当然它知道它发生在某个地方请求执行的管道.但是两者可能都需要连接"起来.与彼此.因此,当在任何地方都没有捕获到异常时,异常处理中间件会捕获它并重新运行在其中注册的路由的管道.这就是你可以通过"的方式使用一致的内容协商或其他一些中间件将异常处理回MVC如果你希望.异常本身是从公共中间件上下文中提取的.看起来很有趣,但完成了工作:)

ASP.NET Core developers embraced the concept of middlewares where different aspects of functionality such as Auth, MVC, Swagger etc. are separated and executed sequentially in the request processing pipeline. Each middleware has access to request context and can write into the response if needed. Taking exception handling out of MVC makes sense if it's important to handle errors from non-MVC middlewares the same way as MVC exceptions, which I find is very common in real world apps. So because built-in exception handling middleware is not a part of MVC, MVC itself knows nothing about it and vice versa, exception handling middleware doesn't really know where the exception is coming from, besides of course it knows that it happened somewhere down the pipe of request execution. But both may needed to be "connected" with one another. So when exception is not caught anywhere, exception handling middleware catches it and re-runs the pipeline for a route, registered in it. This is how you can "pass" exception handling back to MVC with consistent content negotiation or some other middleware if you wish. The exception itself is extracted from the common middleware context. Looks funny but gets the job done :).

更多推荐

ASP.NET Core Web API 异常处理

本文发布于:2023-11-13 15:12:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1584673.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:异常   NET   ASP   Core   API

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!