There are a number of use cases when you need to perform background processing in a web application.
- 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;
The problem is performing background jobs in a web application is very prone to failure:
- An unhandled exception in a thread not associated with a request will take down the process.
- If you run your site in a Web Farm, you could end up with multiple instances of your app that all attempt to run the same task at the same time.
- The AppDomain your site runs in can go down for a number of reasons and take down your background task with it.
That’s where HangFire comes in. HangFire as described on thier home page is “an easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required. Backed by persistent storage. Open and free for commercial use.” HangFire supports all kind of background tasks – short-running and long-running, CPU intensive and I/O intensive, one shot and recurrent. You don’t need to reinvent the wheel – it is ready to use. The best feature of HangFire is its built in dashboard that shows you all your scheduled, processing, succeeded, and failed jobs.
HangFire is easy to get started with. They have great documentation with a good QuickStart guide. I couldn’t find a good tutorial for getting started with HangFire using ASP.NET Core and SQL Server 2016 using Docker so I thought I would put together a step by step guide.
Step one is to install Docker.
Once you have Docker installed verify that you are in Windows container mode by right clicking on the docker whale icon in the task bar. Then verify that the menu option says Swith to Linux Containers. If not then it should say Swith to Windows Containers and you need to click it.
Now open an administrative command line and run the following command to pull down the SQL server container.
docker pull microsoft/mssql-server-windows-express
Run the following command. Be sure to replace the SA password with one that meets the SQL Server Password Policy.
docker run -d -p 1433:1433 -e sa_password=<YOUR_PWD> -e ACCEPT_EULA=Y -v c:/data/:c:/data/ microsoft/mssql-server-windows-express
Use the docker ps command to get the container ID that you want to connect to and use it to replace the parameter placeholder ‘<DOCKER_CONTAINER_ID>’ in the commands below. Run the following command to connect to the SQL Server. Be sure to replace the container id.
docker exec -it <DOCKER_CONTAINER_ID> sqlcmd -S. -Usa
Run the following commands to create the HangFire database and user.
CREATE DATABASE HangFire ON PRIMARY ( NAME = N'HangFire', FILENAME = N'C:\Data\HangFire.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB ); GO CREATE LOGIN HangFireUser WITH PASSWORD = '340$Uuxwp7Mcxo7Khy'; USE HangFire; GO CREATE USER HangFireUser FOR LOGIN HangFireUser WITH DEFAULT_SCHEMA = HangFire; GO EXEC sp_addrolemember 'db_owner', 'HangFireUser'; GO
Run the following commands
dotnet new -t web
You should be able to go to a browser and enter the URL locahost:5000 to view the application.
Now to configure HangFire all you need to do is add the following packages to the csproj file.
<PackageReference Include="Hangfire.Core" Version="1.6.8" /> <PackageReference Include="Hangfire.AspNetCore" Version="1.6.8" /> <PackageReference Include="Hangfire.SqlServer" Version="1.6.8" />
Add the following using statement to the Startup.cs.
Add the following to the Startup.cs ConfigureServices method. Be sure to update the container IP address in the connection string. To get the IP address of the container run the command docker inspect <container_name>.
services.AddHangfire(configuration => configuration.UseSqlServerStorage(@"Server=<CONTAINER_IPADDRESS>;Database=HangFire;User Id=HangFireUser; Password=340$Uuxwp7Mcxo7Khy;"));
Add the following to the Startup.cs Configure method.
app.UseHangfireDashboard(); // Will be available under http://localhost:5000/hangfire app.UseHangfireServer();
Now lets add some jobs. Add the following code at the end of your Startup.cs Configure method.
//Fire-and-Forget BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget")); //Delayed BackgroundJob.Schedule(() => Console.WriteLine("Delayed"), TimeSpan.FromDays(1)); //Recurring RecurringJob.AddOrUpdate(() => Console.WriteLine("Minutely Job"), Cron.Minutely); //Continuation var id = BackgroundJob.Enqueue(() => Console.WriteLine("Hello, ")); BackgroundJob.ContinueWith(id, () => Console.WriteLine("world!"));
That is it lets run the application and verify we can see the dashboard. Run the follownig command.
In your browser navigate to localhost:5000/hangfire and you should see the dashboard.
- Docker for Windows
- SQL Server Container Documentation
- SQL Server Container Article
- HangFire QuickStart
- How to run Background Task in ASP.NET
- The Dangers of Implementing Recurring Background Tasks In ASP.NET
- Message queues & you – 12 reasons to use message queuing
- Simplified .NET Background Tasks with Hangfire
- CronMaker – a utility which helps you to build cron expressions
- Don’t do it now – a series of articles discussing job scheduling and HangFire
- Fire and Forget on ASP.NET