Friday, November 25, 2005

Fixing the Global.asax in ASP.NET 2.0

For some reason ASP.NET 2.0 has gone away from the code behind model to the script model for its Global.asax pages. I ran into this when looking at loading configuration data into global statics on application start in a web service.

When I created a default web service project with Visual Studio 2005 first I found no global.asax page was created. Why its not there by default I do not know as you could easily remove it if not needed, and a empty skeletal one has no performance impact anyway.

To add a global.asax, (or web.config for that matter), simply right click the web site or web server project in your solution explorer, select Add New Item from the context menu and then choose Global Application Class (or Web Configuration File for a web.config).

Happy that I finally had a Global.asax in my project, I opened it only to find that there was no class present! With the scripting page model you get a skeletal global.asax something similar to:




Click to Enlarge


The problem as i see it is two fold.

Firstly there is no class object that can be easily referenced from elsewhere in your application. If you were to load configuration information in the application_start event and store it in a global static, you cannot access that static from elsewhere in your application there is no class name to reference by.

Secondly, as there is no class in the global.asax, you cant use "using" statements in the code easily. There may be a way to do this but it doesnt instantly come to hand. If you place a using before the script tag, the keyword isnt recognised. If you place a using after the script tag its not allowed as you are already inside an implicit class!

After a roam on the internet I came up with an excellent reply post by Scott Allen that showed that you can switch back to the code behind model using the inherits attribute to the Application tag:

<%@ Application Language="C#" Inherits="Global" %>

The only other step is to copy the code within the script tag to a normal class file called Global.cs which you add to the project. Then delete the script tag. An example follows:

Click to Enlarge


Thus I now have simple and consistant use of the using keyword along with a class that is accessible from the rest of the web service to get at preloaded configuration information. My config value in this example can now be access by :

Global.ConfigKeyValue


All this is of course still possible within the script model. You dont have to use using statements and can explicitly denote classes. You also can probably store configuration items into the application cache collection instead of your own statics. However, when migrating some older applications that were written using statics, the fact that you can still use the code behind model is quite usefull. Personally I prefer the older method as it provides consistenct and I dont think a dynamic recompile on changing global.asax values is that useful or even appropriate.

But I am interested in knowning the rationale for why the VS2005 ASP team have gone down this change path.

38 Comments:

Anonymous Anonymous said...

Good solution! I like housing my static members picked up from Web.Config in the Global file as well.

1:10 AM  
Anonymous Anonymous said...

Really cool and it helps a lot, thanks!

12:21 PM  
Anonymous Anonymous said...

Thanks, Ross. I just migrated to VS 2005 and nearly panicked when I could not find the Global.asax file. Now my code is working again!!!

5:00 AM  
Anonymous Anonymous said...

I wa looking all over for thi ssimple solution, i knew it was simple, i just didn't remember what/if VS did anything itself when adding the .asax, thanks for the straightforward article!!!

11:01 PM  
Anonymous Anonymous said...

Great article. Please keep the good work!

7:20 PM  
Anonymous Anonymous said...

Thanks a lot man! You saved my day. Thanks a lot again.

2:57 PM  
Anonymous Anonymous said...

fantastic! started using vs2005 and migrated an application from vs2003. session_start wasn't firing! why? the search for answers began. none were found. none, that is, until devine intervention led to your site! who would have guessed ms would change the way global.asax works :) muchas gracias!

5:48 AM  
Anonymous Anonymous said...

Great! You helped to resolve a very difficult problem with remoting in an upgrade of a website from VS2003 to VS2005.

Lots of thanks!

Alejandro G.

www.grupoaoniken.com.ar

8:36 AM  
Anonymous Anonymous said...

You can add using statements, but more like vb then C#:

< %@ Import namespace="System.Xml"% > for example.

While I can not claim this on my own, I must give credit to Resharper 2.0 which auto inserted this into my Global.asax file. Just incase you wanted to do it in the script.

1:37 PM  
Blogger trishantverma said...

It's really a funky solution!

5:44 PM  
Blogger trishantverma said...

Very funky solution! Thanks.

5:46 PM  
Anonymous Anonymous said...

Thank you! Great article, very helpfull!

7:09 PM  
Anonymous Anonymous said...

I had to put the global.asax.cs file in the App_Code directory before it would work.

5:54 AM  
Blogger Stephen A. Fuqua said...

This article is of great help, thank you. However, I think there is another way of accomplishing this... create a class in the App_Code directory and instantiate that class in the basic version of global.asax. I think both approaches will solve the same problem. The App_Code folder gives you more flexibility in terms of splitting up partial classes or having several different global classes.

6:53 AM  
Anonymous Anonymous said...

The approach of creating a code behind file and implementing Session_Start works great when I run my code under the build in web server of VS2005.

However, when I move the code to run under IIS, the Session_Start no longer gets called.

This isn't specific to the code behind model, but I really can't put my finger on why Session_Start isn't called, when Application_Start is, for instance.

Any clues?

7:53 AM  
Anonymous Anonymous said...

Good article, plain and straight to the point. I came across the problem of the "using" statements in Global.asax, because i had to write "System.Text.Encoding.Decoder" every time!! thanks a lot

