×

iFour Logo

Make your background task easy with Hangfire in .NET

Kapil Panchal - February 10, 2021

Listening is fun too.

Straighten your back and cherish with coffee - PLAY !

  • play
  • pause
  • pause
Make your background task easy with Hangfire in .NET

The background task is a type of task which runs in the background. For example, sometimes we run any task and it takes a long time so start a new task to work more efficiently. Let's take the example in the coding world sometimes we have to log in one page and after a fewprocesses need to send an email to the client so we can do send mail process in the background and continue the process which is unfinished in this sending mail is Background task.

Why we need background Tasks?


The background task is important when you need to run an operation which is taking a long time to finish its operations. Without the background task, we need to perform both operations one by one and the response can also take more time to reach the user and it is a bad user experience. With the Background task, you can run the task in the background to complete and give a response to the user more quickly and it is a good user experience.

What is Hangfire?


Hangfire is an open-source framework. It helps in creating a new process and manage the Background Task. The background task is also called The Background job. Hangfire help us to manage background tasks for example some tasks you can't put in the processing pipeline. From that type of operations some are listed below:

  • mass notifications/newsletter

  • batch import from xml, csv, json

  • creation of archives

  • firing off web hooks

  • deleting users

  • building different graphs

  • image/video processing

  • purge temporary files

  • recurring automated reports

  • database maintenance

Type of Hangfire Jobs


Hangfire had so many types of jobs a few of them are listed below:

  • Fire-and-forget

  • Delayed

  • Recurring

  • Continuations of other jobs

The Background Jobs are stored in your selected place. Hangfire has supported so many storages that are based on documents and relational.

Hangfire has its own automatic retry logic that retries the jobs and completes them so don't worry about the error thrown by the jobs. It uses workers to handle the tasks, you define the number of workers you would like and that they share the queue, running the tasks on a primary-come first-serve basis. Hang fire’s UI is itself protected by an API key and accessible from /Hangfire if you have the API key.

Now let's know how to configure Hangfire:

First of all, you need to create your regular core project. and have to select .NET5 in the web application.

After creating the project to use Hangfire, install a NuGet package of Hangfire is required. Below are listed some packages of Hangfire which are helpful to configure and setup authentication and store job-related information in SQL.

-Hangfire.AspNetCore

- Hangfire.Dashboard.Basic.Authentication

-Hangfire.MemoryStorage

-Hangfire.SqlServer

In this program, we will create connectivity with the database using DbFirst.So need to create one model first:

	using System;  
	using System.Collections.Generic;  
	using System.ComponentModel.DataAnnotations;  
	using System.Linq;  
	using System.Threading.Tasks;  
	namespace HangfireDemo.Model  
	{  
		public class EmployeeData 
		{  
		   [Key]  
			public int Id { get; set; }  
			public string EmployeeName { get; set; }  
			public string DesignationName { get; set; }   
		}  
	}
	

After creating model create DBContex in AppDbContext give its name EmpContex.cs like below:

 
	using Hangfire.Model;  
	using Microsoft.EntityFrameworkCore;  
	using System;  
	using System.Collections.Generic;  
	using System.Linq;  
	using System.Threading.Tasks;  
	  
	namespace Hangfire.AppDbContext  
	{  
		public partial class EmpContex : DbContext  
		{  
			public EmpContex(DbContextOptions options) : base(options)  
			{  
	  
			}  
			public DbSet Employees { get; set; }  
		}  
	}
	
	

