Comprehensive Guide to Implementing Hangfire in a .NET C# Web API

Hangfire is a robust library for scheduling and executing background jobs in .NET applications. It eliminates the need for dedicated Windows Services or additional cron jobs by integrating directly into your .NET Web API. This guide walks you through the steps of implementing Hangfire in your .NET C# Web API, from setup to advanced usage.

It allows you to easily schedule tasks to run in the background, freeing up your web server to handle incoming requests promptly. 

This is crucial for long-running operations like sending emails, processing images, data imports, and more.


What is Hangfire?

Hangfire provides an intuitive way to manage background tasks in .NET applications. Its key features include:

  1. Fire-and-forget jobs: Execute tasks immediately in the background.
  2. Delayed jobs: Schedule tasks to run after a delay.
  3. Recurring jobs: Set up tasks to run periodically based on CRON expressions.
  4. Continuation jobs: Chain tasks to execute after a parent job finishes.
  5. Dashboard: Built-in monitoring UI for managing and troubleshooting jobs.

  • Easy Integration: Seamlessly integrates with various .NET environments, including ASP.NET Core, ASP.NET MVC, and more.
  • Persistence: Stores job information persistently (by default in SQL Server, but other options like Redis, MongoDB, and more are available). This ensures that jobs are not lost even if your application restarts.
  • Scheduling: Allows you to schedule jobs to run at specific times or intervals.
  • Monitoring and Management: Provides a web dashboard for monitoring job queues, inspecting individual jobs, and managing the execution process.
  • Retries: Automatically retries failed jobs with configurable delays and maximum attempts.


Step 1: Setting up the Project

  1. Create a .NET Web API Project:

    • Use Visual Studio or the .NET CLI:
      dotnet new webapi -n HangfireDemo
      cd HangfireDemo
      
  2. Add Hangfire NuGet Packages: Install Hangfire and its SQL Server storage provider:

    dotnet add package Hangfire
    dotnet add package Hangfire.SqlServer
    
  3. Configure the Database:

    • Update the appsettings.json with your database connection string:
      {
        "ConnectionStrings": {
          "HangfireConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HangfireDemoDB;Trusted_Connection=True;"
        }
      }
      

Step 2: Configure Hangfire

Integrate Hangfire into your application by modifying the entry point of your API. Configuration differs slightly based on your .NET version.

For .NET 6+ (Program.cs):

using Hangfire;
using Hangfire.SqlServer;

var builder = WebApplication.CreateBuilder(args);

