Getting Started With NServiceBus in .NET

Getting Started With NServiceBus in .NET

5 min read ·

Thank you to our sponsors who keep this newsletter free to the reader:

Want to move to JetBrains Rider but not sure where to start? For a smooth experience, check out this guide where we look at the essential functionality you'll find helpful when migrating from Visual Studio.

Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for FREE.

NServiceBus is a feature-rich messaging framework supporting many different message transports. It's developed and maintained by Particular Software. And it simplifies the process of building complex distributed systems across various cloud-based queueing technologies.

The basic building blocks of NServiceBus are messages and endpoints. A message contains the required information to execute a business operation. Endpoints are logical entities that send and receive messages.

And now let's see how to get started with NServiceBus, from installation and setup to building your first NServiceBus endpoint.

In this week's newsletter, you will learn how to:

  • Configure an endpoint to use Azure Service Bus
  • Send and publish messages using IMessageSession
  • Handle messages with NServiceBus

Let's dive in!

What is NServiceBus?

NServiceBus is a messaging framework and platform that simplifies building reliable, scalable, and maintainable distributed systems. It's designed to address the challenges that arise when building applications that are distributed across multiple servers.

One of NServiceBus's foundational principles is its embrace of a message-driven architecture. In this model, components communicate by sending and receiving messages. Messages are the fundamental units of communication, representing commands, events, or data that services exchange.

Why is this significant?

Message-driven architectures offer several advantages:

  • Asynchronous communication
  • Loose coupling
  • Reliability

NServiceBus supports the powerful publish/subscribe (pub/sub) messaging pattern. This pattern allows services to publish events and subscribe to events of interest. When a service publishes an event, all interested subscribers receive a copy of the event. This is a key feature for building event-driven architectures, where services react to and process events in response to various actions or changes in the system.

Configuring the NServiceBus Endpoint

NServiceBus uses the concept of an endpoint to send and receive messages. It's a logical component that communicates with other components. You define your message handlers and sagas inside of an endpoint.

Let's start by installing the NServiceBus NuGet package:

Install-Package NServiceBus.Extensions.Hosting

Now you can configure an endpoint to use Azure Service Bus to send messages:

var builder = WebApplication.CreateBuilder();

builder.Host.UseNServiceBus(context =>
{
    var endpointConfiguration = new EndpointConfiguration("Training");

    var transport = endpointConfiguration
        .UseTransport<AzureServiceBusTransport>();

    var connectionString = builder.Configuration
        .GetConnectionString("AzureServiceBusConnectionString");
    transport.ConnectionString(connectionString);

    endpointConfiguration.EnableInstallers();

    return endpointConfiguration;
});

var app = builder.Build();

app.Run();

The call to UseNServiceBus tells the host to use NServiceBus. Inside the callback, you can configure the endpoint that will start when the host runs.

One more important aspect is calling EnableInstallers to set up the Azure Service Bus topology. This will tell NServiceBus to create the required queues, so you don't have to do it manually.

Publishing Messages in NServiceBus

The next building block you need in any messaging system is the messages. Messages are C# classes or interfaces that contain meaningful data for the business process.

NServiceBus supports three types of messages:

  • ICommand - sends a request to perform an action
  • IEvent - communicates that something significant occurred
  • IMessage - for messages that aren't commands or events (typically for replies in request-response)

Events can have more than one handler, while a command should have only one handler.

Let's create our first message contract:

using NServiceBus;

public class WorkoutCreated : IEvent
{
    public Guid Id [ get; set; ]
}

The WorkoutCreated message is an event that we will publish after creating a new Workout.

You can use the IMessageSession service to send messages from your controllers or Minimal API endpoints.

app.MapPost("api/workouts", async (
    Workout workout,
    AppDbContext context,
    IMessageSession messageSession) =>
{
    context.Add(workout);

    await context.SaveChangesAsync();

    await messageSession.Publish(new  WorkoutCreated { Id = workout.Id });

    return Results.Ok(workout);
});

NServiceBus has some built-in validation when sending messages. You have to specify an ICommand when calling the Send method, or you will get an exception. Similarly, you have to specify an IEvent when calling the Publish method.

Handling Messages With NServiceBus

Once you send a message, you need a way to handle it and run some business logic. To handle a message, you need to implement the IHandleMessages interface and specify which message you are handling.

Here's an implementation of the WorkoutCreatedHandler:

public class WorkoutCreatedHandler : IHandleMessages<WorkoutCreated>
{
    private readonly ILogger<WorkoutCreated> _logger;

    public WorkoutCreatedHandler(ILogger<WorkoutCreated> logger)
    {
        _logger = logger;
    }

    public async Task Handle(
        WorkoutCreated message,
        IMessageHandlerContext context)
    {
        logger.LogInformation("Processing workout - {Id}", message.Id);

        // Continue to process the message.
    }
}

Implementing IHandleMessages<WorkoutCreated> tells NServiceBus how to process the WorkoutCreated message when an endpoint receives it. This interface defines only one method: Handle.

The Handle method has an IMessageHandlerContext parameter, which allows you to send more messages. This can be helpful when implementing a choreographed saga. Processing one message triggers the next step in the chain until the entire process is completed.

In Summary

In this week's issue, we discussed NServiceBus, a robust messaging framework for building distributed systems in .NET. You learned how to configure NServiceBus with the Azure Service Bus transport. We discussed the different message types in NServiceBus and how to publish and handle a message.

Building distributed systems is a complex endeavor, but NServiceBus simplifies many challenges. By embracing a message-driven architecture and leveraging NServiceBus's features, you'll be well-equipped to create resilient, scalable, and maintainable applications in the .NET ecosystem.

Further reading:

Hope this was helpful.

I'll see you next week!


Whenever you're ready, there are 4 ways I can help you:

  1. Modular Monolith Architecture (NEW): Join 550+ engineers in this in-depth course that will transform the way you build modern systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario.
  2. Pragmatic Clean Architecture: Join 2,750+ students in this comprehensive course that will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture.
  3. Patreon Community: Join a community of 1,050+ engineers and software architects. You will also unlock access to the source code I use in my YouTube videos, early access to future videos, and exclusive discounts for my courses.
  4. Promote yourself to 49,000+ subscribers by sponsoring this newsletter.

Become a Better .NET Software Engineer

Join 49,000+ engineers who are improving their skills every Saturday morning.