The Global.asax File

The Global.asax File

Global.asax is a text file that houses application-level event handlers, declarations that pertain to all parts of the application, and other global application elements. ASP.NET applications don t have to include Global.asax files, but most do. An application can have only one Global.asax file. That file must be located in the application s virtual root directory.

What s inside a Global.asax file? Global.asax supports three element types:

  • Global directives

  • Global event handlers

  • Global object tags

Of the three, the first two are used more often. Global event handlers are particularly important and are the number one reason why developers include Global.asax files in their applications. We ll discuss global directives first and global event handlers second. Then, for completeness, we ll talk about global object tags, too.

Global Directives

Global directives, also known as application directives, provide application-wide instructions to the ASP.NET compilation engine. A Global.asax file supports three types of global directives:

  • @ Application directives

  • @ Import directives

  • @ Assembly directives

Global.asax can contain just one @ Application directive, but it places no limit on the number of @ Import and @ Assembly directives.

The @ Application Directive

@ Application directives serve two purposes: they enable developers to add descriptive text to applications, and they facilitate code-behind programming in Global.asax files. An @ Application directive accompanied by a Description attribute adds descriptive text, as in

<%@ Application Description="My First ASP.NET Application" %>

ASP.NET ignores Description attributes, so descriptions declared with it are visible only to those persons with access to your Global.asax files.

The @ Application directive also supports an Inherits attribute that enables code to be removed from Global.asax and packaged in a separate DLL. Suppose, for example, that you included the following Global.asax file in an application:

<%@ Import Namespace="System.Data" %> <script language="C#" runat="server"> void Application_Start () { DataSet ds = new DataSet (); ds.ReadXml (Server.MapPath ("GlobalData.xml")); Application["GlobalData"] = ds; } </script>

Coded this way, Application_Start, which is an event handler that fires each time the application starts up, is compiled the first time Global.asax is accessed by ASP.NET. To avoid run-time compilation, you can remove Application_Start from Global.asax and code it into a class that derives from System.Web.HttpApplication:

using System.Web; using System.Data; public class MyApp : HttpApplication { public void Application_Start () { DataSet ds = new DataSet (); ds.ReadXml ("GlobalData.xml"); Application["GlobalData"] = ds; } }

Then you compile the CS file into a DLL, place the DLL in the application root s bin directory, and reduce Global.asax to one simple statement:

<%@ Application Inherits="MyApp" %>

Code-behind offers the same benefits to Global.asax that it offers to ASPX files: it catches compilation errors before the application is deployed, and it enables developers to code handlers in C++ and other languages that ASP.NET doesn t explicitly support.

A look behind the scenes reveals why code-behind classes used by Global.asax files derive from HttpApplication. ASP.NET starts an application running when the very first request for that application arrives. Starting an application involves launching a process named Aspnet_wp.exe (commonly referred to as the ASP.NET worker process) if it isn t already running and creating a new application domain in that process to host the application and segregate it from other running ASP.NET applications. In the absence of code-behind, startup also involves parsing Global.asax and placing any content found there into a temporary file containing a class derived from HttpApplication, compiling the temporary file into a DLL, and instantiating the derived class. The resulting HttpApplication object handles the request that prompted the application to start up. As a performance optimization, ASP.NET maintains a pool of such objects and uses them to service incoming requests.

One implication of this design is that any code you include in Global.asax executes in the context of an HttpApplication object. That means you can call HttpApplication instance methods and access HttpApplication instance properties from anywhere in Global.asax. It also explains why using code-behind in Global.asax means deriving from System.Web.HttpApplication rather than System.Web.UI.Page. Because the system places Global.asax code in an HttpApplication-derived class, you must do the same if you want to get your code out of Global.asax and into a DLL.

The @ Import Directive

The @ Import directive serves the same purpose in Global.asax that it serves in ASPX files: it imports namespaces that ASP.NET doesn t import by default. For example, let s say you include the following <script> block in Global.asax:

