.net core 自定义异常中间件

  • .net core 自定义异常中间件已关闭评论
  • 91 次浏览
  • A+
所属分类:.NET技术
摘要

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


前言

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

异常处理的几种方式

1、通过异常过滤器捕获异常进行处理

2、自定义异常处理中间件

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

异常中间件定义

我们先新建一个类来保存结果信息

   public abstract class AjaxResponseBase     {         public string TargetUrl { get; set; }          public bool Success { get; set; }          public ErrorInfo Error { get; set; }          public bool UnAuthorizedRequest { get; set; }          public string StatusCode { get; set; }     } 
中间件的定义
public class ExceptionMiddleware     {         private readonly RequestDelegate _next;         private readonly ILogger _logger;          public ExceptionMiddleware(RequestDelegate next             , ILoggerFactory loggerFactory         {             _next = next;             _logger = loggerFactory.CreateLogger<ExceptionMiddleware>();         }          public async Task Invoke(HttpContext context)         {             ExceptionDispatchInfo edi;             try             {                 var task = _next(context)                 //判断后续中间件处理是否成功完成,没有的话捕获异常                 if (!task.IsCompletedSuccessfully)                 {                     //记录异常信息                     await Awaited(context, () => task);                 }                 return;             }             catch (Exception ex)             {                 edi = ExceptionDispatchInfo.Capture(ex);             }             //注意我们这里并没有抛出异常,             await HandlerException(context, edi);         }          private async Task HandlerException(HttpContext context, ExceptionDispatchInfo edi)         {             if (context.Response.HasStarted)             {                 // 响应开始抛出异常终止响应                 edi.Throw();             }             //记录异常信息并将异常信息写入响应体中             context.Response.StatusCode = StatusCodes.Status500InternalServerError;             var requestPath = context.Request.Path;             var exception = edi.SourceException;             var logMsg = $"SourseRoute {requestPath} {exception.Source} {exception.Message} {exception.StackTrace} ";             _logger.LogError(logMsg);             AjaxResponse response = new AjaxResponse();             response.Success = false;             response.StatusCode = "500";             ErrorInfo error = new ErrorInfo();             response.Error = error;             error.Error = logMsg;             await context.Response.WriteAsJsonAsync(response);         }         //捕获后续管道的异常         private async Task Awaited(HttpContext context, Func<Task> func)         {             ExceptionDispatchInfo? edi = null;             try             {                 await func.Invoke();             }             catch (Exception exception)             {                 edi = ExceptionDispatchInfo.Capture(exception);             }             if (edi != null)             {                 await HandlerException(context, edi);             }         }     } 

使用

注意请将中间件放置在请求管道的开始处,这样才能捕获到全局的异常并且记录下了

 app.UseMiddleware<ExceptionMiddleware>(); 

在控制器中抛出异常
.net core 自定义异常中间件

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

.net core 自定义异常中间件

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

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

最后,如有不足,请多指教