HttpRequest LifetimeManager and Unity with IDisposable

Oct 27, 2008 at 2:51 PM
I need one instance of an object to be created per HttpRequest in my ASP.NET MVC application. I think I can accomplish this with a custom LifetimeManager that stores created instances inside of HttpContext.Current.Items. If my class below works, how does one deal with objects created by Unity that need to have Dispose called? In my case, I have a service layer that takes a database context. At the end of my HttpRequest, Dispose should really be called on that object, yet I'm allowing Unity to handle the creation of it, and am storing it in HttpContext.Current.Items. Any thoughts on this issue?

Here's my HttpRequestLifetimeManager:

public class HttpRequestLifetimeManager : LifetimeManager
    {
        private readonly Guid key;

        public HttpRequestLifetimeManager()
        {
            key = Guid.NewGuid();
        }

        public override object GetValue()
        {
            return HttpContext.Current.Items[key];
        }

        public override void SetValue(object newValue)
        {
            HttpContext.Current.Items[key] = newValue;
        }

        public override void RemoveValue()
        {
            HttpContext.Current.Items.Remove(key);
        }
    }


In Global.asax under Application_Start()

// Any request for a SystemEntityDatabase data context will provide one instance per HttpRequest
container.RegisterType<SystemEntityDatabase, SystemEntityDatabase>(new HttpRequestLifetimeManager());

Oct 27, 2008 at 11:02 PM
If you want to combine dispose semantics with per-request, an easier approach would be to use a per-request child container instead. Configure your main container in Application_Start. In BeginRequest, call container.CreateChildContainer();. Configure your per-request objects in the child container as ContainerControlledLifetime (you don't need the custom lifetime manager). Then, in EndRequest call Dispose on the child container. Then it'll take all the per-request stuff with it.

Oct 29, 2008 at 1:19 AM
This is certainly an interesting idea. However, I'm curious if Dispose is called on items in HttpContext.Current.Items at the termination of the request. If so, my way seems equally as good. I can't find any information on this however. Does anyone have any info on this?
Oct 29, 2008 at 6:38 AM
Dispose is definately not called on objects in HttpContext.Items. You could spin through them in your EndRequest handler and do it yourself.

You can double check in the framework source code.
Mar 31, 2011 at 1:11 PM
Edited Apr 1, 2011 at 9:04 AM

If you have upgraded to ASP.NET MVC 3, you might like to try http://unitymvc3.codeplex.com which takes care of all this for you. It is also available as a NuGet package (Unity.Mvc3)

Nov 12, 2012 at 2:24 AM

Hi all,

I wouldn't normally resurrect an old thread but I would like to know if anyone has some thoughts on the above two approaches.  In particular in an concerned with the consequences for build plans with creating a new child container per request.  

What is the overhead of having to create new build plans for each "per request" item vs retrieving from the HttpContext.Items hashtable ?

Will new build plans have to be created for items resolved from the parent container via the child container ?

As I'm not a fan of the service locator (anti) pattern, where do you store the child container ?  The controller factory has to know about this somehow but it is application scope.

How reliable is accessing the HttpContext.Items entries in EndRequest to disposable any applicable objects ?

Cheers..

Robert

Nov 12, 2012 at 5:12 AM

When creating a child container it looks like most of the configuration is done by creating a new UnityContainer and setting the properties of the child container to those of the parent container.  In other words, the strategies and policies are reused so they do not have to be recreated.  This doesn't look very expensive.  A simple test I did resulted in creating 10,000 child containers in 107ms.  Perhaps someone else has some other tests they have done?

In terms of storing the child container, HttpContext is a natural fit for per request information.  This shouldn't be using the container as a service locator since a child container is just being used in place of the parent container at the composition root.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Nov 12, 2012 at 8:13 PM

Thanks for the reply.  It's not the container creation that it my concern, it is the time it takes to create the build plan for the first time during the first resolve.

I'll try and do some benchmarking

Nov 13, 2012 at 8:56 PM

The build policies are cached in the parent container, so there was virtually no performance overhead in resolving from a child container ( I have dependencies injected into a child container registration from a parent container ).

So, just need to work out the best place to store the child container