I am trying to use Hangfire to run a background job in my MVC project.
I call the Enqueue
method in the constructor of my controller:
public SHQSController(IUnitOfWork uow) : base(uow)
{
BackgroundJob.Enqueue(() => _Uow.CostRepository.Merge());
}
The _Uow.CostRepository
property returns an Interface:
public ICostRepository CostRepository
{
get
{
return new CostRepository(_Context, _CurrentOrganisationID);
}
}
But the job fails in hangfire giving the following reason:
Error activating int No matching bindings are av…
I have found that if I change the code so that the job is called on the implementation of ICostRepository
instead of via the interface, it works:
i.e. in my controller:
BackgroundJob.Enqueue(() => _Uow.Test());
and in my unit of work:
public void Test()
{
new CostRepository(_Context, _CurrentOrganisationID).Merge();
}
What is going on here? Is there a way to queue a job that allows me to put my implementaion in my repository rather than my unit of work?
EDIT: I found the full error message in the HangFire.State table The full error is:
Error activating int No matching bindings are available, and the type is not self-bindable. Activation path: 2) Injection of dependency int into parameter currentOrganisationID of constructor of type CostRepository 1) Request for CostRepository Suggestions: 1) Ensure that you have defined a binding for int. 2) If the binding was defined in a module, ensure that the module has been loaded into the kernel. 3) Ensure you have not accidentally created more than one kernel. 4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name. 5) If you are using automatic module loading, ensure the search path and filters are correct.
So the problem is the CurrentOrganisationID
that the CostRepository
is dependent on. The CurrentOrganisationID
is currently retrieved from the HttpContext
and set on the unit of work, which passes it to the repository's constructor as shown in my code above.
I think the problem with this line:
is that Hangfire interprets this as a requirement to instantiate an implementation of
ICostRepository
and run itsMerge
method rather than instantiate an implemetation ofIUow
and runCostRepository.Merge()
on that.I got around that by creating a public method on the controller:
and passing that to the
Enqueue
method:The job queued by Hangfire is now
SHQSController.Merge
and the dependencies are now correctly resolved.As an aside, you might notice that I now pass the
organisationid
in to the method as a parameter where previously it was available within the repository. This is retrieved from theHttpContext
and since this isn't available when the controller is instantiated from a background job, I had to create another private method called from the constructor so that theorganisationid
was wired in to the background job:So, instead of:
I have: