My project structure is same as :
https://github.com/MarlabsInc/webapi-angularjs-spa
I have followed the instructions in :
http://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html
So I have created a container job activator.
In my Bootstrapper.cs
containerBuilder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().AsImplementedInterfaces().InstancePerApiRequest();
containerBuilder.RegisterType<UnitOfWork>().As<IUnitOfWork>().AsImplementedInterfaces().InstancePerApiRequest();
containerBuilder.RegisterApiControllers(System.Reflection.Assembly.GetExecutingAssembly());
IContainer container = containerBuilder.Build();
Hangfire.GlobalConfiguration.Configuration
.UseAutofacActivator(container);
JobActivator.Current = new AutofacJobActivator(container);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
My startup class has a method :
GlobalConfiguration.Configuration
.UseSqlServerStorage("entitiesDB",
new SqlServerStorageOptions
{
PrepareSchemaIfNecessary = false,
InvisibilityTimeout = TimeSpan.FromMinutes(30)
});
app.UseHangfireDashboard();
app.UseHangfireServer();
In controller : I am trying to update the status of 2000 invoices as "Approved" So the method is straightforward as follows :
foreach(int id in invoiceIds)
{
BackgroundJob.Enqueue<IInvoiceService>(a => a.UpdateInvoice(id));
}
Now when I query in the SQL :
select * from HangFire.[State]
I get the following exception in Data column:
{"FailedAt":"2015-07-07T10:00:40.9454943Z","ExceptionType":"Autofac.Core.DependencyResolutionException","ExceptionMessage":"No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.","ExceptionDetails":"Autofac.Core.DependencyResolutionException: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.\r\n at Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope)\r\n at Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable
1 parameters)\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable
1 parameters)\r\n at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters)\r\n at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable
1 parameters)\r\n at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable1 parameters)\r\n at Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable
1 parameters)\r\n at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance)\r\n at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable
1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType)\r\n at Hangfire.AutofacJobActivator.ActivateJob(Type jobType)\r\n at Hangfire.Common.Job.Activate(JobActivator activator)"}
Can someone please help me understand what I am doing wrong ?
You are using
InstancePerApiRequest
so your IoC container knows to create a new instance for each API request.But, your background job is not executing inside an API request, so your IoC container does not know how to resolve your dependencies.
From the hangfire docs:
According to this related SO question, Autofac does not support registering for multiple scopes out of the box so you will need to either:
UPDATE:
The Hangfire Autofac integration package introduces a
InstancePerBackgroundJob()
extension method, and suggests that Autofac does support registering for multiple scopes like this:However, it's only available in the 1.2.0-beta1 release of Hangfire.Autofac which requires Hangfire 1.5.0-beta1.