After setting up the Connection string in appsettings.js, change code like below in Startup.cs file:

 
	using Hangfire.AppDbContext;  
	using Hangfire.Services;  
	using HangfireBasicAuthenticationFilter;  
	using Microsoft.AspNetCore.Builder;  
	using Microsoft.AspNetCore.Hosting;  
	using Microsoft.AspNetCore.HttpsPolicy;  
	using Microsoft.AspNetCore.Mvc;  
	using Microsoft.EntityFrameworkCore;  
	using Microsoft.Extensions.Configuration;  
	using Microsoft.Extensions.DependencyInjection;  
	using Microsoft.Extensions.Hosting;  
	using Microsoft.Extensions.Logging;  
	using Microsoft.OpenApi.Models;  
	using System;  
	using System.Collections.Generic;  
	using System.Linq;  
	using System.Threading.Tasks;  
	namespace DemoHangfire  
	{  
		public class Startup  
		{  
			private static IEmpService EmpService;  
			private readonly Job taskscheduler= new Job(EmpService);  
			public Startup(IConfiguration configuration)  
			{  
				Configuration = configuration;  
			}  
			public IConfiguration Configuration { get; }  
			// This method is called at the runtime. Use this method to add services in container.  
			public void ConfigureServices(IServiceCollection services)  
			{  
				services.AddControllers();  
				services.AddSwaggerGen(c =>
				{  
					c.SwaggerDoc("v1", new OpenApiInfo { Title = "Hangfire", Version = "v1" });  
				});  
				#region set Connection String  
				services.AddDbContext(item => item.UseSqlServer(Configuration.GetConnectionString("myconn")));  
				#endregion  
				#region Configure Hangfire  
				services.AddHangfire(c => c.UseSqlServerStorage(Configuration.GetConnectionString("myconn")));  
				GlobalConfiguration.Configuration.UseSqlServerStorage(Configuration.GetConnectionString("myconn")).WithJobExpirationTimeout(TimeSpan.FromDays(7));  
				#endregion  
				#region Services Injection  
				services.AddTransient();  
				#endregion  
			}  
			// This method called at the runtime. Use this method to configure the HTTP request pipeline.  
			public void Configure(IApplicationBuilder app, IWebHostEnvironment env,IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager)  
			{  
				if (env.IsDevelopment())  
				{  
					app.UseDeveloperExceptionPage();  
					app.UseSwagger();  
					app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Hangfire v1"));  
				}  
				#region Configure Hangfire  
				app.UseHangfireServer();  
				//Basic Authentication added to access the Hangfire Dashboard  
				app.UseHangfireDashboard("/hangfire", new DashboardOptions()  
				{  
					AppPath = null,  
					DashboardTitle = "Hangfire Dashboard",  
					Authorization = new[]{  
					new HangfireCustomBasicAuthenticationFilter{  
						User = Configuration.GetSection("HangfireCredentials:UserName").Value,  
						Pass = Configuration.GetSection("HangfireCredentials:Password").Value  
					}  
				},  
					//Authorization = new[] { new DashboardNoAuthorizationFilter() },  
					//IgnoreAntiforgeryToken = true  
				}); ;  
				#endregion  
				app.UseHttpsRedirection();  
				app.UseRouting();  
				app.UseAuthorization();  
				app.UseEndpoints(endpoints =>
				{  
					endpoints.MapControllers();  
				});  
				#region Job Scheduling Tasks  
				//recurringJobManager.AddOrUpdate("Insert Employee : Runs Every 1 Min", () => jobscheduler.JobAsync(), "*/1 * * * *");  
				#endregion  
			}  
		}  
	}
	
	

Looking to Hire .Net Developer? Your Search ends here.