// Add Hangfire services
builder.Services.AddHangfire(config =>
    config.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireConnection")));
builder.Services.AddHangfireServer();

// Add other services
builder.Services.AddControllers();

var app = builder.Build();

// Middleware for Hangfire Dashboard
app.UseHangfireDashboard("/hangfire");

// Map controllers
app.MapControllers();

app.Run();

For .NET 5 or earlier (Startup.cs):

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        // Configure Hangfire
        services.AddHangfire(config =>
            config.UseSqlServerStorage(Configuration.GetConnectionString("HangfireConnection")));
        services.AddHangfireServer();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        // Hangfire Dashboard Middleware
        app.UseHangfireDashboard();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

Step 3: Create Background Jobs

Hangfire supports multiple job types for different scenarios.

1. Fire-and-forget Jobs

Fire-and-forget jobs execute immediately in the background.

[ApiController]
[Route("api/jobs")]
public class JobController : ControllerBase
{
    [HttpPost("fire-and-forget")]
    public IActionResult CreateFireAndForgetJob()
    {
        BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget job executed!"));
        return Ok("Fire-and-forget job has been created.");
    }
}

2. Delayed Jobs

Delayed jobs run after a specified time interval.

[HttpPost("delayed")]
public IActionResult CreateDelayedJob()
{
    BackgroundJob.Schedule(() => Console.WriteLine("Delayed job executed!"), TimeSpan.FromMinutes(5));
    return Ok("Delayed job has been created.");
}

3. Recurring Jobs

Recurring jobs are scheduled to run periodically using CRON expressions.

[HttpPost("recurring")]
public IActionResult CreateRecurringJob()
{
    RecurringJob.AddOrUpdate("recurring-job", () => Console.WriteLine("Recurring job executed!"), Cron.Daily);
    return Ok("Recurring job has been created.");
}

4. Continuation Jobs

Continuation jobs are executed after a parent job finishes.

[HttpPost("continuation")]
public IActionResult CreateContinuationJob()
{
    var parentJobId = BackgroundJob.Enqueue(() => Console.WriteLine("Parent job executed!"));
    BackgroundJob.ContinueWith(parentJobId, () => Console.WriteLine("Continuation job executed!"));
    return Ok("Continuation job has been created.");
}

Step 4: Use the Hangfire Dashboard

The Hangfire dashboard provides a user-friendly interface for managing jobs. By default, it's accessible at /hangfire (e.g., http://localhost:5000/hangfire).

Securing the Dashboard

To secure the dashboard, you can implement a custom authorization filter:

public class HangfireDashboardAuthorizationFilter : IDashboardAuthorizationFilter
{
    public bool Authorize(DashboardContext context)
    {
        // Add custom authorization logic here (e.g., check user roles)
        return true; // Allow all access for demonstration purposes
    }
}

Configure the dashboard to use the filter:

app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    Authorization = new[] { new HangfireDashboardAuthorizationFilter() }
});

Step 5: Dependency Injection for Jobs

For better scalability, use dependency injection in your jobs.

  1. Create a Service:

    public class SampleService
    {
        public void ExecuteTask()
        {
            Console.WriteLine("Task executed by SampleService!");
        }
    }
    
  2. Register the Service: Add the service to the DI container:

    builder.Services.AddTransient<SampleService>();
    
  3. Use the Service in Jobs:

    [HttpPost("fire-and-forget-service")]
    public IActionResult CreateJobWithService([FromServices] SampleService service)
    {
        BackgroundJob.Enqueue(() => service.ExecuteTask());
        return Ok("Job with service has been created.");
    }
    

Best Practices

  1. Monitor Job Failures: Use the Hangfire dashboard to monitor failed jobs and set up retry policies.

  2. Use Distributed Systems for Scalability: Use Redis or other distributed storage systems in production environments.

  3. Secure Your Application: Protect the Hangfire dashboard with proper authentication and authorization.

  4. Optimize Performance:

    • Avoid long-running jobs; break them into smaller tasks.
    • Use job filters for centralized logging and exception handling.
  5. Database Maintenance: Regularly clean up completed or failed jobs to prevent database bloating.


Monitoring and Management:

  • Access the Hangfire dashboard (by default at /hangfire) to:
    • View job queues and their status.
    • Inspect individual jobs.
    • Re-enqueue failed jobs.
    • Manage recurring jobs.

Important Considerations:

  • Error Handling: Implement robust error handling in your background jobs to prevent failures from cascading.
  • Logging: Log job executions, successes, and failures for troubleshooting and monitoring.
  • Security: Secure the Hangfire dashboard by restricting access to authorized users.
  • Performance: Monitor job processing performance and adjust settings (e.g., concurrency limits) as needed.


Conclusion

Hangfire simplifies the management of background jobs in .NET applications. By following this guide, you can integrate Hangfire into your .NET Web API, schedule and monitor jobs, and ensure robust task execution. Whether you're building a small-scale application or a large distributed system, Hangfire is a powerful tool to enhance functionality and scalability.

Comments

Popular posts from this blog

Transforming Sri Lankan Healthcare Through Digital Governance: A Practical Roadmap

Azure Service Bus Integration with Microsoft Dynamics CRM Online

Enhancing a Stripe and MS CRM Integration Guide for Junior Developers