Dotnet core console app running background job System.IO.FileNotFoundException


#1

Hi I am investigating Hangfire and set up a web.api which has the dashboard and can receive requests and add them into the queue. This works and I can see the job added to the queue.

BackgroundJob.Enqueue<IMessage>(m => m.SayHello());

My IMessage looks like this

public interface IMessage
{
    [Queue("bas-hello")]
    void SayHello();
}

public class Message : IMessage
{
    public void SayHello()
    {
        Console.WriteLine("lets say hello");
    }
}

It will run on the web.api server just fine but I want it to run via a console app and not the web.api server. I can see the console app connected to the hangfire server via the dashboard.

However I am getting this error in the dashboard

System.IO.FileNotFoundException: Could not load file or assembly 'hub, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

My console is set up to use DI via the following code

class Program
{
    static void Main(string[] args)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

        var configuration = builder.Build();
        GlobalConfiguration.Configuration.UsePostgreSqlStorage(configuration.GetConnectionString("HangfireConnection"));

        // create service collection
        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);
    
        // create service provider
        var serviceProvider = serviceCollection.BuildServiceProvider();
    
        // entry to run app
        serviceProvider.GetService<App>().Run();
    }

    private static void ConfigureServices(IServiceCollection serviceCollection)
    {
        // add services
        serviceCollection.AddTransient<IMessage, Message>();
    
        // add app
        serviceCollection.AddTransient<App>();
    }
}

My app code is like this. I have injected the IMessage into the App.cs and can see it working.

public class App
{
    public App()
    {}
  
    public void Run()
    {
        var options = new BackgroundJobServerOptions
        {
            Queues = new[] { "bas-hello", "default" }
        };
        
        using (var server = new BackgroundJobServer(options))
        {
            Console.WriteLine("Hangfire Server started. Press any key to exit...");
            Console.ReadKey();
        }
    }
}

And my Message.cs
public interface IMessage
{
void SayHello();
}

public class Message : IMessage
{
    public void SayHello()
    {
        Console.WriteLine("lets say hello");
    }
}

Any help on this would be great, So far the journey has been quite simple to get to this point.

Thanks
Matt


#2

Just a thought is this because IMessage is defined in the web.api server and then defined again in the console so it cant find a match?

Wondering if I need to create a library project which the web.api and the console both consume to create and then to run the code


#3

Yes I faced this issue and I have used separate class library and reference it in the console application to run the job. Additionally, I believe you might also want to add Activator to get the required service.

https://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html

GlobalConfiguration.Configuration.UseActivator(new HangfireActivator(serviceProvider));

public class HangfireActivator : JobActivator
{
private readonly IServiceProvider _serviceProvider;

        public HangfireActivator(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public override object ActivateJob(Type type)
        {
            return _serviceProvider.GetService(type);
        }

}


#4

Thanks @satum I have been wondering how I was supposed to use the Activators. Simply added your class and the configuration and it is now running the job in the dotnet core console worker.

Many thanks