How to disable MassTransit exception wrapping?

71 views Asked by At

I apologize in advance for the long question.

I am using FastEndpoints in an abp.io project. It's strange, not? Let's ignore the reasons behind and suppose we are forced to do that. Here's the sample codes:

Endpoint class in HttpApi project

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)
    {
        // ******** exception A: from inside Endpoint itself *********
        // throw new BusinessException(AuthErrorCodes.Users.UserNotFound);

        var requestClient = _mediator.CreateRequestClient<LoginRequest>();
        var accepted = await requestClient.GetResponse<LoginResponse>(request, cancellationToken);
        return accepted.Message;
    }
}

Handler class in Application project

public interface ILoginHandler : IConsumer<LoginRequest> {} // this interface declared in Application.Contracts project
public class LoginHandler : ILoginHandler
{
    public LoginHandler() {}

    public async Task Consume(ConsumeContext<LoginRequest> context)
    {
        // logic
        // ******** exception B: from inside MassTransit consumer *********
        throw new BusinessException(AuthErrorCodes.Users.UserNotFound);
        // logic
    }
}

The problem: When I added FastEndpoints I found that default abp Exception Handling mechanism didn't work correctly. After checking AbpExceptionHandlingMiddleware's source code , I noticed that theHttpContext only handles exception when it has an item with "_AbpActionInfo" key in its Items collection. To overcome this issue, I wrote a PreProcessor class:

public class HttpContextItemsModifier : IGlobalPreProcessor
{
    public Task PreProcessAsync(IPreProcessorContext ctx, CancellationToken ct)
    {
        ctx.HttpContext.Items["_AbpActionInfo"] = new AbpActionInfoInHttpContext { IsObjectResult = true };
        return Task.CompletedTask;
    }
}

And configured FastEndpoint this way:

app.UseFastEndpoints(c =>
{
    c.Endpoints.Configurator = ep =>
    {
        ep.PreProcessor<HttpContextItemsModifier>(Order.Before);
    };
    // otehr configurations
});

With above changes, the problem fixed for only exceptions those thrown directly from FastEndpoints's Endpoint classes(A exception marked above). But the problem still exists for exceptions thrown from MassTransit Consume methods(B exception). Why? It's because MassTransit consumer wraps B exception into a MassTransit.RequestException class. Adding a try catch block and throw InnerException(BusinessException here), magically solves the problem:

public override async Task<LoginResponse> ExecuteAsync(LoginRequest request, CancellationToken cancellationToken)
{
    // ******** exception A: from inside Endpoint itself *********
    // 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;
    }
}

The Question: But I'm looking for a way to force MassTransit to not wrap exceptions, and throw them in a bare manner

0

There are 0 answers