JobStorage.Current property value has not been initialized. You must set it before using Hangfire Client or Server API
Asked Answered
F

6

22

I am using hangfire in mvc application. I am sending reminder to user for his/her appointment. I have installed hangfire in my app. I have configured hangfire in startup.cs class. But when i run the app, it produce the below error, JobStorage. Current property value has not been initialized. You must set it before using Hangfire Client or Server API.

using Hangfire;
using Hangfire.SqlServer;
using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using UKC.Data.Infrastructure;
using UKC.UI.Helper;

[assembly: OwinStartup(typeof(UKC.UI.App_Start.Startup))]
namespace UKC.UI.App_Start
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            GlobalConfiguration.Configuration
               .UseSqlServerStorage("DbEntities");

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

        }
    }
}
Flytrap answered 31/8, 2018 at 10:20 Comment(0)
M
11

For Initializing in Asp.net core

public static void InitializeHangFire()
        {
            var sqlStorage = new SqlServerStorage("connectionString");
            var options = new BackgroundJobServerOptions
            {
                ServerName = "Test Server"
            };
            JobStorage.Current = sqlStorage;
        }
Milinda answered 16/4, 2019 at 14:37 Comment(0)
H
7

you can use this road:

1-Installing Hangfire->Hangfire.AspNetCore(v1.7.14) and Hangfire.Core(v1.7.14)

2-Registering Services

class Program
{
    static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args)
    {
      return WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
    }
 }

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add Hangfire services.
        services.AddHangfire(configuration => configuration
            .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
            .UseSimpleAssemblyNameTypeSerializer()
            .UseRecommendedSerializerSettings()
            .UseSqlServerStorage("Server=-; Database=-; user=-; password=-;"));

        // Add the processing server as IHostedService
        services.AddHangfireServer();
     }

3- Adding Dashboard UI

public void Configure(IApplicationBuilder app, IBackgroundJobClient 
                      backgroundJobs, IHostingEnvironment env)
    {
        app.UseHangfireDashboard();
        backgroundJobs.Enqueue(() => Console.WriteLine("Hello world from 
        Hangfire!"));

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

    }
}

4- Running Application The following message should also appear, since we created background job, whose only behavior is to write a message to the console. Hello world from Hangfire!

Historian answered 4/10, 2020 at 6:31 Comment(1)
What a little world it is :) I was reading the answer, saw it's yours! Great answer thank you.Hazeghi
L
5

With the version 1.7.30 if I initialize Hangfire like this:

services.AddHangfire(c => c.UseSqlServerStorage(configuration.GetConnectionString("Default")));
services.AddHangfireServer();

and then try to call, for example, RecurringJob.AddOrUpdate in the Configure method, I will have exception from the question title. I didn't have it locally, because locally I have development environment, and applicationBuilder.UseHangfireDashboard() is called. If this method is called before, RecurringJob.AddOrUpdate will work without any problem.

Another way is to inject the IBackgroundJobClient (or get it from the IServiceProvider, it is not important) before calling RecurringJob.AddOrUpdate. You don't need to do anything with the IBackgroundJobClient instance, just inject it. After that everything works. I hope it will save time for someone.

Lactose answered 29/6, 2022 at 20:19 Comment(6)
This did seem to fix the exception (for me, anyway). This seems like a regression - I didn't have to ask for a throw-away client in earlier versions of ASP.NET (maybe it's a .NET6 bug?). Possibly related: github.com/HangfireIO/Hangfire/issues/2086Sidwel
I was using .NET 6 and this answer was helpful to me. Indeed it is necessary to call services.AddHangfireServer() or app.UseHangfireDashboard() before calling any of the hangfire operations like BackgroundJob.Enqueue or RecurringJob.AddOrUpdate. In my case however, I didn't want to use either approach because I needed for architectural reasons to keep the Hangfire server in a different kubernetes pod (console app), separate from my WebApi. So injecting the IBackgroundJobClient into the WebAPI was the more graceful option and worked perfectly without getting the error posted.Lithometeor
We have a HangFire instance that works fine... when the Dashboard is enabled. For Prod, we don't want the dashboard, so we don't call the builder.UseHangfireDashboard(...) and we have that exception. How do you injected the IBackgroundJobClient... we don't have it.Keslie
@Alex75 just add IBackgroundJobClient client to the constructor parameters, that's all you need to do.Lactose
the solution is unclear. Where should IBackgroundJobClient be injected?Albertoalberts
@Albertoalberts as I said, you need to do that before calling RecurringJob.AddOrUpdate or similar method. It can be done if different ways, depending on your context. As I said, you can use IServiceProvider to call GetService method just before calling RecurringJob.AddOrUpdate one.Lactose
R
2

