Hangfire .NET Core (How It Works For Developer)

Modern application development often requires processing background tasks to handle huge tasks, in this scenario we require background job handlers to execute multiple jobs. There are many job handlers, and one such background parent job handler for C# .NET Core applications is Hangfire. In this blog, we are going to learn about the Hangfire background job and how to use it with other packages like IronPDF to generate PDF documents in the background.

Introduction

Hangfire simplifies the implementation of background processing in ASP.NET Core or .NET Core 6 Web API applications by providing a reliable and flexible framework for managing and executing background jobs. Hangfire is available as a NuGet package and can be installed using .NET CLI as below.

dotnet add package Hangfire --version 1.8.6

Implementation in .NET Core Web API

To learn about Hangfire, let us create a simple .NET Core API application and install Hangfire using CLI.

dotnet new webapi -n HangfireDemo
cd HangfireDemo
dotnet build
dotnet add package Hangfire --version 1.8.6
dotnet build

Here we are creating a simple weather REST API using .NET CLI. The first line creates a Core Web API project named HangfireDemo (also can create ASP.NET Core) to execute API endpoints. The second line is to navigate to our newly created folder "HangfireDemo" and then build the project. Next, we added the Hangfire NuGet package to our project and again built it. After this, you can open your project in any editor of your choice, Visual Studio 2022 or JetBrains Rider. Now if you run the project you can see the Swagger as below.

Hangfire .NET Core (How It Works For Developer): Figure 1 - Swagger

Here we can see the weather GET APIs which return date, summary, and temperature.

Hangfire .NET Core (How It Works For Developer): Figure 2 - Weather GET API

Now let us add a Hangfire background job processor. Open project in Visual Studio.

Add Hangfire Job Processor

Configure Hangfire in your application, typically in the Startup.cs file. This involves setting up a job storage and initializing the Hangfire server.

// Startup.cs
using Hangfire;
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add Hangfire services
        services.AddHangfire(config => config.UseSqlServerStorage("your_connection_string"));
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Configure Hangfire
        app.UseHangfireServer();
        app.UseHangfireDashboard();
        // Your other configuration settings
    }
}
// Startup.cs
using Hangfire;
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add Hangfire services
        services.AddHangfire(config => config.UseSqlServerStorage("your_connection_string"));
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Configure Hangfire
        app.UseHangfireServer();
        app.UseHangfireDashboard();
        // Your other configuration settings
    }
}
' Startup.cs
Imports Hangfire
Public Class Startup
	Public Sub ConfigureServices(ByVal services As IServiceCollection)
		' Add Hangfire services
		services.AddHangfire(Function(config) config.UseSqlServerStorage("your_connection_string"))
	End Sub
	Public Sub Configure(ByVal app As IApplicationBuilder, ByVal env As IHostingEnvironment)
		' Configure Hangfire
		app.UseHangfireServer()
		app.UseHangfireDashboard()
		' Your other configuration settings
	End Sub
End Class
VB   C#

The ConfigureServices is used to add storage to save Hangfire's newly created jobs. Here SQL Server database is used. The SQL Server connection string should be replaced with "your_connection_string". One can also use in-memory storage with Hangfire.InMemory.

dotnet add package Hangfire.InMemory --version 0.6.0

And replace with

services.AddHangfire(configuration => { configuration.UseInMemoryStorage(); });
services.AddHangfire(configuration => { configuration.UseInMemoryStorage(); });
services.AddHangfire(Sub(configuration)
	configuration.UseInMemoryStorage()
End Sub)
VB   C#

Create Background Jobs

Define the methods you want to run as a background job. These methods should be static or instance methods of a class with a parameterless constructor. The jobs can be run as recurring jobs or many jobs can be run.

public class MyBackgroundJob
{
    public void ProcessJob()
    {
        // Your background job logic, recurring job or multiple jobs
        Console.WriteLine("Background job is running...");
    }
}
public class MyBackgroundJob
{
    public void ProcessJob()
    {
        // Your background job logic, recurring job or multiple jobs
        Console.WriteLine("Background job is running...");
    }
}
Public Class MyBackgroundJob
	Public Sub ProcessJob()
		' Your background job logic, recurring job or multiple jobs
		Console.WriteLine("Background job is running...")
	End Sub
End Class
VB   C#

Enqueue Jobs

Enqueue background jobs using the Hangfire API. You can schedule background jobs to run at a specific time, after a delay, or regularly.