Now create database table using the Migration commands and after create services for that.

 
	EmpService.cs
	  using Hangfire.AppDbContext;  
	  using Hangfire.Model;  
	  using System;  
	  using System.Collections.Generic;  
	  using System.Linq;  
	  using System.Threading.Tasks;  
	  namespace Hangfire.Services  
	  {  
		  public class EmployeeService : IEmployeeService  
		  {  
			  private readonly EmployeeDbContext _employeeDbContext;  
			  public EmployeeService(EmployeeDbContext employeeDbContext)  
			  {  
				  _employeeDbContext = employeeDbContext;  
			  }  
			  public async Task InsertEmployeeAsync()  
			  {  
				  try  
				  {  
					  Employee employee = new Employee()  
					  {  
						  EmployeeName = "Jk",  
						  Designation = "Full Stack Developer"  
					  };  
					  await _employeeDbContext.AddAsync(employee);  
					  await _employeeDbContext.SaveChangesAsync();  
					  return true;  
				  }  
				  catch (Exception ex)  
				  {  
					  throw;  
				  }  
			  }  
		  }  
	  }  
	  IEmpService.cs
	  using System;  
	  using System.Collections.Generic;  
	  using System.Linq;  
	  using System.Threading.Tasks;  
	  namespace Hangfire.Services  
	  {  
		 public interface IEmpService
		  {  
			  Task InsertEmployeeAsync();  
		  }  
	  } 
	  We are complete service injection in privious step in Startup.cs file  
	  #region Services Injection  
				  services.AddTransient();  
		 #endregion 
	  Now set the Password and id for access the Hangfire Dashboard
	  appsettings.js
	  "HangfireCredentials": {  
		  "UserName": "Demo",  
		  "Password": "Demo@123"  
		}
	  
	
Starup.cs
	  //add Authentication to access the Hangfire Dashboard  
				app.UseHangfireDashboard("/hangfire", new DashboardOptions()  
				{  
					AppPath = null,  
					DashboardTitle = "Hangfire Dashboard",  
					Authorization = new[]{  
					new HangfireCustomBasicAuthenticationFilter{  
						User = Configuration.GetSection("HangfireCredentials:UserName").Value,  
						Pass = Configuration.GetSection("HangfireCredentials:Password").Value  
					}  
				},  
				}); ;
	

Create background tasks


BJob.cs
	  using Hangfire.Services;  
	  using System;  
	  using System.Collections.Generic;  
	  using System.Linq;  
	  using System.Threading.Tasks;  
	  namespace DemoHangfire  
	  {  
		  public class BJob  
		  {  
			  #region Property  
			  private readonly EmpService _EmpService;  
			  #endregion  
			  #region Constructor  
			  public Job(IEmployeeService employeeService)  
			  {  
				  _EmpService = EmpService 
			  }  
			  #endregion  
			  #region Job Scheduler  
			  public async Task JobAsync()  
			  {  
				  var result = await __EmpService.InsertEmployeeAsync();  
				  return true;  
			  }  
			  #endregion  
		  }  
	  }
	  
	

After completingthe above process add Background task in Startup.cs

 
	#region Job Scheduling Tasks  
	// Recurring Job for every 5 min  
				recurringJobManager.AddOrUpdate("Insert Employee : Runs Every 1 Min", () => jobscheduler.JobAsync(), "*/5 * * * *");  
				//Fire and forget job   
				var jobId =  backgroundJobClient.Enqueue(() => jobscheduler.JobAsync());  
				//Continous the Job  
				backgroundJobClient.ContinueJobWith(jobId, () => jobscheduler.JobAsync());  
				//Schedule Job  
				backgroundJobClient.Schedule(() => jobscheduler.JobAsync(), TimeSpan.FromDays(5));  
				#endregion
	

After completing, the whole process for configuring the Hangfire, create the background jobs now run the project in the browser you can initially see the Swagger page. Remove swagger and write Hangfire and see the Hangfire view.

Conclusion


After reading this blog you will surely understand about the Hangfire and background jobs. Also, will come to know about the background process and how it is important for creating a more efficient web application. We also explained that how to configure Hangfire in the project and how to run it.

