Sponsor: 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.
Two popular libraries in Hangfire and MediatR can be used together to create a pretty powerful out-of-process messaging dispatcher. I’ve covered this a bit many years ago but I figured I’d give it a refresh since it’s a bit easier in the world of ASP.NET Core.
Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.
Hangfire and MediatR Bridge/Wrapper
The first thing you need to do is create a bridge/wrapper around MediatR. At first this may seem completely pointless, but it has a purpose. Hangfire has a lot extensibility in terms of how jobs are executed that are often times defined by using attributes. Because we don’t own the MediatR library, we need to have our own class that we can defined these attributes on.
Here’s a simple start to our Bridge/Wrapper
In the example above, I have an overload for Send() that accepts the jobName as the first parameter. The DisplayName attribute will be used by Hangfire to show in the UI Dashboard the name of the job. This is a simple example of why we need this wrapper.
The next piece of the puzzle is creating extension methods to be able to use Hangfire to create background jobs. In the example below I’ve created Enqueue() extension methods that use the Hangfire BackgroundJobClient to enqueue work using our Bridge/Wrapper
In the BackgroundJobClient.Enqueue() above, Hangfire will use Json.NET to serialize the IRequest that we are passing to Send() that ultimately gets put into storage. When Hangfire then pulls that job out of storage to perform the work, it needs to deserialize it. Because it’s just an IRequest it has no way to turning that into a concrete type.
To handle this, we need to configure Hangfire to add type handling when it serializes/deserializes.
The last thing we need to do is actually configure Hangfire in the ConfigureServices of either your ASP.NET Core Startup or your HostBuilder.
Here’s an example of my Worker process. This is just a console app that is purely a Hangfire server that just processes jobs from Hangfire.
Enqueuing a Request
In order to enqueue a MediatR request to Hangfire is a matter of calling the Enqueue() extension method we created off of IMediator.
In the example above, the HTTP Request to our Controller action will return a 204 NoContent, even though we are throwing in our PlaceOrderHandler because it’s execution is actually done out of the context of the HTTP Request. This could either be in a different thread, an entire different process, or on a totally on a different server).
There’s a lot more you can do with this and take it much farther to handle things like event publishing to have each event handler be it’s own job within Hangfire.
You can get all the source code of this running example on my GitHub.
If you have any thoughts or questions, please leave a comment on my blog, Twitter, or on the YouTube video.