×

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.

 

Table of Content

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.   Table of Content 1. Why we need background Tasks? 2. What is Hangfire? 3. Type of Hangfire Jobs 4. Conclusion 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.

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

Power Apps vs Power Automate: When to Use What?
Power Apps vs Power Automate: When to Use What?

I often see people asking questions like “Is Power App the same as Power Automate?”. “Are they interchangeable or have their own purpose?”. We first need to clear up this confusion...

Azure DevOps Pipeline Deployment for Competitive Business: The Winning Formula
Azure DevOps Pipeline Deployment for Competitive Business: The Winning Formula

We always hear about how important it is to be competitive and stand out in the market. But as an entrepreneur, how would you truly set your business apart? Is there any way to do...

React 18 Vs React 19: Key Differences To Know For 2024
React 18 Vs React 19: Key Differences To Know For 2024

Ever wondered how a simple technology can spark a revolution in the IT business? Just look at React.js - a leading Front-end JS library released in 2013, has made it possible. Praised for its seamless features, React.js has altered the way of bespoke app development with its latest versions released periodically. React.js is known for building interactive user interfaces and has been evolving rapidly to meet the demands of modern web development. Thus, businesses lean to hire dedicated React.js developers for their projects. React.js 19 is the latest version released and people are loving its amazing features impelling them for its adoption.