// Enqueue a job to run immediately
BackgroundJob.Enqueue<MyBackgroundJob>(x => x.ProcessJob());
// Schedule a job to run after 5 min delay, delayed job
BackgroundJob.Schedule<MyBackgroundJob>(x => x.ProcessJob(), TimeSpan.FromMinutes(5));
// Schedule a recurring job / recurring jobs using job Id
RecurringJob.AddOrUpdate<MyBackgroundJob>("job Id", x => x.ProcessJob(), Cron.Daily);
// Enqueue a job to run immediately
BackgroundJob.Enqueue<MyBackgroundJob>(x => x.ProcessJob());
// Schedule a job to run after 5 min delay, delayed job
BackgroundJob.Schedule<MyBackgroundJob>(x => x.ProcessJob(), TimeSpan.FromMinutes(5));
// Schedule a recurring job / recurring jobs using job Id
RecurringJob.AddOrUpdate<MyBackgroundJob>("job Id", x => x.ProcessJob(), Cron.Daily);
' Enqueue a job to run immediately
BackgroundJob.Enqueue(Of MyBackgroundJob)(Function(x) x.ProcessJob())
' Schedule a job to run after 5 min delay, delayed job
BackgroundJob.Schedule(Of MyBackgroundJob)(Function(x) x.ProcessJob(), TimeSpan.FromMinutes(5))
' Schedule a recurring job / recurring jobs using job Id
RecurringJob.AddOrUpdate(Of MyBackgroundJob)("job Id", Function(x) x.ProcessJob(), Cron.Daily)
VB   C#

Hangfire Dashboard and Server

The Hangfire dashboard and server can be added in the Configure method.

// Run Hangfire server
app.UseHangfireServer();
app.UseHangfireDashboard();
// Run Hangfire server
app.UseHangfireServer();
app.UseHangfireDashboard();
' Run Hangfire server
app.UseHangfireServer()
app.UseHangfireDashboard()
VB   C#

The server can also be added in ConfigureServices.

services.AddHangfireServer();
services.AddHangfireServer();
services.AddHangfireServer()
VB   C#

Fire and Forget Jobs

//Fire and forget job / Fire and forget jobs are executed only once and almost immediately after creation.
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!")); //jobId for Fire and forget job
//Fire and forget job / Fire and forget jobs are executed only once and almost immediately after creation.
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!")); //jobId for Fire and forget job
'Fire and forget job / Fire and forget jobs are executed only once and almost immediately after creation.
Dim jobId = BackgroundJob.Enqueue(Sub() Console.WriteLine("Fire-and-forget!")) 'jobId for Fire and forget job
VB   C#

Recurring Jobs

//Recurring jobs fire many times on the specified CRON schedule.
RecurringJob.AddOrUpdate( "myrecurringjob",() => Console.WriteLine("Recurring!"),Cron.Daily);
//Recurring jobs fire many times on the specified CRON schedule.
RecurringJob.AddOrUpdate( "myrecurringjob",() => Console.WriteLine("Recurring!"),Cron.Daily);
'Recurring jobs fire many times on the specified CRON schedule.
RecurringJob.AddOrUpdate("myrecurringjob",Sub() Console.WriteLine("Recurring!"),Cron.Daily)
VB   C#

Delayed Jobs

//Delayed jobs are executed only once too, but not immediately, after a certain specific interval.
var jobId = BackgroundJob.Schedule(() => Console.WriteLine("Delayed!"),
    TimeSpan.FromDays(7));
//Delayed jobs are executed only once too, but not immediately, after a certain specific interval.
var jobId = BackgroundJob.Schedule(() => Console.WriteLine("Delayed!"),
    TimeSpan.FromDays(7));
'Delayed jobs are executed only once too, but not immediately, after a certain specific interval.
Dim jobId = BackgroundJob.Schedule(Sub() Console.WriteLine("Delayed!"), TimeSpan.FromDays(7))
VB   C#

Continuations

//Continuation jobs are executed when its parent job has been finished, immediate child job
BackgroundJob.ContinueJobWith(jobId,() => Console.WriteLine("Continuation!"));
//Continuation jobs are executed when its parent job has been finished, immediate child job
BackgroundJob.ContinueJobWith(jobId,() => Console.WriteLine("Continuation!"));
'Continuation jobs are executed when its parent job has been finished, immediate child job
BackgroundJob.ContinueJobWith(jobId,Sub() Console.WriteLine("Continuation!"))
VB   C#

Batch Job