4:03 PM  
Anonymous Anonymous said...

thanks for this great solution. You wrote this back in 2005 and it's still helping people in 2007.
BTW, my Session_Start gets called ok.

3:28 AM  
Blogger Nik's said...

hi
good work ,
but i am using .net 2005 , and not getting Application_error() event.
what should i do....?

6:10 PM  
Blogger Imran said...

Thank god, i found solution :)

This saves my lots of time and efforts thanks!

1:12 PM  
Anonymous Anonymous said...

Great solution! I converted to VB and it works great. The only problem I have is that not to access my Global shared variables, I have to use Global.Global.VariableName whereas I used to just specify Global.VariableName. Any thoughts on why?

10:36 PM  
Blogger Ross W Nelson said...

Hi all,
glad this post is still helping people 2 years on almost. I have never done that much VB.Net so only really know C# ASP.NET. Sorry. Im also not programming much these days due a plethora of reasons, mostly like becoming an Enterprise Architect and not having enough time to get dirty anymore (even though I think it is important for architects and EA's even to still understand the coal face if not dig at it every day).

I always stated there may be a better solution to this, and some posters have hinted about App_Code or some such area as being the way to do it in 2005 (.Net 2.0). Please try this out. I suspect the way i've put forward will be easier for folks converting from earlier ASP.Net Apps however.

I have no clue what happens to the ASP.NET code behind in Orca but it will probably be interesting to see... any money on it going back to how it was in Jan 2002? :)

Cheers

3:07 PM  
Anonymous Anonymous said...

Very helpful. And the instructions are clear and easy to follow. Thank you.

10:41 AM  
Anonymous Anonymous said...

Thanks for taking the time to document this so thoroughly for .NET newbies like myself.

Like several other posters, I prefer to declare my static members (i.e. global application variables) in Global.cs: it makes those values available as strongly-typed constants, and I can see them via IntelliSense in VS2005.

1:53 AM  
Blogger Jason said...

Thanks heaps ...

This makes it easier for us to resuse our standard collection of classes.

J

3:47 PM  
Anonymous Anonymous said...

Thanks a ton man. I have just started using ASP 2.0 and it was very annoying to see the new approach of global.asax

3:44 PM  
Blogger Gokul said...

Thank u so much!! saved my time!!

7:19 AM  
Blogger Michael Hanney said...

Great article. This is still relevant 2 years on. An alternative approach to putting the global.asax.cs file in the App_Code directory is to compile it into an assembly and reference it using the full namespace like this:
<%@ Application Language="C#" Inherits="MyWebSite.Global" %>

5:46 AM  
Blogger Unknown said...

Great article. Extremely useful. I was really amazed if there is no global.asax by default like asp.net 1.1. Thanks a lot.

7:42 PM  
Anonymous Anonymous said...

Thank you. Thank you. Thank you.

1:22 PM  
Anonymous Anonymous said...

I installed VS05 Express Edition, created a new Web Site , but I do not see Global Application class

9:32 PM  
Anonymous Anonymous said...

Hi Ross,

Thanks for the helpful info. A couple additional comments.

First, dont forget that the purpose of using the Global.asax in the 2.0+ version (using script tag instead of class) goes back to the new "Website" setup in Visual Studio. Allot of "desktop developers" cling to the older 1.1 model of the "WebApplication" and precompilation. Thats actually more tedious to use and the idea of building such a class for Global, despite static variable access, breaks with the newer Web model, which makes web development faster and easier (ie partial classes, App_Code compilation, etc). Microsoft has provided the older WebApp model though for people who do not understand the advantages and prefer that system.

Second, I use the Global.asax like you mentioned, adding a refernce to the global partial class as so:

@ Application Language="C#" Inherits="Security"

But I then place built a custom "Security" class that inherits from HttpApplication (like Global used), and drop that into App_Code, where its compiled with everything else. Like everyone mentioned, I drop statics and global variables into that. This shows that you can leverage your model, but still use the Website Visual Studio project and also customize your own class system to tap into Global.asax. Works great, and thought I would add that into the mix. Thanks Again! - Stormy

4:08 AM  
Blogger Raghunandan Sharma said...

This gave me an 1000 Horse Power boost. I was just fed up trying work around methods. Added a Global.cs file and meanwhile happened to read your article. I am just jumping :D

thanks in deed.

3:26 PM  
Blogger akois said...

if your code in vb don't forget to put [] in your class! %^&!@#@$

Public Class [Global]
Inherits System.Web.HttpApplication
..
..
..

1:01 PM  
Anonymous Anonymous said...

Nice tip - thanks for sharing.

9:02 PM  
Blogger Antonysezhian Materals said...

I have problem regarding public function of entire site. That is one function i need to write. i called that function all over the site.How it can be using C# 2.0.

Reagrds,
Antony Sezhian

5:39 PM  
Blogger Unknown said...

I panicked when I didnt see global.asax....in 2.0 and m application was in 1.1

11:21 PM  
Blogger Zeeshan Arif said...

Thanks it was so informative.

8:19 PM  
Blogger Unknown said...

Good article!

Here is an example of the management of global.asax in .NET 4.0

Application and Global.asax

Greetings!

5:21 AM  

Post a Comment

<< Home