如何禁用MassTransit的异常包装?(ABP+FastEndpoints场景)
ABP+FastEndpoints+MassTransit 异常处理适配问题
在abp.io项目中集成FastEndpoints框架后,ABP默认的异常处理机制失效。查看AbpExceptionHandlingMiddleware源码发现,该中间件仅当HttpContext.Items集合包含"_AbpActionInfo"键时才会处理异常。
我编写了HttpContextItemsModifier全局预处理器并配置到FastEndpoints中,解决了FastEndpoints的Endpoint类直接抛出的异常(标记为异常A)的处理问题,但MassTransit的Consume方法抛出的异常(标记为异常B)仍无法被ABP正确处理——因为MassTransit会将该异常包装为MassTransit.RequestException。
虽然通过try-catch捕获后抛出InnerException可以临时解决问题,但我希望找到强制MassTransit不包装异常、直接抛出原异常的方法。
相关代码示例
1. HttpApi项目中的Endpoint类
public class Login(IMediator mediator) : Endpoint<LoginRequest, LoginResponse> { private readonly IMediator _mediator = mediator; public override void Configure() { Post("auth/login"); AllowAnonymous(); } public override async Task<LoginResponse> ExecuteAsync(LoginRequest request, CancellationToken cancellationToken) { // ******** 异常A:Endpoint内部抛出 ********* // throw new BusinessException(AuthErrorCodes.Users.UserNotFound); var requestClient = _mediator.CreateRequestClient<LoginRequest>(); var accepted = await requestClient.GetResponse<LoginResponse>(request, cancellationToken); return accepted.Message; } }
2. Application项目中的Handler类
public interface ILoginHandler : IConsumer<LoginRequest> {} // 该接口声明在Application.Contracts项目中 public class LoginHandler : ILoginHandler { public LoginHandler() {} public async Task Consume(ConsumeContext<LoginRequest> context) { // 业务逻辑 // ******** 异常B:MassTransit消费者内部抛出 ********* throw new BusinessException(AuthErrorCodes.Users.UserNotFound); // 业务逻辑 } }
3. 已实现的预处理器及FastEndpoints配置
HttpContextItemsModifier预处理器
public class HttpContextItemsModifier : IGlobalPreProcessor { public Task PreProcessAsync(IPreProcessorContext ctx, CancellationToken ct) { ctx.HttpContext.Items["_AbpActionInfo"] = new AbpActionInfoInHttpContext { IsObjectResult = true }; return Task.CompletedTask; } }
FastEndpoints配置
app.UseFastEndpoints(c => { c.Endpoints.Configurator = ep => { ep.PreProcessor<HttpContextItemsModifier>(Order.Before); }; // 其他配置 });
临时解决方案代码
public override async Task<LoginResponse> ExecuteAsync(LoginRequest request, CancellationToken cancellationToken) { // ******** 异常A:Endpoint内部抛出 ********* // throw new BusinessException(AuthErrorCodes.Users.UserNotFound); try { var requestClient = _mediator.CreateRequestClient<LoginRequest>(); var accepted = await requestClient.GetResponse<LoginResponse>(request, /*Callback,*/ cancellationToken); return accepted.Message; } catch (System.Exception ex) { throw ex.InnerException; } }
内容的提问来源于stack exchange,提问作者ABS
相关产品推荐
相关产品推荐

