Serving Industries Worldwide

Innovative Ways - Satisfied Clientele

Make your background task easy with Hangfire in .NET


Listening is fun too.

Straighten your back and cherish with coffee - PLAY !

 
 

Make your background

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:

  1. mass notifications/newsletter
  2. batch import from xml, csv, json
  3. creation of archives
  4. firing off web hooks
  5. deleting users
  6. building different graphs
  7. image/video processing
  8. purge temporary files
  9. recurring automated reports
  10. database maintenance

Type of Hangfire Jobs

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

  1. Fire-and-forget
  2. Delayed
  3. Recurring
  4. 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 ASP.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

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:

  1. mass notifications/newsletter
  2. batch import from xml, csv, json
  3. creation of archives
  4. firing off web hooks
  5. deleting users
  6. building different graphs
  7. image/video processing
  8. purge temporary files
  9. recurring automated reports
  10. database maintenance

Type of Hangfire Jobs

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

  1. Fire-and-forget
  2. Delayed
  3. Recurring
  4. 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 ASP.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.