Julian Jelfs’ Blog

Nasty problem with PerWebRequest lifestyle objects

Posted in Castle by julianjelfs on June 16, 2009

For a while now I have been trying to ignore a nasty intermittent problem where my application would temporarily go wrong because it appeared that I had two instances of a PerWebRequest lifestyle component created inside the same web request. Of course this should not be possible – that’s the whole point of the PerWebRequest lifestyle.

In my investigations into this I had concluded that this was something to do with concurrent web requests. This was quite alarming because it looked like concurrent web requests were interfering with each other which would be pretty disastrous.  I pursued various theories about thread switching and was able to discount this because I could recreate it and clearly demonstrate that the component was being created twice in the same request on the same thread.

To cut a long story short, I eventually realised that I was bootstrapping my application (i.e. creating and configuring my Windsor container) from inside the Global class’s constructor based on the assumption that this runs once and only once on application start-up. It turns out that this is not true and in fact asp.net uses one Global class instance to serve a single request which will then be recycled when the request ends. So it is possible for asp.net to create multiple instances of the Global class to server simultaneous requests.

So it is possible when two simultaneous requests are fired in the following happens:

  • request A arrives and asp.net creates an instance of Global class which creates a (singleton) instance of the container and creates a single instance of my PerWebRequest component.
  • request B arrives while request A is still running and asp.net created another instance of Global class which creates another instance of the container (overwriting the first and trashing the PerWebRequest component).
  • Code in request A attempts to resolve the component for the second time and gets a new copy of it … strange very hard to debug behaviour ensues.

The moral of the story is DO NOT confuse the application start event with the Global constructor. Application_Start runs exactly once, Global constructor runs once for each concurrent request – maybe it’s more complicated than that , don’t know? All I had to do was move my bootstrapping code into the ApplicationStart handler and all was well.