Make your background task easy with Hangfire in .NET The background task is a type of task which runs in the background. For example, sometimes we run any task and it takes a long time so start a new task to work more efficiently. Let's take the example in the coding world sometimes we have to log in one page and after a fewprocesses need to send an email to the client so we can do send mail process in the background and continue the process which is unfinished in this sending mail is Background task. Why we need background Tasks? The background task is important when you need to run an operation which is taking a long time to finish its operations. Without the background task, we need to perform both operations one by one and the response can also take more time to reach the user and it is a bad user experience. With the Background task, you can run the task in the background to complete and give a response to the user more quickly and it is a good user experience. What is Hangfire? Hangfire is an open-source framework. It helps in creating a new process and manage the Background Task. The background task is also called The Background job. Hangfire help us to manage background tasks for example some tasks you can't put in the processing pipeline. From that type of operations some are listed below: mass notifications/newsletter batch import from xml, csv, json creation of archives firing off web hooks deleting users building different graphs image/video processing purge temporary files recurring automated reports database maintenance Type of Hangfire Jobs Hangfire had so many types of jobs a few of them are listed below: Fire-and-forget Delayed Recurring Continuations of other jobs The Background Jobs are stored in your selected place. Hangfire has supported so many storages that are based on documents and relational. Hangfire has its own automatic retry logic that retries the jobs and completes them so don't worry about the error thrown by the jobs. It uses workers to handle the tasks, you define the number of workers you would like and that they share the queue, running the tasks on a primary-come first-serve basis. Hang fire’s UI is itself protected by an API key and accessible from /Hangfire if you have the API key. Now let's know how to configure Hangfire: First of all, you need to create your regular core project. and have to select .NET5 in the web application. After creating the project to use Hangfire, install a NuGet package of Hangfire is required. Below are listed some packages of Hangfire which are helpful to configure and setup authentication and store job-related information in SQL. -Hangfire.AspNetCore - Hangfire.Dashboard.Basic.Authentication -Hangfire.MemoryStorage -Hangfire.SqlServer Read More: Basic Authentication In Swagger (Open Api) .net5 In this program, we will create connectivity with the database using DbFirst.So need to create one model first: using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace HangfireDemo.Model { public class EmployeeData { [Key] public int Id { get; set; } public string EmployeeName { get; set; } public string DesignationName { get; set; } } } After creating model create DBContex in AppDbContext give its name EmpContex.cs like below:   using Hangfire.Model; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Hangfire.AppDbContext { public partial class EmpContex : DbContext { public EmpContex(DbContextOptions options) : base(options) { } public DbSet Employees { get; set; } } } After setting up the Connection string in appsettings.js, change code like below in Startup.cs file:   using Hangfire.AppDbContext; using Hangfire.Services; using HangfireBasicAuthenticationFilter; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace DemoHangfire { public class Startup { private static IEmpService EmpService; private readonly Job taskscheduler= new Job(EmpService); public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method is called at the runtime. Use this method to add services in container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Hangfire", Version = "v1" }); }); #region set Connection String services.AddDbContext(item => item.UseSqlServer(Configuration.GetConnectionString("myconn"))); #endregion #region Configure Hangfire services.AddHangfire(c => c.UseSqlServerStorage(Configuration.GetConnectionString("myconn"))); GlobalConfiguration.Configuration.UseSqlServerStorage(Configuration.GetConnectionString("myconn")).WithJobExpirationTimeout(TimeSpan.FromDays(7)); #endregion #region Services Injection services.AddTransient(); #endregion } // This method called at the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env,IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Hangfire v1")); } #region Configure Hangfire app.UseHangfireServer(); //Basic Authentication added to access the Hangfire Dashboard app.UseHangfireDashboard("/hangfire", new DashboardOptions() { AppPath = null, DashboardTitle = "Hangfire Dashboard", Authorization = new[]{ new HangfireCustomBasicAuthenticationFilter{ User = Configuration.GetSection("HangfireCredentials:UserName").Value, Pass = Configuration.GetSection("HangfireCredentials:Password").Value } }, //Authorization = new[] { new DashboardNoAuthorizationFilter() }, //IgnoreAntiforgeryToken = true }); ; #endregion app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); #region Job Scheduling Tasks //recurringJobManager.AddOrUpdate("Insert Employee : Runs Every 1 Min", () => jobscheduler.JobAsync(), "*/1 * * * *"); #endregion } } } Looking to Hire .Net Developer? Your Search ends here. See here Now create database table using the Migration commands and after create services for that.   EmpService.cs using Hangfire.AppDbContext; using Hangfire.Model; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Hangfire.Services { public class EmployeeService : IEmployeeService { private readonly EmployeeDbContext _employeeDbContext; public EmployeeService(EmployeeDbContext employeeDbContext) { _employeeDbContext = employeeDbContext; } public async Task InsertEmployeeAsync() { try { Employee employee = new Employee() { EmployeeName = "Jk", Designation = "Full Stack Developer" }; await _employeeDbContext.AddAsync(employee); await _employeeDbContext.SaveChangesAsync(); return true; } catch (Exception ex) { throw; } } } } IEmpService.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Hangfire.Services { public interface IEmpService { Task InsertEmployeeAsync(); } } We are complete service injection in privious step in Startup.cs file #region Services Injection services.AddTransient(); #endregion Now set the Password and id for access the Hangfire Dashboard appsettings.js "HangfireCredentials": { "UserName": "Demo", "Password": "Demo@123" } Starup.cs //add Authentication to access the Hangfire Dashboard app.UseHangfireDashboard("/hangfire", new DashboardOptions() { AppPath = null, DashboardTitle = "Hangfire Dashboard", Authorization = new[]{ new HangfireCustomBasicAuthenticationFilter{ User = Configuration.GetSection("HangfireCredentials:UserName").Value, Pass = Configuration.GetSection("HangfireCredentials:Password").Value } }, }); ; Create background tasks BJob.cs using Hangfire.Services; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace DemoHangfire { public class BJob { #region Property private readonly EmpService _EmpService; #endregion #region Constructor public Job(IEmployeeService employeeService) { _EmpService = EmpService } #endregion #region Job Scheduler public async Task JobAsync() { var result = await __EmpService.InsertEmployeeAsync(); return true; } #endregion } } After completingthe above process add Background task in Startup.cs   #region Job Scheduling Tasks // Recurring Job for every 5 min recurringJobManager.AddOrUpdate("Insert Employee : Runs Every 1 Min", () => jobscheduler.JobAsync(), "*/5 * * * *"); //Fire and forget job var jobId = backgroundJobClient.Enqueue(() => jobscheduler.JobAsync()); //Continous the Job backgroundJobClient.ContinueJobWith(jobId, () => jobscheduler.JobAsync()); //Schedule Job backgroundJobClient.Schedule(() => jobscheduler.JobAsync(), TimeSpan.FromDays(5)); #endregion After completing, the whole process for configuring the Hangfire, create the background jobs now run the project in the browser you can initially see the Swagger page. Remove swagger and write Hangfire and see the Hangfire view. Conclusion After reading this blog you will surely understand about the Hangfire and background jobs. Also, will come to know about the background process and how it is important for creating a more efficient web application. We also explained that how to configure Hangfire in the project and how to run it.
Kapil Panchal

