Thank you to our sponsors who keep this newsletter free to the reader:
Learn about Postman with Postman Intergalactic sessions. Whether you're a developer or a tester, there's something for you. Collaborate on API development with workspaces. Sync your data across devices. And it's free. Get Postman here!
Introducing Shesha, a brand new, open-source, low-code framework for .NET developers. Create business applications faster and with >80% less code! Find out more here.
MassTransit is an open-source distributed application framework for .NET. It provides a messaging abstraction on top of the supported message transports. MassTransit lets you focus on adding business value instead of worrying about messaging complexity.
MassTransit supports many message transport technologies. Here are a few that are popular:
- RabbitMQ
- Azure Service Bus
- Amazon SQS
- Kafka
In today's newsletter, I'll show you how to install and configure MassTransit in .NET. We'll connect MassTransit to a few message brokers - RabbitMQ and Azure Service Bus. And we will also cover how to publish and consume messages with MassTransit.
Why Use MassTransit?
MassTransit solves many challenges of building distributed applications. You (almost) don't have to think about the underlying message transport. This allows you to focus on providing business value.
Here are a few things MassTransit does for you:
- Message routing - Type-based publish/subscribe, automatic broker topology configuration
- Exception handling - Messages can be retried or moved to an error queue
- Dependency injection - Service collection configuration and scope service provider
- Request-Response - Handle requests with automatic response routing
- Observability - Native Open Telemetry (OTEL) support
- Scheduling - Schedule message delivery using transport delay, Quartz.NET, or Hangfire
- Sagas - Reliable, durable, event-driven workflow orchestration
Let's see how to start using MassTransit.
Installing and Configuring MassTransit with RabbitMQ
You need to install the MassTransit
library.
If you already have a message transport, you can install the respective transport library.
Let's add the MassTransit.RabbitMQ
library to configure RabbitMQ as the transport mechanism.
Install-Package MassTransit
Install-Package MassTransit.RabbitMQ
Then, you can configure the required services for MassTransit
.
The AddMassTransit
method accepts a delegate where you can configure many settings.
For example, you can set the messaging endpoints to use kebab case naming by calling SetKebabCaseEndpointNameFormatter
.
This is also where you configure the transport mechanism.
Calling UsingRabbitMq
allows you to connect RabbitMQ as the transport mechanism.
builder.Services.AddMassTransit(busConfigurator =>
{
busConfigurator.SetKebabCaseEndpointNameFormatter();
busConfigurator.UsingRabbitMq((context, configurator) =>
{
configurator.Host("localhost", "/", h =>
{
h.Username("guest");
h.Password("guest");
});
configurator.ConfigureEndpoints(context);
});
});
MassTransit takes care of setting up the required broker topology. RabbitMQ supports exchanges and queues, so messages are sent or published to exchanges. RabbitMQ routes those messages through exchanges to the appropriate queues.
You can start RabbitMQ locally inside a Docker container:
docker run -d --name rabbitmq -p 5672:5672
Configuring MassTransit with Azure Service Bus
Azure Service Bus is a cloud-based message broker with support for queues and topics. MassTransit fully supports Azure Service Bus, including many advanced features and capabilities. However, you must be on the Standard or Premium tier of the Microsoft Azure Service Bus service.
To configure MassTransit to work with Azure Service Bus, you need to install the required transport library:
Install-Package MassTransit.Azure.ServiceBus.Core
Then, you can connect to Azure Service Bus by calling UsingAzureServiceBus
and providing the connection string.
Everything else remains the same.
MassTransit takes care of configuring the broker topology.
MassTransit sends messages to topics, and Azure Service Bus routes those messages to the appropriate queues.
builder.Services.AddMassTransit(busConfigurator =>
{
busConfigurator.SetKebabCaseEndpointNameFormatter();
busConfigurator.UsingAzureServiceBus((context, configurator) =>
{
configurator.Host("<CONNECTION_STRING>");
configurator.ConfigureEndpoints(context);
});
});
Using the MassTransit In Memory Transport
You can also configure MassTransit to use an in-memory transport. It's useful for testing, because it doesn't require a message broker to be running. Another advantage is that it's fast.
However, there's a big problem with the in-memory transport - it's not durable.
If the message bus is stopped, all messages are lost. Don't use the in-memory transport for production systems.
It will only work on a single machine. So, it doesn't make sense for distributed applications.
builder.Services.AddMassTransit(busConfigurator =>
{
busConfigurator.SetKebabCaseEndpointNameFormatter();
busConfigurator.UsingInMemory((context, configurator) =>
{
configurator.ConfigureEndpoints(context);
});
});
Message Types
MassTransit requires message types to be reference types.
So, you can use a class
, record
or interface
to define a message.
You'll often create two types of messages: commands and events.
A command is an instruction to perform some action.
Commands are intended to have exactly one consumer.
Commands are expressed using verbs first: CreateArticle
, PublishArticle
, ShareArticle
.
An event represents that something of significance happened.
Events can have one or many consumers.
Events should have a name in the past tense: ArticleCreated
, ArticlePublished
, ArticleShared
.
Here's an example ArticleCreated
message containing information about an article:
public record ArticleCreated
{
public Guid Id { get; init; }
public string Title { get; init; }
public string Content { get; init; }
public DateTime CreatedOnUtc { get; init; }
}
Using public set
or public init
properties is recommended to avoid serialization problems with System.Text.Json
.
Publishing and Consuming Messages
You can use the IPublishEndpoint
service to publish messages with MassTransit.
The framework routes the message to the appropriate queue or topic based on the message type.
app.MapPost("article", async (
CreateArticleRequest request,
IPublishEndpoint publishEndpoint) =>
{
await publishEndpoint.Publish(new ArticleCreated
{
Id = Guid.NewGuid(),
Title = request.Title,
Content = request.Content,
CreatedOnUtc = DateTime.UtcNow
});
return Results.Accepted();
});
To consume an ArticleCreated
message, you need to implement the IConsumer
interface.
The IConsumer
has one Consume
method where you place your business logic.
The consumer also gives you access to the ConsumeContext
, which you can use to send further messages.
public class ArticleCreatedConsumer(ApplicationDbContext dbContext)
: IConsumer<ArticleCreatedEvent>
{
public async Task Consume(ConsumeContext<ArticleCreatedEvent> context)
{
ArticleCreated message = context.Message;
var article = new Article
{
Id = message.Id,
Title = message.Title,
Content = message.Content,
CreatedOnUtc = message.CreatedOnUtc
};
dbContext.Add(article);
await dbContext.SaveChangesAsync();
}
}
MassTransit doesn't automatically know that the ArticleCreatedConsumer
exists.
You have to configure the consumer when calling AddMassTransit
.
The AddConsumer
method registers the consumer type with the bus.
builder.Services.AddMassTransit(busConfigurator =>
{
busConfigurator.SetKebabCaseEndpointNameFormatter();
busConfigurator.AddConsumer<ArticleCreatedConsumer>();
// ...
});
Next Steps
MassTransit is an excellent messaging library I often use when building distributed applications.
The setup is straightforward, and there are only a few important abstractions.
You need to know abstraction for publishing messages (IPublishEndpoint
) and consuming messages (IConsumer
).
MassTransit takes care of doing the heavy lifting for you.
If you aren't already using it, I highly recommend adding MassTransit to your toolbox.
Here are some more practical MassTransit learning resources:
- Request-Response pattern with MassTransit
- RabbitMQ and MassTransit tutorial
- Microservices with RabbitMQ
- Saga pattern with RabbitMQ
- Orchestration vs Choreography
- Messaging with Azure Service Bus
That's all for today.
See you next week.