NServiceBus Integration With Aspnet Core
With .NET Core now becoming mainstream, you might ask how you can run NServiceBus endpoints in an asp.net process. After all, it sounds pretty trivial, but turns out maybe not as easy as it sounds. Let’s see why.
The code to start the endpoint would typically have two steps. The first step is to setup the endpoint using ‘EndpoingConfiguration’ object and the second step is to create, or potentially ‘start’ an endpoint. In NSB v6 and higher, the create and start are both an async method. Initialization of the endpoint during the startup of the WebHost / Generic Host would look like this:
public class Startup
As it is obvious in the code above, you’d have to block the Start method call as it is async. It goes without saying that this is not a good practice and could cause issues like thread getting blocked or even deadlocks in certain situations.
More importantly, if you have message handlers in your process, when you start the endpoint it opens the flood gates and the handler will start receiving messages. This might be undesired as you are still initializing the application. The
ConfigureServices stage is for preparing your services and not actually run anything.
The proper way to run long running async tasks in aspnet core is to use
IHostedService interface. The good thing about this interface is that it supports async already as both
StopAsync methods are designed to support async method calls.
Starting NServiceBus as a background service would look something like this (this is a simplified version):
Note: there is a base class called
BackgroundService implementing this interaface already, so you can inherit from that base class instead.
public class NServiceBusServiceHost : IHostedService
And then we can easily plug in the hosted service in our Startup method like:
And this, of course does not work. The problem is that the service expects the EndpointConfiguration object to be registered in the container. An alternative to that is to manually register the hosted service like so:
services.AddSingleton<IHostedService>(provider => new NServiceBusServiceHost(CreateEndpointConfiguration()));
There are still other things to figure out though. For example, how do you send messages in your controllers? With this approach, you’ll need to inject the hosted service into your controller to use the
IEndpointInstance interface. If your controller has direct dependency on
IMessageSession) to send messages, it won’t work.
As you can see, making it work is a lot of chore and figuring out all the little details would add up. Luckily, there are two packages to use. Why two packages, you may ask? We’ll get to that in a bit. Using these packages allow seamless integration between Asp.net Core and NServiceBus. The package essentially does the same thing as here, but also registers
IMessageSession in the container as well. Your code would look like this:
There are two packages to choose from to achieve this. There is the
Community.NServiceBus.WebHost package, designed for .NET Core 2.x and there is the official
NServiceBus.Extensions.Hosting that works for .NET Core 3.x. Why two packages, again? The reason is that there is race-condition in Asp.net Core 2.x which would cause
IMessageSession not being available when the application is being initialized. The community package has a workaround for this to ‘make it work’ but the better option is to use the official package but you’ll need to be on .NET Core 3.x to do so.
The official documentation can be found online.