Kapil Panchal

A passionate Technical writer and an SEO freak working as a Content Development Manager at iFour Technolab, USA. With extensive experience in IT, Services, and Product sectors, I relish writing about technology and love sharing exceptional insights on various platforms. I believe in constant learning and am passionate about being better every day.

Build Your Agile Team

Enter your e-mail address Please enter valid e-mail

Categories

Ensure your sustainable growth with our team

Talk to our experts
Sustainable
Sustainable
 
Blog Our insights
10 Executive Dashboard Examples for Consultants and CEOs
10 Executive Dashboard Examples for Consultants and CEOs

There is a principle behind every business. “If you don’t keep track of essentials, you won’t get clear direction, eventually causing your company to stumble.” To manage this scenario,...

How Spatial Data Analysis Improves Healthcare
How Spatial Data Analysis Improves Healthcare

Do you know when geospatial analysis took traction in healthcare? It was when John Snow, a London-based physician, used it to analyze the spread of cholera, which ultimately proved...

4 Types of Power BI Dashboards: Analytical, Strategic, Operational, and Tactical
4 Types of Power BI Dashboards: Analytical, Strategic, Operational, and Tactical

One interesting aspect you truly love about Power BI, as a CTO, is how it lets you step back and see the bigger picture of your business. Isn’t it? Without getting bogged down in minute...