Simple Injector: cannot register Web API controllers with AsyncScopedLifestyle

1.8k views Asked by At

I am trying to integrate Simple Injector (4.0.12) in my .NET (4.6.1) Web API Project, but cannot find a way to register all Web API Controllers with the correct AsyncScopedLifestyle.

When I try injecting an async scoped instance of DatabaseProvider into the controller like so...

public class DatabaseController : ApiController
{
    private readonly IDatabaseProvider databaseProvider;

    public DatabaseController(IDatabaseProvider databaseProvider)
    {
        this.databaseProvider = databaseProvider;
    }

    [HttpGet]
    public bool CheckDatabaseConnection()
    {
        return databaseProvider.IsConnected();
    }
}

... I receive a SimpleInjector.ActivationException with the following error:

The DatabaseProvider is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope.

But why?


This is how my code for registering the the controllers looks like:

public static Container Initialize()
{
     var container = new Container();
     container.Options.LifestyleSelectionBehavior = new CustomLifestyleSelectionBehavior();
     container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
     container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

     DependencyProvider.SetResolver(new SimpleInjectorDependencyProvider(container));
     GlobalConfiguration.Configuration.DependencyResolver = 
         new SimpleInjectorWebApiDependencyResolver(container);
     RegisterTypes(container);

     //container.Verify();

     return container; 
 }

public class CustomLifestyleSelectionBehavior : ILifestyleSelectionBehavior
{
    public Lifestyle SelectLifestyle(Type implementationType)
    {
        if (implementationType.GetCustomAttribute<ApplicationScoped>(true) != null)
        {
            return Lifestyle.Singleton;
        }

        return new AsyncScopedLifestyle();
    }
}

As you can see the DefaultScopedLifestyle is set to AsyncScopedLifestyle and also my CustomLifestyleSelectionBehavior returns the same lifestyle for controllers.

However all controllers seem to be registered as Transient, because this is the output of container.Verify() for all controllers:

Exception Type: DiagnosticVerificationException
Exception Message: The configuration is invalid.
The following diagnostic warnings were reported:

-[Disposable Transient Component] DatabaseController is registered as transient, but implements IDisposable.

-[Disposable Transient Component] LoginDataController is registered as transient, but implements IDisposable.
...

Does anybody know how to set the lifestyle for WebAPIController-registrations to AsyncScoped so that I can inject async scoped business logic?

1

There are 1 answers

0
Saibamen On

In .NET Core add:

// Sets up the basic configuration that for integrating Simple Injector with
// ASP.NET Core by setting the DefaultScopedLifestyle, and setting up auto
// cross wiring.
services.AddSimpleInjector(_container, options =>
{
    // AddAspNetCore() wraps web requests in a Simple Injector scope and
    // allows request-scoped framework services to be resolved.
    options.AddAspNetCore()
        .AddControllerActivation();
});

via https://simpleinjector.readthedocs.io/en/latest/aspnetintegration.html