Mediator using MassTransit

In our previous blogs, we had visited the Mediator Pattern and also walked through the implementation of Mediator using Mediatr library. In this example, we will look into an alternative library – the MassTransit.

Over the years, MassTransit has made its APIs a lot more simpler. I wasn’t a huge of the earlier implementations, but the last time I checked the library things has evolved to a more usable API. Let us examine the implementation now.

To demonstrate the capabilities of MassTransit as an implementation of Mediator, we will build a Web API with an enpoint for order submission. The API has a response which indicates if the Order was successful or not. The endpoint would accept two Guids each representing the OrderId and CustomerId.

Before we begin, ensure that we have installed the necessary nuget packages.

MassTransit

We will begin by defining the OrderSubmitCommand which indicates the command for a new Order.

public class OrderSubmitCommand : Request<OrderSubmitResponse>
{
    public Guid Id { get; set; }
    public Guid CustomerId { get; set; }
    public DateTime TimeStamp { get; set; }
}

public class OrderSubmitResponse:IResponseBase
{
    public Guid OrderId { get; set; }
    public Guid CustomerId { get; set; }
    public DateTime TimeStamp { get; set; }
    public string Message { get; set; } = string.Empty;
    public bool IsSuccess { get; set; }
}

public interface IResponseBase
{
    string Message { get; set; }
    bool IsSuccess { get; set; }
}

The OrderSubmitCommand requires an IdCustomerId and a associated TimeStamp. The OrderSubmitResponse represents the expected response from the mediator consumer/handler.

We will now proceed te define our consumer OrderSubmitHandler

public class  OrderSubmitHandler : IConsumer<OrderSubmitCommand>
{
    public async Task Consume(ConsumeContext<OrderSubmitCommand> context)
    {
        var request = context.Message;

        await context.RespondAsync(new OrderSubmitResponse
        {
            OrderId = request.Id,
            TimeStamp = DateTime.UtcNow,
            Message = request.CustomerId.Equals(Guid.Empty) ? "Invalid User" : "Order Submission Successful;",
            IsSuccess = !request.CustomerId.Equals(Guid.Empty)
        });
    }
}

The consumer needs to inherit from IConsumer<T>. Do not that this is likely to change as the current develop branch of MassTransit uses a different base class. We indicate that the particular consumer is designed to handler OrderSubmitCommand by passing the type in IConsumer.

The consumer doesn’t do anything fancy. It checks if the CustomerId is a valid one and respond based on it.

Now is the time to define our endpoint. We will use DI to inject an instance of IMediator.

public class DemoController : ControllerBase
{
    private readonly IMediator _mediator;
    public DemoController(IMediator mediator)
    {
        _mediator = mediator;
    }
    [HttpPost]
    public async Task<IActionResult> PlaceOrder(Guid id,Guid customerId)
    {
        
        var response = await _mediator.SendRequest(new OrderSubmitCommand
        {
            Id = id,
            CustomerId = customerId,
            TimeStamp = DateTime.UtcNow
        });


        return response.IsSuccess ? Ok(response) : BadRequest(response);
    }
}

So how does the Mediator.Send know where to find consumers ? This magic is done with some configurations which we need to do.

builder.Services.AddMediator(cfg =>
{
    cfg.AddConsumersFromNamespaceContaining<OrderSubmitHandler>();
});


In the above code, we are asking our application to detect all the consumers defined under the namespace where OrderSubmitHandler is defined (in this case, we have only one).

That’s all we require. Run your API and test the output. You can find the source code in this example in my Github.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s