Using EasyNetQ Version 8 in C# & .NET
[C#, .NET, RabbitMQ, EasyNetQ, StarLibrary]
When it comes to writing scalable applications using message queues, my engine of choice is RabbitMQ.
My library of choice for interfacing with RabbitMQ is EasyNetQ.
After a considerable period, a new release of EayNetQ, version 8, was recently published, version 8.1.2 at the time of writing this.
This involved significant changes to the API surface, design, and library integrations.
I will demonstrate the most fundamental change using two projects:
Version7that shows how the old library workedVersion8that shows how the new library works
Version7 and Version 8 we create as follows:
dotnet new web -o Version7
dotnet new web -o Version8
In the Version7 folder, we add the necessary packages:
dotnet add package EasyNetQ --Version 7.8.0
dotnet add package NewtonSoft.Json
We are adding NewtonSoft.Json as a result of an earlier change in which EasyNetQ unbundled the library and required it to be explicitly added to your code.
We set up our appsetttings.json as follows. to register our RabbitMQ connection string:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RabbitMQ": "host=localhost;username=test;password=test"
}
}
Next in the Program.cs, we set up the dependency injection.
using EasyNetQ;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IBus>(_ => RabbitHutch.CreateBus(builder.Configuration.GetConnectionString("RabbitMQ")));
var app = builder.Build();
We then register an endpoint to publish our message:
app.MapGet("/", async (IBus bus, ILogger<Program> logger) =>
{
try
{
logger.LogInformation("Publishing message ...");
// Publish a message
await bus.PubSub.PublishAsync("hello");
// Return OK
return Results.Ok();
}
catch (Exception ex)
{
return Results.InternalServerError(ex.Message);
}
});
Next, we set up the Version8 project.
dotnet add package EasyNetQ --Version 8.2.0
Note, we no longer need NewtonSoft.Json.
Our connection string setup is the same as before:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RabbitMQ": "host=localhost;username=test;password=test"
}
}
Our endpoint is also the same:
app.MapGet("/", async (IBus bus, ILogger<Program> logger) =>
{
try
{
logger.LogInformation("Publishing message ...");
// Publish a message
await bus.PubSub.PublishAsync("hello");
// Return OK
return Results.Ok();
}
catch (Exception ex)
{
return Results.InternalServerError(ex.Message);
}
});
The big change is in the dependency injection setup, which now looks like this:
using EasyNetQ;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEasyNetQ(builder.Configuration.GetConnectionString("RabbitMQ"));
var app = builder.Build();
Dependency injection is now supported out of the box, using a convenient extension method. You no longer need to deal with the RabbitHutch object.
Finally, we set up the RabbitMQ instance, and, as usual, I prefer to do this via Docker.
The docker-compose.yaml that I use is as follows:
services:
rabbitmq:
image: rabbitmq:management-alpine
container_name: rabbitmq
restart: always
volumes:
- ./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
environment:
- TZ=Africa/Nairobi
ports:
- 5672:5672
- 15672:15672
The rabbitmq.conf file that I use to configure the container is as follows:
default_user = test
default_pass = test
TLDR
The new release of EasyNetQ introduces breaking changes to support modern application development practices, such as dependency injection.
The code is in my GitHub.
Happy hacking!