Search code examples
c#.netdependency-injectionioc-containersimple-injector

SimpleInjector Container.Verify() with HTTP context-scoped dependency


I have the following basic SI registration in an ASP.NET WebApi project.

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSimpleInjector(container, options =>
    {
        options
            .AddAspNetCore()
            .AddControllerActivation();
    });

    services.AddHttpContextAccessor();
    services.AddScoped<Work>(services =>
    {
        var traceId = services.GetRequiredService<IHttpContextAccessor>().HttpContext.TraceIdentifier;
        // ...
    });
}

public void Configure(IApplicationBuilder app)
{
    app.ApplicationServices.UseSimpleInjector(container);
    // ...
    container.Verify();
}

private readonly Container container = new Container();

The Problem

Container.Verify() attempts to resolve a Work instance, whose factory delegate successfully resolves an IHttpContextAccessor but its HttpContext is null because there is no current HTTP call on startup. Therefore the code dies with a null-reference exception.

I don't think there is anything we can do except guard against null but that goes against my taste in this context:

  • why would I do that when I know for a fact that this factory delegate should only be called during an HTTP call?
  • what exactly do I do if my HTTP-scoped dependency is null? Sure, return a fake BUT how do I detect that it's null for good reason and not because my web infrastructure is dying somehow?

I can't see a good solution. What do you do in this case?


Solution

  • I've wrote extensively about this problem in the past. Your HttpContext and its TraceIdentifier are runtime data and runtime data should be kept out of the construction of your object graphs. See for instance this article.

    What the correct solution in your particular case is, is hard to say, because it depends on the details of what you are trying to construct, but the article gives some pointers.