Session_Start or Session_OnStart?

Posted on December 18, 2005

10 comments

Ever since I started to develop with ASP.NET, I’ve been wondering why global.asa from the ASP days quietly moved over to ASP.NET as global.asax. When you look at it, it just feels so outdated, so VBScript-ish, so loosely–typed. And what is the right way to name event handlers?

Even MSDN documentation is contradictory on this. For example, which is a correct handler for the Session.Start event? Session_Start or Session_OnStart? Documentation lists both in different places, and when you look it up newsgroups, you’ll read some pretty opinionated arguments about each.

For example, MSDN states:

You can use the Global.asax file to synchronize any event that is exposed by the HttpApplication base class. To do this, you must use the following naming pattern to author methods:

Application_EventName(AppropriateEventArgumentSignature)

According to Framework Design Guidelines, section 5.4.1, Custom event handler design, an “appropriate event argument signature” is one with a return type of void; object as the type of the first parameter of the event handler, and called sender; System.EventArgs or its subclass as the type of the second parameter of the event handler, called e.

Nevertheless, you see the following code snippet time and time again:

void Session_OnStart() {
   // Session start-up code goes here.
}

void Session_OnEnd() {
   // Session clean-up code goes here.
}

First, what happened to an appropriate signature? Second, the Session_End event is so flaky that you shouldn’t bank on it.

Here’s another quote from Handling Public Events:

In any of these classes, look for the public events they define. You can hook them in Global.asax using the syntax ModuleName_OnEventName. For example, the Start event of the SessionStateModule module is declared protected void Session_Start(Object sender, EventArgs e) in Global.asax. You can use the syntax Session_OnStart in a <script runat=server> block in an ASP.NET application file to define an event handler for the Start event of the SessionStateModule.

So do you need that On prefix or not? And should handlers be private, protected or public? No wonder there’s so much confusion over this.

Quiz

How about a quiz? What if you define the following methods in global.asax (yes, all of them):

  • void Session_Start(object sender, EventArgs e)
  • void Session_Start()
  • void Session_OnStart(object sender, EventArgs e)
  • void Session_OnStart()
  • void Session_Start(object sender)

Having these five event handlers, which one(s) will be called? Place your bets.

And the Winner Is…

It turns out all of them, except the last one, will be called, and in the same order as listed! Not that anyone would want to declare more than one, but it demonstrates that the On prefix does not matter. Neither does it the access modifier—private, protected or public—matter. As long as the handler has no arguments, or has two arguments that resemble a correct signature, it will be called.

Digging Deeper

I got curious why this was taking place and started digging with Reflector. Eventually, I found a method, HookupEventHandlersForAppplicationAndModules, inside the HttpApplication class. I believe this is where event handlers of modules are magically wired.

This method goes through a list of methods that look like event handlers, extracts the part before the underscore (e.g. “Session” in Session_OnStart), and looks up an HttpModule with this name. It then extracts the part after the underscore (taking into account the optional On prefix), and then creates a delegate with the extracted name. Next, the method tries to add this delegate to the right event in the identified module. If an event handler had no parameters, a special ArglessEventHandlerProxy comes to the rescue.

Which Methods Are Picked Up?

The only missing bit is which methods in global.asax look like event handlers. You can see the algorithm in the ReflectOnMethodInfoIfItLooksLikeEventHandler method of HttpApplicationFactory. In a nutshell, this method checks if the method has a return type of void; and if the first argument to a method is of type object and the second—of type EventArgs or a derivative thereof. If the signature is satisfactory, the method is passed on as a possible event handler. A special case is a method without parameters—it’s treated as a potential event handler as well.

Conclusion

I hope at this point it is clear why all variations of Session.Start event handlers in global.asax, except the last one listed, were called. I still don’t understand the reason for all this late binding and the need to drag this file around. At least this article should settle disputes about the “proper” naming of event handlers within global.asax.

10 comments

Igor Olikh
on February 19, 2006

Thank you.


Hadar
on March 01, 2006

Very nice article. it clear things up.
I was also wondering why global works like this - it is really a bad implemention.


Jørn Schou-Rode
on May 20, 2006

"so VBScript-ish, so loosely–typed"

I think you are absolutely right! I tend to do handle all application events through HttpModules instead, which also helps to keep different functionalities apart.


Nick
on September 20, 2006

It was probably implemented so "VBScript-ish" to support the ability to upgrade an ASP site to ASP.NET by people who are still learning ASP.NET.


Mike
on September 10, 2007

How else would you wire these events up, through an HttpModule? That may be correct, but it may also be 'too difficult' for many VB programmers, and MS wants to help them by giving them an easy way to hook these events.

And hooking up the session events is even more difficult without global.asax


WC
on October 02, 2007

It's a just a quick, convenient way to wire up stuff. It's obviously an aid to upgrades from classic asp. Don't like it? Write a module and delete the file. Poof, problem solved.


Daniel Williams
on August 07, 2008

This was a great summary. Thank you for delving into it and distilling it into a short, concise article.


Vivek
on December 18, 2008

Nice article.

Made things clear.

Thank you so much.


PF
on December 31, 2008

Thanks for investigation! Horrible implementation :-( VisualBasic programmers are really privileged sort of people ;-)

Here [1] is the request to have the events as a part of the HttpApplication interface, but it was not listen from MS side :-(

[1] http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=104258


Rick Wannall
on August 01, 2009

Thanks! A lovely detailed look at a detail that had made me wonder a few times also. I had emprically arrived at just about the right conclusion, but that's not really the same as knowing for sure. This was a great little find.