Test in a live environment
Test in production without watermarks.
Works wherever you need it to.
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.
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
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.
Here we can see the weather GET APIs which return date, summary, and temperature.
Now let us add a Hangfire background job processor. Open project in Visual Studio.
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
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)
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
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)
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()
The server can also be added in ConfigureServices.
services.AddHangfireServer();
services.AddHangfireServer();
services.AddHangfireServer()
//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
//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)
//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))
//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!"))
//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)
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)
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.
The successful jobs can be viewed below.
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.
IronPDF is a NuGet package from Iron Software 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.
The main attraction of IronPDF is its HTML to PDF function, which preserves layouts and styles. It can create PDFs from web content, ideal for reports, invoices, and documentation. This feature supports converting HTML files, URLs, and HTML strings to PDFs.
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
// 1. Convert HTML String to PDF
var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");
// 2. Convert HTML File to PDF
var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");
// 3. Convert URL to PDF
var url = "http://ironpdf.com"; // Specify the URL
var pdfFromUrl = renderer.RenderUrlAsPdf(url);
pdfFromUrl.SaveAs("URLToPDF.pdf");
}
}
using IronPdf;
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
// 1. Convert HTML String to PDF
var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");
// 2. Convert HTML File to PDF
var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");
// 3. Convert URL to PDF
var url = "http://ironpdf.com"; // Specify the URL
var pdfFromUrl = renderer.RenderUrlAsPdf(url);
pdfFromUrl.SaveAs("URLToPDF.pdf");
}
}
Imports IronPdf
Friend Class Program
Shared Sub Main(ByVal args() As String)
Dim renderer = New ChromePdfRenderer()
' 1. Convert HTML String to PDF
Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")
' 2. Convert HTML File to PDF
Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")
' 3. Convert URL to PDF
Dim url = "http://ironpdf.com" ' Specify the URL
Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
pdfFromUrl.SaveAs("URLToPDF.pdf")
End Sub
End Class
Install-Package IronPdf
Install-Package IronPdf
Start using IronPDF in your project today with a free trial.
Check out IronPDF on Nuget for quick installation and deployment. With over 8 million downloads, it's transforming PDF with C#.
Install-Package IronPdf
Consider installing the IronPDF DLL directly. Download and manually install it for your project or GAC form: IronPdf.zip
Manually install into your project
Download DLLTo Integrate IronPDF into your Hangfire .NET project using the NuGet Package manager, follow these steps:
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.
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.
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
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
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.
The result looks like the below.
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.
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.
9 .NET API products for your office documents