I now that by default the controllers are registered with the default DI container with the transient lifetime.
By default, controllers are not registered at all. It is the default IControllerActivator
that is creating that type without an explicit registration.
If you want to change this, you should call:
services.AddMvc().AddControllersAsServices();
This will ensure that controllers are registered and the original IControllerActivator
is replaced with one (ServiceBasedControllerActivator
) that resolves controllers from the DI container.
AddControllersAsServices
, unfortunately, always registers the controllers using the Transient lifestyle and there's no way to override that behavior. So you have to re-implement AddControllersAsServices
:
public static IMvcBuilder AddControllersAsServices(
this IMvcBuilder builder, ServiceLifetime lifetime)
{
var feature = new ControllerFeature();
builder.PartManager.PopulateFeature(feature);
foreach (var controller in feature.Controllers.Select(c => c.AsType()))
{
builder.Services.Add(
ServiceDescriptor.Describe(controller, controller, lifetime));
}
builder.Services.Replace(ServiceDescriptor
.Transient<IControllerActivator, ServiceBasedControllerActivator>());
return builder;
}
This new extension method can be used as follows:
services.AddMvc().AddControllersAsServices(ServiceLifetime.Singleton);
WARNING: Do not register your controllers as Singleton
in case they derive from Controller
or ControllerBase
, as these classes contain state (as @MarcoPelegrini correctly notes in the comments) and will malfunction when reused by multiple requests.