ASP.NET Core 2.0 inject Controller with Autofac

16,902

Solution 1

Use InstancePerLifetimeScope in ASP.NET Core. The differences between ASP.NET and ASP.NET Core like this are documented.

Solution 2

By default, ASP.NET Core will resolve the controller parameters from the container but doesn’t actually resolve the controller from the container. This usually isn’t an issue but it does mean:

The lifecycle of the controller is handled by the framework, not the request lifetime.

The lifecycle of controller constructor parameters is handled by the request lifetime. Special wiring that you may have done during registration of the controller (like setting up property injection) won’t work.

You can change this by specifying AddControllersAsServices() when you register MVC with the service collection. Doing that will automatically register controller types into the IServiceCollection when you call builder.Populate(services).

public class Startup
{
  public IContainer ApplicationContainer {get; private set;}
  public IServiceProvider ConfigureServices(IServiceCollection services)
  {
    // Add controllers as services so they'll be resolved.
    services.AddMvc().AddControllersAsServices();

    var builder = new ContainerBuilder();

    // When you do service population, it will include your controller
    // types automatically.
    builder.Populate(services);

    // If you want to set up a controller for, say, property injection
    // you can override the controller registration after populating services.
    builder.RegisterType<MyController>().PropertiesAutowired();

    this.ApplicationContainer = builder.Build();
    return new AutofacServiceProvider(this.ApplicationContainer);
  }
}
Share:
16,902
Nieksa
Author by

Nieksa

Updated on June 30, 2022

Comments

  • Nieksa
    Nieksa almost 2 years

    I'm trying to inject my controller with Autofac. Unfortunately I am unable to configure Autofac in away so that the 'DefaultControllerActivator` wont construct my controllers?

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().AddControllersAsServices();
            var containerBuilder = new ContainerBuilder();
            containerBuilder.RegisterModule<ServiceModule>();
            containerBuilder.Populate(services);
            containerBuilder.RegisterType<LoginController>().PropertiesAutowired();
    
            ApplicationContainer = containerBuilder.Build();
            return new AutofacServiceProvider(this.ApplicationContainer);
        }
    
        public class ServiceModule : Module
        {
            protected override void Load(ContainerBuilder builder)
            {
                builder.RegisterModule(new DataProviderModule());
                builder.RegisterType(typeof(LoginService)).As(typeof(ILoginService)).InstancePerRequest();
            }
        }
    
        [Route("api/[controller]")]
        public class LoginController : Controller
        {
            private readonly ILoginService _loginService;
    
            public LoginController(ILoginService loginService)
            {
                _loginService = loginService;
            }
        }
    

    I followed the documentation of Autofac as shown above. Unfortunately the LoginController will not be constructed because it requires an injection.

    edit: If there is a way of using "Modules" without Autofac, I'd be very interesting for any suggestions :)

    Thanks you in advance!

  • Dina
    Dina over 5 years
    If you are reading this answer please consider you need to add this property to your startup class: [... public IContainer ApplicationContainer { get; private set; } ...]
  • Pepito Fernandez
    Pepito Fernandez over 5 years
    @Sep Thank you! Fixed it.
  • Manfred
    Manfred over 5 years
    @PepitoFernandez From which class did you get the method Populate()? I've installed Autofac version 4.6.1 but I cannot see "Populate()" as a method on class ContainerBuilder.
  • Pepito Fernandez
    Pepito Fernandez over 5 years
    @Manfred I don't quite remember at this point. It could be an extension method (which most likely requires you to add that namespace).
  • Manfred
    Manfred over 5 years
    @PepitoFernandez Thank you for your reply. I found it: I had to install yet another NuGet package named Autofac.Extensions.DependencyInjection and add the namespace Autofac.Extensions.DependencyInjection to the file Startup.cs and then the compiler was happy.