Search code examples
c#asp.netdependency-injectionautofachangfire-autofac

Autofac.Core.Registration.ComponentNotRegisteredException, FAILED: An exception occurred during processing of a background job


Exception: The requested service 'Mach.CharterPad.Business.TripManager' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'Mach.CharterPad.Business.TripManager' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Hangfire.AutofacJobActivator.AutofacScope.Resolve(Type type)
   at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_0.<PerformJobWithFilters>b__0()
   at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
   at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
   at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

Startup.cs

private void ConfigureAutofac(HttpConfiguration config, IAppBuilder app)
{
  var builder = new ContainerBuilder();
  var businessasm = BuildManager.GetReferencedAssemblies()
                                .Cast<Assembly>()
                                .Where(n => n.FullName.Contains("Business"))
                                .FirstOrDefault();

  builder.RegisterAssemblyTypes(businessasm)
  .Where(t => t.Name.EndsWith("Manager"))
  .AsImplementedInterfaces()
  .InstancePerRequest();

//Set the dependency resolver to be Autofac.
   var container = builder.Build();
   config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
   Hangfire.GlobalConfiguration.Configuration.UseAutofacActivator(container, 
   false);
   config.MessageHandlers.Insert(0, new ApiDelegatingHandler());
   app.UseAutofacMiddleware(container);
   app.UseAutofacWebApi(config)
}

MyController.cs

[Route("{Id}")]
public IHttpActionResult GetById(long Id)
   {
     var result = TripManager.GetById(Id);  // WORKS PERFECT

     var jobId = BackgroundJob.Enqueue(() => TripManager.GetById(Id)); // Always go to Retries in Hangfire

     return Ok(result != null ? new ApiResponse(true, "Trip has been found", result) : new ApiResponse(false, "No record found", result));
   }

Solution

  • Unfortunately, there's not much here to go on - there's no actual question, no explanation of what steps have been taken to solve the problem, which questions have already been looked at, etc.

    I recommend checking out this post on what makes a good SO question. This can help you - by working through some of the issues and helping get more eyes on the question; and it can help others - by narrowing down what things need to be looked at or understanding exactly what you're shooting for. Everyone wins with a well-written question, even people who may see a similar issue and are looking for help.

    Given there's some guesswork to figure out what you're asking, I assume the question is something along the lines of:

    I have [some sort of an ASP.NET app, likely Web API] running an OWIN pipeline. I also have background jobs running via Hangfire. I'm trying to share a container across the ASP.NET app and the Hangfire jobs, but I see an exception [at some point, but it's unclear when]. Why might this exception be occurring?

    Well, first, the exception message tells you a lot:

    The requested service 'Mach.CharterPad.Business.TripManager' has not been registered.

    Looking at how your registrations are...

    builder.RegisterAssemblyTypes(businessasm)
      .Where(t => t.Name.EndsWith("Manager"))
      .AsImplementedInterfaces()
      .InstancePerRequest();
    

    I see two potential issues right off the bat:

    • You've used AsImplementedInterfaces, which means if you have public class TripManager : ITripManager then it's going to only be registered as ITripManager. You can't resolve a concrete type if you've only registered the interfaces. You'd have to register things AsSelf as well.
    • You've specified InstancePerRequest and background tasks don't have requests. That's not going to work. You'd have to register as InstancePerDependency or InstancePerLifetimeScope if you wanted a fresh one in each background task; or SingleInstance if you want to share a singleton between the web app and the background task.

    In the MyController.cs I can't see how the TripManager is getting resolved. I don't know if that's a static reference to TripManager.GetById(id) or if that's a property. There's no constructor so you can't tell if it's taking an ITripManager or a TripManager or what.

    However, the registration issues there should likely give you enough info to start unwinding the problem. If not, I might recommend opening up a new question with more details so folks can better assist you.