Search code examples
c#.netasp.net-web-apiioc-containersimple-injector

Simple Injector Creates Controller Multiple Times and Creates Unnecessary Controller


I noticed a strange behavior when using Simple Injector with ASP.NET Web APIs, so I reduced it to its basics. Steps to reproduce:

  • create ASP.NET Core's default Web API project. I used .NET Core 3.1, which is out of support now but I don't think that has anything to do with the issue. You will have a single controller: WeatherForecastController
  • create another API controller descending from ControllerBase with a default ctor. I have the default Index() method in it but changed the return value to string.
  • put a breakpoint in the ctor of both controllers
  • run the app, and call the weather/get endpoint: the breakpoint shows that the weather controller is created once, as expected. The other controller's code is untouched, also as expected.
  • add these SimpleInjector nuget packages to the project:
    • SimpleInjector: I add it directly because this is what the documentation suggests
    • SimpleInjector.Integration.AspNetCore.Mvc.Core
  • initialize SI in Startup.cs as follows
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddSimpleInjector(container, options =>
    {
        options
            .AddAspNetCore()
            .AddControllerActivation();
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.ApplicationServices.UseSimpleInjector(container);

    // the rest of the default code
}

// instantiated in ctor in my code but I do it here for brevity
private readonly Container container = new Container();
  • run the app, and call the weather/get endpoint: the breakpoints show that the second controller is created once, and the weather controller is created twice. Then the weather/get endpoint is called.

The issue is the above unexpected controller creation. The same thing happens in my actual project as in this reproduction test project. The unnecessary controller creation concerns me. Why is that, and how can it be avoided? This surely cannot be normal but I cannot imagine what I could have mistaken in this simple configuration.

EDIT: this strange behavior occurs only for the first weather/get call


Solution

  • Simple Injector contains an auto verification feature which will, when the first component is resolved, trigger verification and construct all types known to Simple Injector as a verification measure. That means that at the first call, its expected for the controller to be created once. Every following request, the controller will be created just once.

    When the other controller is created just once, it could mean that it isn't created by Simple Injector. You can inspect this by placing a break point in the constructor and inspecting the stack trace. Why this is the case is unclear to me from the code you posted.

    More information about verification and auto-verification can be found here.