Simple Injector and Application_EndRequest

Per Request lifetime is one of the lifetimes that Simple Injector supports (as you would expect). But there is a bit of a problem when it comes to resolving objects in the application’s Application_EndRequest of the Global.asax.cs. Fortunately, the author of Simple Injector has built in a callback which effectively enables us to do the same thing. Other containers solve the problem differently (e.g. StructureMap offers Nested Containers). I also want to point out that Steven van Deursen (aka .NET junkie) is one of the most helpful developers on the planet. He freely gives away design/architectural advice and is very active answering questions about Simple Injector. The kind of guy I would love to work with.

Anyhow, lets say we have the following code which we want to run in the Application_EndRequest event handler (e.g. IRunAfterEachRequest may be implemented by a transaction-per-request object which either commits or rolls back a transaction at the conclusion of the request):

public void Application_EndRequest()
{
    foreach (var task in DependencyResolver.Current.GetServices(typeof(IRunAfterEachRequest)).Cast<IRunAfterEachRequest>())
    {
        task.Execute();
    }
}

You are going to get an exception:

[ObjectDisposedException: Cannot access a disposed object.
Object name: ‘SimpleInjector.Scope’.]

The reason being that the Container disposes the Scope by hooking into the HttpContext.EndRequest event. And that event gets handled before the Application_EndRequest.

The solution to the problem is to put the code, which you would otherwise put in the Application_EndRequest handler, in the WhenScopeEnds callback which I mentioned at the top of the post. And this would be done, ironically, in the Application_BeginRequest handler:

public void Application_BeginRequest()
{
    var container = SimpleInjectorInitializer.Container;

    container.Options.DefaultScopedLifestyle.WhenScopeEnds(container, () =>
    {
        foreach (var task in container.GetAllInstances<IRunAfterEachRequest>())
        {
            task.Execute();
        }
    });
            
    foreach (var task in container.GetAllInstances<IRunOnEachRequest>())
    {
        task.Execute();
    }
}

Note that I have exposed the Container as a static property of the SimpleInjectorInitializer class.

This is all explained in more detail here.

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>