zoukankan      html  css  js  c++  java
  • asp.net core 自定义异常处理中间件

    asp.net core 自定义异常处理中间件

    Intro

    在 asp.net core 中全局异常处理,有时候可能不能满足我们的需要,可能就需要自己自定义一个中间件处理了,最近遇到一个问题,有一些异常,不希望记录错误日志,目前主要是用户请求取消导致的 TaskCanceledExceptionOperationCanceledException 异常。因为我的 ERROR 级别的日志会输出到 Sentry,sentry的异常会自动发邮件提醒,如果是一些没必要的错误,自然不需要记录错误日志,于是就想自定义一个异常处理中间件,自己处理异常,不将异常处理直接交给 asp.net core 的异常处理。

    请求取消

    请求取消导致的异常:

    request aborted

    asp.net core 引入了 HttpContext.RequestAborted 来监听用户取消请求(实际测试下来,并不是每次都会触发,还没搞清楚怎么100%的触发),你可以使用 HttpContext.RequestAborted 来在用户取消请求的时候中断后台逻辑的处理,避免处理一些不必要的业务,下面给出一个使用示例,示例源码
    ,更多详细信息可以参考 圣杰的这篇 中断请求了解一下

    [HttpGet]
    public async Task<IActionResult> GetAsync(string keyword, int pageNumber = 1, int pageSize = 10)
    {
        Expression<Func<Notice, bool>> predict = n => true;
        if (!string.IsNullOrWhiteSpace(keyword))
        {
            predict = predict.And(n => n.NoticeTitle.Contains(keyword));
        }
        var result = await _repository.GetPagedListResultAsync(x => new
        {
            x.NoticeTitle,
            x.NoticeVisitCount,
            x.NoticeCustomPath,
            x.NoticePublisher,
            x.NoticePublishTime,
            x.NoticeImagePath
        }, queryBuilder => queryBuilder
                .WithPredict(predict)
                .WithOrderBy(q => q.OrderByDescending(_ => _.NoticePublishTime))
            , pageNumber, pageSize, HttpContext.RequestAborted); // 直接使用 HttpContext.RequestAborted
    
        return Ok(result);
    }
    
    // 在 Action 方法中声明 CancellationToken,asp.net core 会自动将 `HttpContext.RequestAborted` 绑定到 CancellationToken 对象
    [HttpGet]
    public async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
    {
        var result = await _repository.GetResultAsync(p => new
        {
            p.PlaceName,
            p.PlaceIndex,
            p.PlaceId,
            p.MaxReservationPeriodNum
        }, builder => builder
        .WithPredict(x => x.IsActive)
        .WithOrderBy(x => x.OrderBy(_ => _.PlaceIndex).ThenBy(_ => _.UpdateTime)), cancellationToken);
        return Ok(result);
    }
    

    异常处理中间件

    异常处理中间件源码:

    public class CustomExceptionHandlerMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly CustomExceptionHandlerOptions _options;
    
        public CustomExceptionHandlerMiddleware(RequestDelegate next, IOptions<CustomExceptionHandlerOptions> options)
        {
            _next = next;
            _options = options.Value;
        }
    
        public async Task InvokeAsync(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (System.Exception ex)
            {
                var logger = context.RequestServices.GetRequiredService<ILoggerFactory>()
                    .CreateLogger<CustomExceptionHandlerMiddleware>();
                if (context.RequestAborted.IsCancellationRequested && (ex is TaskCanceledException || ex is OperationCanceledException))
                {
                    _options.OnRequestAborted?.Invoke(context, logger);
                }
                else
                {
                    _options.OnException?.Invoke(context, logger, ex);
                }
            }
        }
    }
    
    public class CustomExceptionHandlerOptions
    {
        public Func<HttpContext, ILogger, Exception, Task> OnException { get; set; } =
            async (context, logger, exception) => logger.LogError(exception, $"Request exception, requestId: {context.TraceIdentifier}");
    
        public Func<HttpContext, ILogger, Task> OnRequestAborted { get; set; } =
            async (context, logger) => logger.LogInformation($"Request aborted, requestId: {context.TraceIdentifier}");
    }
    

    可以通过配置 CustomExceptionHandlerOptions 来实现自定义的异常处理逻辑,默认请求取消会记录一条 Information 级别的日志,其他异常则会记录一条 Error 级别的错误日志

    你可以通过下面的示例来配置遇到请求取消异常的时候什么都不做

    service.Configure(options=>
    {
        options.OnRequestAborted = (context, logger) => Task.CompletedTask;
    });
    

    Reference

  • 相关阅读:
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    使用Jasmine和karma对传统js进行单元测试
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    nginx 基于IP的多虚拟主机配置
    Shiro 框架的MD5加密算法实现原理
    项目实战:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)
    实用技巧:阿里云服务器建立公网物联网服务器(解决阿里云服务器端口,公网连接不上的问题)
  • 原文地址:https://www.cnblogs.com/weihanli/p/custom-exception-handler-for-aspnetcore.html
Copyright © 2011-2022 走看看