You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MediatR全局异常处理器重复执行问题排查求助

问题根源

你的全局异常处理器重复执行的核心原因是未标记异常已处理:MediatR的异常处理管道会遍历所有匹配的IRequestExceptionHandler实现,若当前处理器未通过RequestExceptionHandlerState标记异常已处理,管道会继续传播异常,导致该全局处理器(因泛型约束匹配所有异常)被重复触发。

解决方案

1. 标记异常已处理

在日志记录完成后,调用state.SetHandled或state.SetException终止异常传播,避免后续重复触发处理器:

修改后的GlobalRequestExceptionHandler代码:

public class GlobalRequestExceptionHandler<TRequest, TResponse, TException>(IMediator mediator, ILoggerService loggerService) : IRequestExceptionHandler<TRequest, TResponse, TException>
    where TRequest : notnull
    where TException : Exception
{
    private readonly IMediator _mediator = mediator;
    private readonly ILoggerService _loggerService = loggerService;

    public async Task Handle(TRequest request, TException exception, RequestExceptionHandlerState<TResponse> state, CancellationToken cancellationToken)
    {
        try
        {
            if (IsLogSystemErrorCommandException(request))
                return;

            var systemError = SystemError.Create(request.GetType().Name, exception.GetType().Name, exception.Message, exception.StackTrace, VentureDomain.Common, VentureModule.Common);
            var command = new LogSystemErrorCommand(systemError);
            await _mediator.Send(command, cancellationToken);
            
            // 标记异常已处理,终止管道传播
            // 若TResponse为值类型或需要特定失败响应,替换为对应实例
            state.SetHandled(default);
        }
        catch (Exception ex)
        {
            _loggerService.Log(ex.Message, LogLevel.Error);
            // 即使日志记录失败,也要标记异常已处理,防止无限循环
            state.SetHandled(default);
        }
    }

    private bool IsLogSystemErrorCommandException(object? errorObject)
    {
        return errorObject?.GetType() == typeof(LogSystemErrorCommand);
    }
}

如果你的TResponse类型不允许default值(比如自定义的Result类型),可以构造合法的失败响应传入:

// 假设Result是你的响应类型,提供失败构造方法
state.SetHandled((TResponse)(object)_resultService.CreateFailure("系统异常已记录"));

2. 检查是否重复注册处理器

确认AddSystemSurveillanceRequestHandlers扩展方法仅被调用一次,避免处理器被多次注册:

// Program.cs/Startup.cs中确保只调用一次
builder.Services.AddMediatR(cfg =>
{
    cfg.AddSystemSurveillanceRequestHandlers();
    // 其他MediatR配置逻辑
});
额外提醒
  • 避免在异常处理器中抛出未处理的异常,否则会导致异常传播到上层(如ASP.NET全局异常中间件),可能再次触发MediatR的异常处理流程。
  • 若需保留原始异常的传播(比如让上层处理HTTP响应状态码),可调用state.SetException(exception),但需确保不会导致重复触发处理器。

内容的提问来源于stack exchange,提问作者Nico1395

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 14:00:18