<script language="C#" runat="server"> void Application_Start () { DataSet ds = new DataSet (); ds.ReadXml (Server.MapPath ("GlobalData.xml")); Application["GlobalData"] = ds; } </script>

Because DataSet is defined in the System.Data namespace and System.Data isn t imported by default, you must either fully qualify all references to DataSet by including the namespace name or place the following directive at the top of Global.asax:

<%@ Import Namespace="System.Data" %>

@ Import directives in Global.asax pertain only to code in Global.asax. They do not import namespaces into other of the application s files.

The @ Assembly Directive

The @ Assembly directive does for Global.asax what @ Assembly does for ASPX files: it identifies assemblies Global.asax uses that ASP.NET doesn t link to by default. (For a list of default assemblies, see Chapter 5.)

As an example, suppose your Global.asax file uses classes in the System.DirectoryServices namespace. Because that namespace isn t imported by default and because the types that belong to that namespace live in System.DirectoryServices.dll, which ASP.NET doesn t link to by default, you need to include the following statements in Global.asax:

<%@ Import Namespace="System.DirectoryServices" %> <%@ Assembly Name="System.DirectoryServices" %>

If you don t, ASP.NET will greet you with an error message the moment the application starts up.

Global Event Handlers

The most common reason for including Global.asax files in ASP.NET applications is to handle global events events that aren t specific to a particular page but that apply to the application as a whole. Some global events are fired by the HttpApplication instances that process individual requests. Others are fired by HTTP modules plug-in components that provide services such as authentication and output caching to ASP.NET. Some events fire on every request. Others fire at predictable junctures in an application s lifetime, such as when the application starts or stops. Still others fire conditionally for example, when an unhandled exception occurs. Regardless of when a global event fires or who fires it, you can process it by including a handler in Global.asax.

Start and End Events

ASP.NET fires global events named Start and End when an application starts and stops. To process these events, include handlers named Application_Start and Application_End in Global.asax:

<script language="C#" runat="server"> void Application_Start () { ... } void Application_End () { ... } </script>

Application_Start is called when the application receives its first request. This handler is frequently used to initialize application state or the ASP.NET application cache (both of which are introduced later in this chapter) with data that is global to the application that is, shared by all of its users. Application_End is called when the application shuts down. Typically, that happens when the application has run for 20 minutes without receiving an HTTP request. Application_End isn t used all that often because ASP.NET applications don t have to clean up after themselves by deleting objects created in Application_Start, but it s sometimes used to write data to a persistent storage medium prior to shutdown so that the data can be reloaded the next time the application starts and to dispose of objects that encapsulate unmanaged resources such as database connections.

Later in this chapter, you ll learn about ASP.NET session state. Session state is a mechanism for storing per-user information (such as shopping carts) in Web applications and preserving it across requests. Session state services are provided by an HTTP module named SessionStateModule, which fires a Start event each time it creates a session and an End event each time a session ends. You can process these events by including handlers named Session_Start and Session_End in Global.asax:

<script language="C#" runat="server"> void Session_Start () { ... } void Session_End () { ... } </script>

Session_Start is called when a user visits your site who hasn t been there recently (usually in the last 20 minutes). Session_End is typically called when a session times out, which by default happens 20 minutes after the last request is received from the user for whom the session was created. The most common use for Session_Start is to initialize session state with data that is unique to each user. You ll see examples later in this chapter.

Per-Request Events

Global.asax can also include handlers for events fired by HttpApplication instances. If present in Global.asax, the following methods are called in every request in response to HttpApplication events. They re listed in the order in which they re called.

Per-Request Global Event Handlers

Method

Description

Application_BeginRequest

Called at the beginning of each request

Application_AuthenticateRequest

Called to authenticate the caller

Application_AuthorizeRequest

Called to determine whether the caller is authorized to access the requested resource

Application_ResolveRequestCache

Called to resolve the current request by providing content from a cache

Application_AcquireRequestState

Called to associate the current request with a session and populate session state

Application_PreRequestHandlerExecute

Called to prepend content to the HTTP response

