This article covers detail about how to integrate Hangfire in ASP.NET Core applications which is an easy way to schedule background jobs in .NET Core and .NET based applications.
Background jobs or tasks allow the programmers to execute code on a different thread but scheduling & monitoring background jobs is a difficult task to achieve. Hangfire simplifies tasks to handle background jobs in ASP.NET Core.
Table of Contents
Why or When to Schedule background jobs in .NET Core?
There might be some web requests which take lots of time for execution like generating a report on successful insertion or sending email/SMS as acknowledgment for the transaction completion. These requests can take an unknown amount of time to completion and keeping the user looking at the wait indicator for that time is not good handling of the request.
Idea is to unblock the user screen as soon as possible for requests which are going to take a long time to complete so that the user is able to perform other tasks. Though the user has been unblocked before the completion of long-running activities completion of these activities is also important as those are part of request business logic.
This is where background jobs come into the picture it’s like running the remaining of the activities in the background like on a different thread so that the main thread has been released for a user to perform other activities.
Introduction to Hangfire
We saw the use of background jobs in our application but if we have to build a framework for background jobs creation & monitoring then it would be a complicated task that might require lots of effort. Also, this is a design feature and not a functional feature so spending too much time on this will not go down well with all the stakeholders. This is where Hangfire can be used.
Hangfire is a simple to use an open-source library that makes the implementation of background job easy in .NET Core & .NET Applications. Hangfire in ASP.NET Core allows the creation of background jobs and even provide monitoring features.
Hangfire in ASP.NET Core even supports persistent storage like Microsoft SQL Server, Redis (as part of Hangfire Pro), etc. for storing jobs information that prevents applications from losing jobs information in case of pool restarts. Storing the information of the jobs ensures that jobs are executed as per defined types & also jobs are retried if any exception occurs during the execution of the job.
Hangfire supports all the major logging frameworks and will log the complete job execution information to the logging destination configured for the application.
Hangfire provides reliability of background jobs by ensuring that jobs are executed at least once based on their scheduling criteria
Hangfire in ASP.NET Core application can be simple or distributed i.e. server/application that creates a job can be separate from the server/application that executes the job. This is possible as job information is stored on a database that can be shared between different servers/applications.
Types of background Jobs in Hangfire
With Hangfire in ASP.NET Core, you can create the following types of background Jobs
Fire and Forget
Fir and Forget jobs as the name suggests are executed only once and immediately as soon as they are created. These are mainly used to release the main thread so that the user experience is more responsive.
Delayed
As the name suggests these jobs are executed after some delay. This delay i.e. wait time is configurable and is queued upon creation. Execution is similar to fire & forget. This can be used for jobs that can be run outside the peak load window.
Recurring
These are scheduled jobs normally executed multiple times on every defined interval. The frequency of these jobs can be configured which can vary from milliseconds to years. These can be daily or weekly jobs to generate data dumps or reports.
Continuation
Continuation allows you to define a workflow i.e. you can configure multiple (parent-continuation job) background jobs that can be linked together based on completion of a parent job. i.e. the second job should execute provided that the first/parent job has executed correctly.
Additional job Types with Hangfire Pro
Batch Jobs
More than one background job can be linked together to form batch jobs together so that they all are executed together at the same time.
Batch Continuation
The link continuation job fires when the parent batch of jobs have completed i.e. all the jobs within a batch have completed then the continuation background job will fire.
Implement Hangfire in ASP.NET Core i.e. schedule background jobs in .NET Core
Here is the quick & short video to implement Hangfire in ASP.NET Core
Create a new ASP.NET Core WebAPI Project
For the implementation of Hangfire in ASP.NET Core let’s create a new ASP.NET Core Web API project in which we implement Hangfire.
I will be using Visual Studio 2019 community edition along with .NET Core 5 to create a new Web API project
- Launch Visual Studio 2019
- Select Create a new project on the initial screen as shown below
3. Next select ASP.NET Core Web Application from the displayed project types template list and click on the Next button as shown in the screenshot below
4. After that enter name for the project\solution as ProCodeGuide.Samples.Hangfire, provide a path of the project where it will be saved on the local disk & click on create button as shown below
5. Finally select .NET Core Framework as ASP.NET Core 5.0, application type as ASP.NET Core Web API, Enable OpenAPI Support for testing purpose & click on Create button as shown below
This will create the project and load the same in Visual Studio 2019 as shown in below screenshot
Install required Hangfire NuGet Packages
You will need to install the NuGet package Hangfire as shown below to include Hangfire references into your application.
Hangfire package in ASP.NET Core has a dependency on three other references which get installed along with Hangfire NuGet package as shown below
Configure Hangfire in Startup
Now that all the required NuGet packages for Hangfire has been installed we will not configure Hangfire in Startup.cs file.
We will add calls to the extension method AddHangfire & AddHangfireServer on the IServiceCollection in ConfigureServices method in class Startup.
public void ConfigureServices(IServiceCollection services) { services.AddHangfire(x => x.UseSqlServerStorage("Server=(localdb)\\mssqllocaldb;Database=ProCodeGuide.Samples.Hangfire;Trusted_Connection=True;MultipleActiveResultSets=true")); services.AddHangfireServer(); //Remaining code has been removed for readability purposes }
AddHangfire – This adds Hangfire in ASP.NET Core to the dependency injection container and takes an Action delegate using which we have set the connection string for SQL Server database to use SQL Server database as the storage for Hangfire Implementation.
Being a demo application I have hardcoded SQL Server connecting string in the startup class but that is not a good practice so please configure your SQL Server connection strings in the appsettings.json file and set it from there so that you have environment-specific SQL Server connection strings
AddHangfireServer – This adds Hangfire Server to the dependency injection container which will be used to configure and run jobs.
Adding Hangfire Dashboard UI
Now let’s add the middleware for Hangfire to the ASP.NET Core Middleware Pipeline that will be required to add the Hangfire dashboard UI. We will add a call to the extension method UseHangfireDashboard on the IApplicationBuilder instance.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ProCodeGuide.Samples.Hangfire v1")); } app.UseRouting(); app.UseAuthorization(); app.UseHangfireDashboard(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
Check Hangfire Dashboard UI
Now that we have integrated Hangfire in ASP.NET Core application let’s run the application & check the dashboard for Hangfire.
You should see the below screen from swagger after building & running the application from visual studio.
Now after navigating to URL /Hangfire you should be able to see the dashboard for Hangfire in ASP.NET Core as shown below.
From dashboard UI you will be able to see scheduled jobs & monitor the status of jobs. The dashboard even allows you to manually run the jobs visible in the dashboard. The information available on the dashboard is as follows
Jobs – All the jobs stored in the database will be visible here under different status as Scheduled, Enqueued, Processing, Succeeded, Failed, Deleted & Awaiting.
Retries – Jobs list which have been retried due to some failure during previous execution.
Recurring Jobs – List of all the jobs which have been scheduled as recurring jobs can be seen.
Servers – All the Hangfire servers which have been added to the dependency injection container can be seen. These servers are responsible for processing jobs.
Please note that since Dashboard UI exposes application-specific sensitive data & even allows manual execution of jobs so it is important to secure access of this dashboard to authorized users only.
The only security provided by Hangfire in ASP.NET Core by default is that it allows only local requests for Dashboard UI
Hangfire Database
We did configure SQL Server database for Hangfire in ASP.NET Core as part of the Hangfire configuration in the startup (AddHangfire). When hangfire starts it looks for the required schema in the database if that does not exist then it will create the same as shown below
Hangfire database is used to for storing jobs information.
Create jobs with Hangfire in ASP.NET Core
To demonstrate different types of jobs in Hangfire in ASP.NET Core first let’s create a dummy service i.e. DummyEmailService, which implements interface IEmailService, that simulates mail sending by writing to console window that mail has been sent instead of sending actual mail.
Now if you want to implement a working email service that sends emails using MailKit Libraray & SMTP Server then you can read my other article on How to Send Emails in ASP.NET Core
Add interface Services/IEmailService.cs that has function SendEmail which will be implemented in dummy service DummyEmailService to write to console that email has been sent.
public interface IEmailService { void SendEmail(string backGroundJobType, string startTime); }
Add class Services/DummyEmailService that will implement interface IEmailService & will contain an implementation of SendEmail method to writing to console window.
public class DummyEmailService : IDummyEmailService { public void SendEmail(string backGroundJobType, string startTime) { Console.WriteLine(backGroundJobType + " - " + startTime + " - Email Sent - " + DateTime.Now.ToLongTimeString()); } }
Now register this service in the application dependency injection container so that it can be injected into the controller. To add DummyEmailService to the container add the following line of code in Method ConfigureServices in Startup.cs file
services.AddTransient<IEmailService, DummyEmailService>();
Now let’s add a new API controller i.e. EmailController into which we will inject IEmailService to call method SendEmail from service in controller action method SendEmail.
[Route("[controller]")] [ApiController] public class EmailController : ControllerBase { private IEmailService _emailService = null; public EmailController(IEmailService emailService) { _emailService = emailService; } [HttpGet] public string SendMail() { _emailService.SendEmail("Direct Call", DateTime.Now.ToLongTimeString()); return "Email Initiated"; } }
Now run the application & you should be below screen when you navigate to URL /Email
Let’s look at how to implement each type of job in Hangfire in ASP.NET Core
Fire-and-Forget job
Hangfire.BackgroundJob.Enqueue is used to create the Fire-and-Forget background task. These jobs are executed almost immediately after creation and only once.
BackgroundJob.Enqueue(() => _emailService.SendEmail("Fire-and-Forget Job", DateTime.Now.ToLongTimeString()));
Delayed job
Hangfire.BackgroundJob.Schedule is used to create the Delayed background task. These jobs are created with a delay and are executed when the configured delay time has been elapsed.
BackgroundJob.Schedule(() => _emailService.SendEmail("Delayed Job",DateTime.Now.ToLongTimeString()),TimeSpan.FromSeconds(30));
Recurring Job
Hangfire.RecurringJob.AddOrUpdate is used to create the recurring background task. These can be every minute, daily or weekly jobs that get executed as per defined frequency.
RecurringJob.AddOrUpdate(() => _emailService.SendEmail("Recurring Job", DateTime.Now.ToLongTimeString()),Cron.Minutely);
Continuations job
Hangfire.BackgroundJob.ContinueJobWith is used to create the continuation background task. These jobs are executed immediately after the linked previous job has been successfully executed.
var jobId = BackgroundJob.Schedule(() => _emailService.SendEmail("Continuation Job 1", DateTime.Now.ToLongTimeString()), TimeSpan.FromSeconds(45)); BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("Continuation Job 2 - Email Reminder - " + DateTime.Now.ToLongTimeString()));
Finally, I have modified the code in the SendMail action method in EmailController as shown below to demonstrate the execution pattern for each type of background job available in Hangfire in ASP.NET Core
[HttpGet] public string SendMail() { _emailService.SendEmail("Direct Call", DateTime.Now.ToLongTimeString()); BackgroundJob.Enqueue(() => _emailService.SendEmail("Fire-and-Forget Job", DateTime.Now.ToLongTimeString())); BackgroundJob.Schedule(() => _emailService.SendEmail("Delayed Job", DateTime.Now.ToLongTimeString()),TimeSpan.FromSeconds(30)); RecurringJob.AddOrUpdate(() => _emailService.SendEmail("Recurring Job", DateTime.Now.ToLongTimeString()),Cron.Minutely); var jobId = BackgroundJob.Schedule(() => _emailService.SendEmail("Continuation Job 1", DateTime.Now.ToLongTimeString()), TimeSpan.FromSeconds(45)); BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("Continuation Job 2 - Email Reminder - " + DateTime.Now.ToLongTimeString())); return "Email Initiated"; }
Let’s run the code & check the results
Now let’s run the code to check execution pattern of different type of jobs available in Hangfire in ASP.NET Core.
After running the application navigate to URL /Email this should call SendEmail to get action method in EmailController and the below screen should be displayed. But in background, all the configured job types should get created and triggered as per their execution pattern.
Let’s view the console window weather different type of jobs in Hangfire in ASP.NET Core have got triggered or not
We can see from above screen that all jobs were triggered as per their execution pattern.
Summary
In this article, we learn about background jobs, Hangfire in ASP.NET Core & the implementation of different types of jobs available in Hangfire in ASP.NET Core.
We also saw that there is even a paid version of Hangfire i.e. Hangfire Pro which supports Redis as a database & also supports some additional complex job types like batch & batch continuation.
I hope you liked this article, let me know your feedback in the comments section below
Download Source Code
Source code download link for implementation of Hangfire in ASP.NET Core
https://github.com/procodeguide/ProCodeGuide.Samples.Hangfire
You specify in the initial diagram that there are 2 asp web applications, one to queue jobs and one to fetch and consume jobs, but in the implementation its all in one web app? Am I missing something obvious?
Hi. You are correct in the diagram I have shown 2 applications but in implementation, I have merged them into a single project. You can divide the relevant code into different projects if required