Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make controllers scoped or singleton instead of transient in ASP.NET Core?

How to make controllers scoped or singleton instead of transient in ASP.NET Core?

I now that by default the controllers are registered with the default DI container with the transient lifetime.

In case I would like to register them with a different lifetime, how could I do that?

I want to know that solely for the educational purposes, to better wrap my head around the controller types management by the DI container.

like image 922
Sasuke Uchiha Avatar asked Jul 08 '20 08:07

Sasuke Uchiha


People also ask

What is transient scoped and singleton in .NET Core?

Singleton is a single instance for the lifetime of the application domain. Scoped is a single instance for the duration of the scoped request, which means per HTTP request in ASP.NET. Transient is a single instance per code request.

When use transient vs scoped in NET Core?

Scoped approach => This is a better option when you want to maintain a state within a request. Transient approach => Use this approach for the lightweight service with little or no state.

Should repository be scoped or transient?

If you want an instance that lasts for the duration of a user request (that eg might hold details of the user), then use scoped. If you want a new instance every time the container is asked to provide one (a resource access request that needs disposing quickly for example), then use transient.

Can you inject transient into singleton?

Transient services that are stateless and don't contain any stateful dependencies can be injected into singleton or scoped services. A transient service injected into a singleton has singleton lifetime, it's not disposed until the app shuts down.


1 Answers

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);
like image 115
Steven Avatar answered Oct 14 '22 08:10

Steven