//Batch is a group of background jobs that is created atomically and considered as a single entity. Two jobs can be run as below.
var batchId = BatchJob.StartNew(x =>
{
    x.Enqueue(() => Console.WriteLine("Job 1"));
    x.Enqueue(() => Console.WriteLine("Job 2"));
});
//Batch is a group of background jobs that is created atomically and considered as a single entity. Two jobs can be run as below.
var batchId = BatchJob.StartNew(x =>
{
    x.Enqueue(() => Console.WriteLine("Job 1"));
    x.Enqueue(() => Console.WriteLine("Job 2"));
});
'Batch is a group of background jobs that is created atomically and considered as a single entity. Two jobs can be run as below.
Dim batchId = BatchJob.StartNew(Sub(x)
	x.Enqueue(Sub() Console.WriteLine("Job 1"))
	x.Enqueue(Sub() Console.WriteLine("Job 2"))
End Sub)
VB   C#

Batch Continuation Job

Batch continuation is fired when all background jobs in a parent batch are finished.
BatchJob.ContinueBatchWith(batchId, x =>
{
    x.Enqueue(() => Console.WriteLine("Last Job"));
});
Batch continuation is fired when all background jobs in a parent batch are finished.
BatchJob.ContinueBatchWith(batchId, x =>
{
    x.Enqueue(() => Console.WriteLine("Last Job"));
});
Dim tempVar As Boolean = TypeOf continuation Is fired
Dim [when] As fired = If(tempVar, CType(continuation, fired), Nothing)
Batch tempVar all background jobs in a parent batch are finished.BatchJob.ContinueBatchWith(batchId, Sub(x)
	x.Enqueue(Sub() Console.WriteLine("Last Job"))
End Sub)
VB   C#

Dashboard

Hangfire Dashboard is where you can find all the information about your background jobs. It is written as an OWIN middleware (if you are not familiar with OWIN, don’t worry), so you can plug it into your ASP.NET, ASP.NET MVC, Nancy, and ServiceStack application as well as use the OWIN Self-Host feature to host Dashboard inside Console Applications or in Windows Services.

When you have the dashboard enabled in your view, the dashboard is at /hangfire/ extension. In this dashboard, one can manage background running jobs, schedule background jobs, view fire and forget jobs, and recurring jobs. The jobs can be identified using job ID.

Live processing

Hangfire .NET Core (How It Works For Developer): Figure 3 - Live Processing of Jobs

Succeeded Jobs

The successful jobs can be viewed below.

Hangfire .NET Core (How It Works For Developer): Figure 4 - Succeeded Jobs

Scheduled jobs

Hangfire .NET Core (How It Works For Developer): Figure 5 - Scheduled Jobs

Now, when your application runs, Hangfire will take care of processing the background jobs based on the configured settings.

Remember to check the Hangfire documentation for more advanced configuration options and features: Hangfire Documentation and complete code can be found on GitHub.

Introducing IronPDF

IronPDF is a NuGet package from IronSoftware that helps to read and generate PDF docs. It can convert easily formatted documents with style information to PDF. IronPDF can easily generate PDFs from HTML content. It can download the HTML from the URL and then generate PDFs.

Install IronPDF Library

C# NuGet Library for PDF

Install with NuGet

Install-Package IronPdf
or
C# PDF DLL

Download DLL

Download DLL

Manually install into your project

Install Using NuGet Package Manager

To Integrate IronPDF into your Hangfire .NET project using the NuGet Package manager, follow these steps:

  1. Open Visual Studio and in the solution explorer, right click on your project.
  2. Choose “Manage NuGet packages…” from the context menu.
  3. Go to the browse tab and search IronPDF.
  4. Select IronPDF library from the search results and click install button.
  5. Accept any license agreement prompt.

If you want to include IronPDF in your project via Package manager console, then execute the following command in Package Manager Console:

Install-Package IronPdf

It’ll fetch and install IronPDF into your project.

Install Using NuGet Website

For a detailed overview of IronPDF, including its features, compatibility, and additional download options, visit the IronPDF page on the NuGet website at https://www.nuget.org/packages/IronPdf.

Install Via DLL

Alternatively, you can incorporate IronPDF directly into your project using its dll file. Download the ZIP file containing the DLL from this link. Unzip it, and include the DLL in your project.

Now let's modify our application to add a background processing job to download a HTTP request pipeline website as a PDF file.

