Hangfire with Ninject using InRequestScope

854 views Asked by At

I have installed the Hangfire.Ninject package to an ASP MVC 5 application so that I can run some background jobs.

I've read through the documentation but I'm baffled as to how to implement it.

My existing configuration uses InRequestScope for my IUnitOfwork class to ensure only a single instance is instantiated per HTTP request as follows:

private static void RegisterServices(IKernel kernel)
{
        kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
 } 

To use ninject with hangfire having followed the documentation I have updated the configuration as follows in my ninjectwebcommon.cs class:

 private static IKernel CreateKernel()
 {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            GlobalConfiguration.Configuration.UseNinjectActivator(kernel);

            RegisterServices(kernel);

        return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    private static void RegisterServices(IKernel kernel)
    {
         kernel.Bind<IUnitOfWork>()
            .ToSelf()
            .InNamedOrBackgroundJobScope(context => context.Kernel.Components.GetAll<INinjectHttpApplicationPlugin>()
            .Select(c => c.GetRequestScope(context))
            .FirstOrDefault(s => s != null));

    }

But now I get the following error:

Error activating IUnitOfWork using self-binding of IUnitOfWork
No constructor was available to create an instance of the implementation type.

I have a class I would like to use to process my background job using hangfire is as follows:

 public class EmailJob
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly IMailer _mailer;

    public EmailJob(IUnitOfWork unitOfWork, IMailer mailer)
    {
        _unitOfWork = unitOfWork;
        _notificationMailer = notificationMailer;
    }

     public void Execute()
    {
        // DO Stuff
    }

}

Any one know what I'm doing wrong? The documentation also states:

Services registered with InRequestScope() directive will be unavailable during job activation, you should re-register these services without this hint.

What does this mean? I still want to ensure that only one IUnitOfwork class which implement dbContext is used per http request. How is this now going to affect the rest of the application if I remove the InRequestScope?

1

There are 1 answers

0
shbht_twr On

I think the issue is that you are binding IUnitOfWork to itself. Niject would need a concrete class to activate something like UnitOfWork.

  kernel.Bind<IUnitOfWork>()
        .To<UnitOfWork()
        .InNamedOrBackgroundJobScope(context => context.Kernel.Components.GetAll<INinjectHttpApplicationPlugin>()
        .Select(c => c.GetRequestScope(context))
        .FirstOrDefault(s => s != null));