Application_PostRequestHandlerExecute

Called to append content to the HTTP response

Application_ReleaseRequestState

Called to release (store) any state associated with this session

Application_UpdateRequestCache

Called to update a cache with content returned in the response

Application_EndRequest

Called at the end of each request

These handlers let you customize ASP.NET by plugging into the request processing pipeline. For example, Application_ResolveRequestCache and Application_UpdateRequestCache could be used to implement a custom output cache. Application_AuthenticateRequest and Application_AuthorizeRequest provide hooks for modifying ASP.NET s security apparatus. The event handlers Application_PreRequestHandlerExecute and Application_PostRequestHandler Execute enable HTTP responses to be modified before they re returned to clients. The following Global.asax file uses the latter of these two methods to place a copyright notice at the bottom of each and every page (assuming, of course, that your pages use HTML flow layout rather than absolute positioning):

<script language="C#" runat="server"> void Application_PostRequestHandlerExecute (Object sender, EventArgs e) { HttpApplication app = (HttpApplication) sender; app.Context.Response.Write ("<hr><center><i>" +  "Copyright 2002 by Me, Myself, and I</i></center>"); } </script>

Outputting a copyright notice this way rather than duplicating it in every ASPX file lets you change it in one place to modify it everywhere it shows up.

Error Events

The events listed above fire in each and every request. HttpApplication also defines an Error event that fires if ASP.NET throws an unhandled exception. You can process Error events by including an Application_Error handler in Global.asax. Here s a Global.asax file that logs unhandled exceptions in the NT event log. It uses the FCL s System.Diagnostics.EventLog class to write to the event log:

<%@ Import Namespace="System.Diagnostics" %> <script language="C#" runat="server"> void Application_Error (Object sender, EventArgs e) { // Formulate a message to write to the event log string msg = "Error accessing " + Request.Path + "\n" + Server.GetLastError ().ToString (); // Write an entry to the event log EventLog log = new EventLog (); log.Source = "My ASP.NET Application"; log.WriteEntry (msg, EventLogEntryType.Error); } </script>

It s not unwise to include a handler like this one in every ASP.NET application so that you can detect unhandled exceptions by periodically checking the NT event log. You could even modify the handler to send an e-mail message to a system administrator to apprise him or her of unhandled exceptions (a sure sign of a sick or buggy application) the moment they occur.

Don t be surprised if you encounter a Global.asax file containing an event handler that s not mentioned here. HttpApplication fires a few other events that I haven t listed because they re rarely used or used internally by ASP.NET. Plus, ASP.NET can be extended with HTTP modules that fire global events of their own. HTTP modules can also sink global events, which is precisely how the HTTP modules built into ASP.NET work much of their magic. A full discussion is beyond the scope of this chapter, but further information regarding HTTP modules and events is available in the Microsoft .NET Framework SDK.

Global Object Tags

Global object tags create object instances declaratively. Suppose you want a new instance of ShoppingCart created for each user that visits your site. Rather than do this:

<script> void Session_Start () { Session["MyShoppingCart"] = new ShoppingCart (); } </script>

you can do this:

<object   scope="session" runat="server" />

Assuming ShoppingCart has an Add method, a Web form could add an item to a user s shopping cart by doing this:

MyShoppingCart.Add (...);

This code might not make a lot of sense right now, but it ll make plenty of sense by the end of the chapter.

An <object> tag s Scope attribute assigns a scope to the object instances it creates. Scope= Application creates one object instance, which is shared by all users of the application. Scope= Session creates one object instance per session (that is, per user). Scope= Pipeline creates a unique instance of the object for each and every request.

ASP.NET doesn t create objects declared with <object> tags unless it has to that is, until they re requested for the first time. Lazy instantiation prevents objects from being created unnecessarily if the application doesn t use them.



Programming Microsoft  .NET
Applied MicrosoftNET Framework Programming in Microsoft Visual BasicNET
ISBN: B000MUD834
EAN: N/A
Year: 2002
Pages: 101

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net