ASP.NET Core 2.0 inject Controller with Autofac
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);
}
}
Nieksa
Updated on June 30, 2022Comments
-
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 over 5 yearsIf 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 over 5 years@Sep Thank you! Fixed it.
-
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 classContainerBuilder
. -
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 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 namespaceAutofac.Extensions.DependencyInjection
to the fileStartup.cs
and then the compiler was happy.