Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?


Official Site NuGet Build status License MIT

This repo is the extension for Hangfire to build RecurringJob automatically. When app start, RecurringJob will be added/updated automatically. There is two ways to build RecurringJob.

  • RecurringJobAttribute attribute
  • Json Configuration

Using RecurringJobAttribute

We can use the attribute RecurringJobAttribute to assign the interface/instance/static method.

public class RecurringJobService
    [RecurringJob("*/1 * * * *")]
    public void TestJob1(PerformContext context)
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} TestJob1 Running ...");
    [RecurringJob("*/2 * * * *", RecurringJobId = "TestJob2")]
    public void TestJob2(PerformContext context)
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} TestJob2 Running ...");
    [RecurringJob("*/2 * * * *", "China Standard Time", "jobs")]
    public void TestJob3(PerformContext context)
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} TestJob3 Running ...");
    [RecurringJob("*/5 * * * *", "jobs")]
    public void InstanceTestJob(PerformContext context)
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} InstanceTestJob Running ...");

    [RecurringJob("*/6 * * * *", "UTC", "jobs")]
    public static void StaticTestJob(PerformContext context)
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} StaticTestJob Running ...");

Json Configuration

It is similar to, We also define the unified interface IRecurringJob. Recurring jobs must impl the specified interface like this.

[AutomaticRetry(Attempts = 0)]
public class LongRunningJob : IRecurringJob
    public void Execute(PerformContext context)
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} LongRunningJob Running ...");

        var runningTimes = context.GetJobData<int>("RunningTimes");

        context.WriteLine($"get job data parameter-> RunningTimes: {runningTimes}");

        var progressBar = context.WriteProgressBar();

        foreach (var i in Enumerable.Range(1, runningTimes).ToList().WithProgress(progressBar))

Now we need to provider the json config file to assign the implemented recurring job, the json configuration samples as below.

    "job-name": "My Job1",
    "job-type": "Hangfire.Samples.MyJob1, Hangfire.Samples",
    "cron-expression": "*/1 * * * *",
    "timezone": "China Standard Time",
    "queue": "jobs"
    "job-name": "My Job2",
    "job-type": "Hangfire.Samples.MyJob2, Hangfire.Samples",
    "cron-expression": "*/5 * * * *",
    "job-data": {
        "IntVal": 1,
        "StringVal": "abcdef",
        "BooleanVal": true,
        "SimpleObject": {
            "Name": "Foo",
            "Age": 100
    "job-name": "Long Running Job",
    "job-type": "Hangfire.Samples.LongRunningJob, Hangfire.Samples",
    "cron-expression": "*/2 * * * *",
    "job-data": {
        "RunningTimes": 300

The json token description to the configuration is here.

JSON Token Description
job-name [required] The job name to RecurringJob.
job-type [required] The job type while impl the interface IRecurringJob.
cron-expression [required] Cron expressions.
timezone [optional] Default value is TimeZoneInfo.Utc.
queue [optional] The specified queue name , default value is default.
job-data [optional] Similar to the JobDataMap, it is can be deserialized to the type Dictionary<string,object>.
enable [optional] Whether the RecurringJob can be added/updated, default value is true, if false RecurringJob will be deleted automatically.

To the json token job-data, we can use extension method to get/set data with specified key from storage which associated with BackgroundJob.Id when recurring job running.

var intVal = context.GetJobData<int>("IntVal");

context.SetJobData("IntVal", ++intVal);

Building RecurringJob

  • Building with CronJob.

In hangfire client, we can use the helper class CronJob to add or update recurringjob automatically.

//Builds within specified interface or class.

//Builds by using multiple JSON configuration files.
  • Building with IGlobalConfiguration.

Use IGlobalConfiguration extension method UseRecurringJob to build RecurringJob, in .NET Core's Startup.cs.

public void ConfigureServices(IServiceCollection services)
    services.AddHangfire(x =>


        //using json config file to build RecurringJob automatically.
        //using RecurringJobAttribute to build RecurringJob automatically.


For the json configuration file, we can monitor the file change and reload RecurringJob dynamically by passing the parameter reloadOnChange = true.