Blog about profiling and debugging of .NET and Windows applications

Global.asax in ASP.NET

The Global.asax, also known as the ASP.NET application file, is used to handle application-level and session-level events. Although its structure is pretty simple and it’s easy to have one in the project, many developers don’t know exactly how it works. This post aims at revealing some of the mystery behind this file as well as providing you with some good usage examples.
Let’s first have a look at a sample Global.asax file:

Global.asax is compiled to its own assembly – if you publish the web project from Visual Studio you can find App_global.asax.dll in the bin directory, otherwise it will go to c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\<appname>. After decompiling the produced assembly we will receive something like (methods are collapsed for clarity):

From the above code we can see that a new class (global_asax) was created in ASP namespace which inherits from the HttpApplication. HttpApplication is an interesting class itself. It implements the ASP.NET request pipeline, invoking HttpModules, page event handlers etc. A quite common mistake is to think of the HttpApplication (global_asax) as a singleton shared by all the requests. The truth is that each request has its own instance of the HttpApplication class. To be more specific ASP.NET runtime keeps two pools of HttpApplication objects. First is a special pool with HttpApplication objects used for application level events (such as Application_Start, Application_End and Application_Error(Application_Error is served by normal HttpApplication instance – thanks Denis for spotting the mistake here!)), second pool contains instances used in requests to serve all other types of events. Which class is then responsible for managing those pools? Here the HttpApplicationFactory comes into play. There is only one instance of this class per HttpRuntime and beside managing app pools it is also responsible for compiling Global.asax and ensuring that Application_Start/End events are called only once.

To prove what I described let’s use the above Global.asax file in a very simple web application. We will use the System.Diagnostics.Trace so some changes to the web.config file are required:

The different guids for Application_Start and Application_…Request events prove that there were two global_asax instances involved in processing the request. The first one is the special one and will be stored in the special pool (probably reused for Application_End/Application_Error event), the second one is a normal instance that will be reused in any further requests. Now look at the TestMessage property value – it was set only for the HttpApplication instance that was created as the first one. That assures us that the Application_Start is called only once in the web application lifetime (and not for every newly created HttpApplication instance).

So what’s the correct way of using global.asax? Firstly, remember:

It’s not a singleton.

Application_Start/End events are called only once.

There is one instance of global_asax per request and additionally there are instances for special events

Secondly, try to apply those guidelines to your Global.asax files:

All private fields should be initialized in the constructor.

Static fields may be initialized either in the Application_Start or static constructor.

Don’t use lock blocks – your request possesses this instance of the glboal_asax.

You can stop reading here if what I wrote is satisfactory for you. If you still have some doubts and would like to dig deeper keep on reading:) – I will show you how to look at the ASP.NET internals with the SOS debugger extension. Basically you start with attaching to the w3wp.exe process that your application is running in. Then load sos (replace clr with mscorwks if it’s .NET 2.0):

10 thoughts on “Global.asax in ASP.NET”

>ASP.NET runtime keeps two pools of HttpApplication objects. First is a special pool with HttpApplication objects used for application level events (such as Application_Start, Application_End and Application_Error)

Great artical about the global.asax. I was always wondering why I’m not able to persist things in static properties between sessions or requests. And now you’ve explained to me in the most simplest way. Thanks. Ondrej

“To be more specific ASP.NET runtime keeps two pools of HttpApplication objects. First is a special pool with HttpApplication objects used for application level events (such as Application_Start, Application_End, second pool contains instances used in requests to serve all other types of events.”

You menitoned HttpApplication objectS. Should it be just one HttpApplication object there, since only for first instance Application_Start is called?

Going further, what happens with that object, can it be also used for processing requests? Or, if my application creates lets say four HttpApplication instances, by default, only three of them will be used for processing requsts? Thanks

Those are very good questions. Unfortunately I don’t have a definitive answer for the first one. Logically there should be one instance of such an object – the only situation that comes to my mind when there might exist more instances is when application is being reloaded, but I haven’t tested it yet.

The special application object is not used in a normal request processing – they are stored in different pools. And yes, if your application creates four instances of HttpApplication, three of them will be used for processing requests.