There is same question in this link. I hope this helps you.

Can you write code which throws exception? I write your Startup class and test controller -below-. It works fine. I did not faced any exception.

[RoutePrefix("")]
public class HomeController : ApiController
{
    [Route(""), HttpGet]
    public void Get()
    {
        Hangfire.BackgroundJob.Enqueue(() => Tasks.DoIt("test"));

        Hangfire.BackgroundJob.Schedule(() => Tasks.InitializeJobs(), TimeSpan.FromSeconds(5));
    }
}

public static class Tasks
{
    public static void DoIt(string s)
    {
        Console.WriteLine(s);
    }

    public static void InitializeJobs()
    {
        Console.WriteLine(DateTime.Now.ToString());
    }
}
Rafi answered 31/8, 2018 at 10:56 Comment(12)
Thanks,Now my app is running,the above exception has gone,Bu now In my mvc controller when i call, BackgroundJob.Schedule( () => InitializeJobs(), TimeSpan.FromMinutes(1)); Then the exception occurs, that meta data is not supported.?Flytrap
May you post your code? What is your jobs and job parameters can I see?Rafi
GlobalConfiguration.Configuration .UseSqlServerStorage("DbEntities"); Actually in startup.cs class , when this code execute, it gives exceprion, Keyword not supported: 'metadata'.Flytrap
Can you check ConnectionString? Probably it contains not valid keywordRafi
But Sir, My when i comment the above code,my app with this same connection string successfully running.I am using repository pattern, in my web.config, and in app.config has same connection string.Flytrap
I do not have any suggestions :) I try to schedule some job and work. If project is open source, may you give me link? I download and try to find problem.Rafi
Thanks Adem Catamak , problem resolved sucessfully, Actually my connection string contains meta data produced by entity framework caused by creating exceprion meta data not supported, so it has been resoled by remove it.Now code works,Thanks for your time.Flytrap
Respected, Adem Catamak, I have another question.Can we use external server link in GlobalConfiguration.Configuration.UseSqlServerStorage("connString"), how we can use database connection string that is hosted on external server?Flytrap
I ask you to confirm: you are currently using a local database server and would you like to connect to a database that is running on an existing server that exists outside? In this case, you do not need to modify your code. It will suffice to use the connection string of the external database. Note: The firewall settings for the external server must be made in order for the application to be accessible to the existing database.Rafi
But sir,Is this supported,can we give database connection that is not hosted on current server.i-e 192.168.9.10Flytrap
Yes you can. You can give db address which is located somewhere outside. In this case, you should check security permission. Db may give connection permission which has spesific IP address. You ensure your app can connect dbRafi
I hope I could helpRafi
G
2

adding this line to startup should make it right

services.AddHangfire(config =>
            {
                config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default"));
            });
            JobStorage.Current = new SqlServerStorage(_appConfiguration.GetConnectionString("Default"));
Gait answered 13/8, 2023 at 16:38 Comment(1)
Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?Duax
B
0

for regular ASP.NET MVC

instead of

app.UseHangfireDashboard();

use

app.UseHangfireAspNet(GetHangfireServers);

This worked for me

Bowls answered 1/8, 2022 at 9:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.