Better Task Scheduling in Umbraco

In the previous post I went through the steps required to get Hangfire running in an MVC application. Hangfire has a huge amount of features and allows developers to quickly implement recurring background jobs with very little setup.

Umbraco already has the notion of scheduled tasks, but this is very basic and relies on publicly available URLs to trigger tasks. It is also limited to a recurring task that can only be fired on a fixed interval so no real scheduling options. This is achieved by adding a line to the umbracoSettings.config:

<scheduledTasks>
    <!-- add tasks that should be called with an interval (seconds) -->
    <task log="true" alias="someTask" interval="900" url="http://mydomain/task"/>
</scheduledTasks>

I was pleasantly surprised that it is almost as straight forward to get Hangfire up and running with Umbraco as it was in a vanilla MVC application.

The first step is to install hangfire, nuget is the easiest method for this:

PM> Install-Package Hangfire

Next you need to create the Startup.cs class for Owin, this generally will go in your web root. If you check out the hangfire readme.txt it will recommend something along the following lines:

using Hangfire;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(MyWebApplication.Startup))]
namespace MyWebApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            GlobalConfiguration.Configuration.UseSqlServerStorage("<name or connection string>");

            app.UseHangfireDashboard();
            app.UseHangfireServer();
        }
    }
}

Normally this would work on its own but we are running in the context of an Umbraco application so a few modifications are required. First Umbraco has its own OwinStartup class that you will want to extend and override the Configuration method, remember to call the base version prior to your own code.

using Hangfire;
using Microsoft.Owin;
using Owin;
using Umbraco.Web; [assembly: OwinStartup(typeof(MyWebApplication.Startup))] namespace MyWebApplication {     public class Startup : UmbracoDefaultOwinStartup     {         public override void Configuration(IAppBuilder app)         {             base.Configuration(app);             GlobalConfiguration.Configuration.UseSqlServerStorage("umbracoDbDSN");             app.UseHangfireDashboard();             app.UseHangfireServer();         }     } }

One point to make is that Hangfire needs to create its db structure on first run so your umbracoDbDSN connection will need sufficient permissions. Alternatively you may want to create the Hangfire table structure locally and run a script to make the db updates.

The Hangfire dashboard is a neat tool to allow you to view the scheduled jobs and server health, by default this will be available on /hangfire but only for local connections. If you want to use this feature you need to add the path to the umbracoReservedPaths in your web.config:

<add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/hangfire" />

You also need to let Umbraco know that you want to use your own custom Owin Startup class. In the web.config update the value for owin:appStartup this needs to be the fully qualified name of your custom class to work.

<add key="owin:appStartup" value="MyWebApplication.Startup" />

The last step is to actually run some background jobs, this is pretty straight forward, assuming you have a static class somewhere that performs some task you can add a line to your Startup.cs class to schedule the job:

RecurringJob.AddOrUpdate(() => SystemTask.MyTask(), Cron.Daily(20));

There are lots of options with Hangfire depending on your specific need this was tested with Umbraco 7.4.2, Hangfire 1.5.6 and MVC 5.2.3.