翼度科技»论坛 编程开发 .net 查看内容

.net core 自定义异常中间件

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
前言

在程序设计中,我们会遇到各种各样的异常问题,一个好的异常处理解决方案能够帮助开发者快速的定位问题,也能够给用户更好的用户体验。
异常处理的几种方式

1、通过异常过滤器捕获异常进行处理
2、自定义异常处理中间件
在这里我选择自定义异常处理中间件,中间件依托于请求管道运行,并且中间件的执行是有序的,与业务隔离开的,将中间件放置在请求管道开始能够捕获到全局异常。
异常中间件定义

我们先新建一个类来保存结果信息
  1.    public abstract class AjaxResponseBase
  2.     {
  3.         public string TargetUrl { get; set; }
  4.         public bool Success { get; set; }
  5.         public ErrorInfo Error { get; set; }
  6.         public bool UnAuthorizedRequest { get; set; }
  7.         public string StatusCode { get; set; }
  8.     }
复制代码
中间件的定义
  1. public class ExceptionMiddleware
  2.     {
  3.         private readonly RequestDelegate _next;
  4.         private readonly ILogger _logger;
  5.         public ExceptionMiddleware(RequestDelegate next
  6.             , ILoggerFactory loggerFactory
  7.         {
  8.             _next = next;
  9.             _logger = loggerFactory.CreateLogger<ExceptionMiddleware>();
  10.         }
  11.         public async Task Invoke(HttpContext context)
  12.         {
  13.             ExceptionDispatchInfo edi;
  14.             try
  15.             {
  16.                 var task = _next(context)
  17.                 //判断后续中间件处理是否成功完成,没有的话捕获异常
  18.                 if (!task.IsCompletedSuccessfully)
  19.                 {
  20.                     //记录异常信息
  21.                     await Awaited(context, () => task);
  22.                 }
  23.                 return;
  24.             }
  25.             catch (Exception ex)
  26.             {
  27.                 edi = ExceptionDispatchInfo.Capture(ex);
  28.             }
  29.             //注意我们这里并没有抛出异常,
  30.             await HandlerException(context, edi);
  31.         }
  32.         private async Task HandlerException(HttpContext context, ExceptionDispatchInfo edi)
  33.         {
  34.             if (context.Response.HasStarted)
  35.             {
  36.                 // 响应开始抛出异常终止响应
  37.                 edi.Throw();
  38.             }
  39.             //记录异常信息并将异常信息写入响应体中
  40.             context.Response.StatusCode = StatusCodes.Status500InternalServerError;
  41.             var requestPath = context.Request.Path;
  42.             var exception = edi.SourceException;
  43.             var logMsg = $"SourseRoute {requestPath} {exception.Source} {exception.Message} {exception.StackTrace} ";
  44.             _logger.LogError(logMsg);
  45.             AjaxResponse response = new AjaxResponse();
  46.             response.Success = false;
  47.             response.StatusCode = "500";
  48.             ErrorInfo error = new ErrorInfo();
  49.             response.Error = error;
  50.             error.Error = logMsg;
  51.             await context.Response.WriteAsJsonAsync(response);
  52.         }
  53.         //捕获后续管道的异常
  54.         private async Task Awaited(HttpContext context, Func<Task> func)
  55.         {
  56.             ExceptionDispatchInfo? edi = null;
  57.             try
  58.             {
  59.                 await func.Invoke();
  60.             }
  61.             catch (Exception exception)
  62.             {
  63.                 edi = ExceptionDispatchInfo.Capture(exception);
  64.             }
  65.             if (edi != null)
  66.             {
  67.                 await HandlerException(context, edi);
  68.             }
  69.         }
  70.     }
复制代码
使用

注意请将中间件放置在请求管道的开始处,这样才能捕获到全局的异常并且记录下了
  1. app.UseMiddleware<ExceptionMiddleware>();
复制代码
在控制器中抛出异常

可以看到我们在swagger请求控制器时已经记录了异常信息并且打印了出来

中间件与异常过滤器的比较

二者都可以用来捕获程序的异常,只是捕获异常的范围不一样。IExceptionFilter 作为过滤器的一种,它只能捕获控制器内部的异常,如果我们的异常发生控制器之外就无法捕获了,将异常中间件放置在请求管道的第一个,可以捕获到全局的异常。
最后,如有不足,请多指教

来源:https://www.cnblogs.com/lonely-wen/archive/2023/03/24/17253525.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具