asp.net core custom exception processing middleware

asp.net core custom exception processing middleware

Intro

Global exception handling in asp.net core, it is sometimes not possible to meet our needs, you may need your own custom middleware handled, recently encountered a problem, there are some exceptions, do not want to log errors, the key is canceled due to user requests TaskCanceledExceptionand OperationCanceledExceptionanomalies. Because my ERROR level log output to the Sentry, sentry exceptions will automatically send e-mail alert, if some unnecessary mistakes, naturally do not need to log errors, and instead want a custom exception handling middleware own exception handling not the exception handling exception processing directly to the asp.net core.

Request cancellation

Request canceled due to abnormal:

request aborted

asp.net core introduced HttpContext.RequestAbortedto monitor the user cancels the request (actual test down, not every time the trigger, not figure out how a 100% trigger), you can use HttpContext.RequestAbortedto when the user cancels the request processing logic interrupts the background, avoid unnecessary business process, gives the following example of a use, sample source code
, more detailed information can be found Byron's this interrupt request to find out

[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);
}

Exception Handling Middleware

Exception Handling Middleware Source:

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}");
}

You can configure CustomExceptionHandlerOptionsan error log to implement custom exception handling logic, the default request will cancel a record level log Information, other exceptions will record a level of Error

When you encounter can be configured by the following example request cancellation of doing nothing abnormal

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

Reference

Guess you like

Origin www.cnblogs.com/weihanli/p/custom-exception-handler-for-aspnetcore.html