侧边栏壁纸
博主头像
进击的码农博主等级

新年新气象,开搞开搞

  • 累计撰写 31 篇文章
  • 累计创建 11 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

自定义全局异常拦截,友好错误位置提示日志

wosperry
2021-10-07 / 0 评论 / 0 点赞 / 2 阅读 / 3432 字

就是个Demo,记录下中间件使用

引用

中间件代码

/// <summary>
/// 全局异常拦截中间件
/// </summary>
public class MyGlobalExceptionMiddleware
{
  private readonly RequestDelegate _next;

  /// <summary>
  /// 注入下一个中间件
  /// </summary>
  public MyGlobalExceptionMiddleware(RequestDelegate next)
  {
      _next = next;
  }

  public async Task Invoke(HttpContext httpContext)
  {
      try
      {
          // 等待下一个中间件执行完成
          await _next(httpContext);
      }
      // 异常时统一处理
      catch (Exception ex)
      {
          httpContext.Response.ContentType = "application/problem+json";

          ProblemDetails problem = new ProblemDetails
          {
              Status = 500,
              Title = "Exception: " + ex.Message
          };
          problem.Extensions.Add("message", ex.Message);
          if (!string.IsNullOrWhiteSpace(ex.StackTrace))
          {
              // 自定义正则:匹配 at [方法名] in [文件路径]:line [行号]
              var matches = Regex.Matches(ex.StackTrace, "at[ ](.+?)[ ]in[ ](.+?)[:]line[ ]([0-9]+)"); 
              // 使用Linq的拓展方法,筛选出需要的数据
              // 过滤掉:
              //      1. 包含了当前中间件名字的错误信息
              var filterdMatches = matches.Where(t => !t.Groups[0].ToString().Contains("Middlewares.MyGlobalExceptionMiddleware"));
              // 投影新的对象列表,方便前端人员阅读
              var extendExObject = filterdMatches.Select(x => new
              {
                  method = x.Groups[1].ToString(),
                  file = x.Groups[2].ToString(),
                  line = x.Groups[3].ToString()
              });
              // 往problem对象添加一个拓展属性detail
              problem.Extensions.Add("detail", extendExObject);
          }

          // 暂时不清楚具体干了什么,表现上是把problem对象格式化到HTML文本中。
          var stream = httpContext.Response.Body;
          await JsonSerializer.SerializeAsync(stream, problem);
      }
  }
}

/// <summary>
/// 添加拓展方法
/// </summary>
public static class MyGlobalExceptionMiddlewareExtensions
{
  public static IApplicationBuilder UseMyGlobalExceptionMiddleware(this IApplicationBuilder app)
  {
      return  app.UseMiddleware<MyGlobalExceptionMiddleware>();
  }
}

注册中间件

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ 
    // 注册自定义异常中间件(也可以使用 app.UseMiddleware<MyGlobalExceptionMiddleware>();)
    app.UseMyGlobalExceptionMiddleware();

    // 省略的其他项
}

控制器代码

[ApiController]
[Route("api/filter")]
public class TestFilterController:ControllerBase
{
    [HttpGet]
    public string TestFilterXXX()
    {
        throw new NotImplementedException();
        return "asdf";
    }
}

Api调用结果

{
    "title": "Exception: The method or operation is not implemented.",
    "status": 500,
    "message": "The method or operation is not implemented.",
    "detail": [
        {
            "method": "AbpTest1.Controllers.TestFilterController.TestFilterXXX()",
            "file": "C:\\Users\\Administrator\\source\\repos\\AbpTest1\\AbpTest1\\Controllers\\TestFilterController.cs",
            "line": "14"
        }
    ]
}
0

评论区