namespace HangfireDemo.Core;
public class PdfGenerationJob
{
    public void Start(string website)
    {
        // Create a PDF from any existing web page
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        PdfDocument pdf = renderer.RenderUrlAsPdf(website);
        var filePath = AppContext.BaseDirectory + "result.pdf";
        pdf.SaveAs(filePath);
    }
}
namespace HangfireDemo.Core;
public class PdfGenerationJob
{
    public void Start(string website)
    {
        // Create a PDF from any existing web page
        ChromePdfRenderer renderer = new ChromePdfRenderer();
        PdfDocument pdf = renderer.RenderUrlAsPdf(website);
        var filePath = AppContext.BaseDirectory + "result.pdf";
        pdf.SaveAs(filePath);
    }
}
Namespace HangfireDemo.Core
	Public Class PdfGenerationJob
		Public Sub Start(ByVal website As String)
			' Create a PDF from any existing web page
			Dim renderer As New ChromePdfRenderer()
			Dim pdf As PdfDocument = renderer.RenderUrlAsPdf(website)
			Dim filePath = AppContext.BaseDirectory & "result.pdf"
			pdf.SaveAs(filePath)
		End Sub
	End Class
End Namespace
VB   C#

IronPDF has an inbuilt method to download a website from a URL and save it as a PDF document. We are going to use this method in our job to download and save it to a temp location. This background job can be modified to take multiple website URLs and save them as PDFs.

Now let us add a controller to expose the PDF generation and download APIs.

using Hangfire;
using HangfireDemo.Core;
using Microsoft.AspNetCore.Mvc;
namespace HangfireDemo.Controllers;
[ApiController]
[Route("[controller]")]
public class PdfGeneratorController : ControllerBase
{
    [HttpGet("request", Name = "Start PDF Generation")]
    public void Start([FromQuery] string websiteUrl)
    {
        BackgroundJob.Enqueue<PdfGenerationJob>(x => x.Start(websiteUrl));
    }
    [HttpGet("result", Name = "Download PDF Generation")]
    public IActionResult WebResult()
    {
        var filePath = AppContext.BaseDirectory + "result.pdf";
        var stream = new FileStream(filePath, FileMode.Open);
       return new FileStreamResult(stream, "application/octet-stream") { FileDownloadName = "website.pdf" };
    }
}
using Hangfire;
using HangfireDemo.Core;
using Microsoft.AspNetCore.Mvc;
namespace HangfireDemo.Controllers;
[ApiController]
[Route("[controller]")]
public class PdfGeneratorController : ControllerBase
{
    [HttpGet("request", Name = "Start PDF Generation")]
    public void Start([FromQuery] string websiteUrl)
    {
        BackgroundJob.Enqueue<PdfGenerationJob>(x => x.Start(websiteUrl));
    }
    [HttpGet("result", Name = "Download PDF Generation")]
    public IActionResult WebResult()
    {
        var filePath = AppContext.BaseDirectory + "result.pdf";
        var stream = new FileStream(filePath, FileMode.Open);
       return new FileStreamResult(stream, "application/octet-stream") { FileDownloadName = "website.pdf" };
    }
}
Imports Hangfire
Imports HangfireDemo.Core
Imports Microsoft.AspNetCore.Mvc
Namespace HangfireDemo.Controllers
	<ApiController>
	<Route("[controller]")>
	Public Class PdfGeneratorController
		Inherits ControllerBase

		<HttpGet("request", Name := "Start PDF Generation")>
		Public Sub Start(<FromQuery> ByVal websiteUrl As String)
			BackgroundJob.Enqueue(Of PdfGenerationJob)(Function(x) x.Start(websiteUrl))
		End Sub
		<HttpGet("result", Name := "Download PDF Generation")>
		Public Function WebResult() As IActionResult
			Dim filePath = AppContext.BaseDirectory & "result.pdf"
			Dim stream = New FileStream(filePath, FileMode.Open)
		   Return New FileStreamResult(stream, "application/octet-stream") With {.FileDownloadName = "website.pdf"}
		End Function
	End Class
End Namespace
VB   C#

Here we have created two APIs, one to start the background job to take the website URL and initiate the download. Another API is to download the PDF result. The APIs look like as shown below.

Hangfire .NET Core (How It Works For Developer): Figure 7 - PDFGenerator APIs

The result looks like the below.

Hangfire .NET Core (How It Works For Developer): Figure 8 - Output

Licensing (Free Trial Available)

For the above code to work without a watermark, a license key is required. A trial license is available for developers up on registering here and yes, no credit card is required for a trial license. One can provide the email ID and register for a free trial.

Conclusion

Hangfire and IronPDF together are a great combination to generate and download PDFs in the background. We can use Hangfire in various programming paradigms to process long-running tasks. IronPDF provides a flexible and easy-to-use solution to generate PDFs. To know more about IronPDF, you can find the documents here.

Also, you can explore other tools from Iron Software which will help you improve your coding skills and achieve modern application requirements.