programming4us
programming4us
WEBSITE

Microsoft ASP.NET 3.5 : The HTTP Request Context - The global.asax File

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
7/20/2012 11:33:36 AM
The global.asax file is used by Web applications to handle some application-level events raised by the ASP.NET runtime or by registered HTTP modules. The global.asax file is optional. If it is missing, the ASP.NET runtime environment simply assumes you have no application or module event handlers defined. To be functional, the global.asax file must be located in the root directory of the application. Only one global.asax file per application is accepted. Any global.asax files placed in subdirectories are simply ignored. Note that Microsoft Visual Studio doesn’t list global.asax in the items you can add to the project if there already is one.

Compiling global.asax

When the application is started, global.asax, if present, is parsed into a source class and compiled. The resultant assembly is created in the temporary directory just as any other dynamically generated assembly would be. The following listing shows the skeleton of the C# code that ASP.NET generates for any global.asax file:

namespace ASP
{
    public class global_asax : System.Web.HttpApplication
    {
        //
        // The source code of the "global.asax" file is flushed
        // here verbatim. For this reason, the following code
        // in global.asax would generate a compile error.
        //     int i;
        //     i = 2;  // can't have statements outside methods
        //
    }
}

The class is named ASP.global_asax and is derived from the HttpApplication base class. In most cases, you deploy global.asax as a separate text file; however, you can also write it as a class and compile it either in a separate assembly or within your project’s assembly. The class source code must follow the outline shown earlier and, above all, must derive from HttpApplication. The assembly with the compiled version of global.asax must be deployed in the application’s Bin subdirectory.

Note, though, that even if you isolate the logic of the global.asax file in a precompiled assembly, you still need to have a (codeless) global.asax file that refers to the assembly, as shown in the following code:

<%@ Application Inherits="Core35.Global" %>

We’ll learn more about the syntax of global.asax in the next section, “Syntax of global.asax.” With a precompiled global application file, you certainly don’t risk exposing your source code over the Web to malicious attacks. However, even if you leave it as source code, you’re somewhat safe.

The global.asax file, in fact, is configured so that any direct URL request for it is automatically rejected by Internet Information Services (IIS). In this way, external users cannot download or view the code it contains. The trick that enables this behavior is the following line of code, excerpted from machine.config:

<add verb="*" path="*.asax" type="System.Web.HttpForbiddenHandler" />

ASP.NET registers with IIS to handle .asax resources, but then it processes those direct requests through the HttpForbiddenHandler HTTP handler. As a result, when a browser requests an .asax resource, an error message is displayed on the page, as shown in Figure 1.

Figure 1. Direct access to forbidden resources, such as *.asax files, results in a server error.

Tip

You can duplicate that line in your application’s web.config file and block direct access to other types of resources specific to your application. For this trick to work, though, make sure that the resource type is redirected to ASP.NET at the IIS level. In other words, you must first register aspnet_isapi.dll to handle those files in the IIS metabase and then ask ASP.NET to block any requests. You accomplish this through the IIS manager applet from the Control Panel.


When the global.asax file of a running application is modified, the ASP.NET runtime detects the change and prepares to shut down and restart the application. It waits until all pending requests are completed and then fires the Application_End event. When the next request from a browser arrives, ASP.NET reparses and recompiles the global.asax file, and again raises the Application_Start event.

Syntax of global.asax

Four elements determine the syntax of the global.asax file. They are: application directives, code declaration blocks, server-side <object> tags, and server-side includes. These elements can be used in any order and number to compose a global.asax file.

Application Directives

The global.asax file supports three directives: @Application, @Import, and @Assembly. The @Import directive imports a namespace into an application; the @Assembly directive links an assembly to the application at compile time.

The @Application directive supports a few attributes—Description, Language, and Inherits. Description can contain any text you want to use to describe the behavior of the application. This text has only a documentation purpose and is blissfully ignored by the ASP.NET parser. Language indicates the language being used in the file. The Inherits attribute indicates a code-behind class for the application to inherit. It can be the name of any class derived from the HttpApplication class. The assembly that contains the class must be located in the Bin subdirectory of the application.

Code Declaration Blocks

A global.asax file can contain code wrapped by a <script> tag. Just as for pages, the <script> tag must have the runat attribute set to server. The language attribute indicates the language used throughout:

<script language="C#" runat="server">
    ...
</script>

If the language attribute is not specified, ASP.NET defaults to the language set in the configuration, which is Microsoft Visual Basic. The source code can also be loaded from an external file, whose virtual path is set in the Src attribute. The location of the file is resolved using Server.MapPath—that is, starting under the physical root directory of the Web application.

<script language="C#" runat="server" src="somecode.aspx.cs" />

In this case, any other code in the declaration <script> block is ignored. Notice that ASP.NET enforces syntax rules on the <script> tag. The runat attribute is mandatory, and if the block has no content the Src must be specified.

Server-Side <object> Tags

The server-side <object> tag lets you create new objects using a declarative syntax. The <object> tag can take three forms, as shown in the following lines of code, depending on the specified reference type:

<object id="..." runat="server" scope="..." class="..." />
<object id="..." runat="server" scope="..." progid="..." />
<object id="..." runat="server" scope="..." classid="..." />

In the first case, the object is identified by the name of the class and assembly that contains it. In the last two cases, the object to create is a COM object identified by the program identifier (progid) and the 128-bit CLSID, respectively. As one can easily guess, the classid, progid, and class attributes are mutually exclusive. If you use more than one within a single server-side <object> tag, a compile error is generated. Objects declared in this way are loaded when the application is started.

The scope attribute indicates the scope at which the object is declared. The allowable values are defined in Table 1. Unless otherwise specified, the server-side object is valid only within the boundaries of the HTTP pipeline that processes the current request. Other settings that increase the object’s lifetime are application and session.

Table 1. Feasible Scopes for Server-Side <object> Tags
ScopeDescription
pipelineDefault setting, indicates the object is available only within the context of the current HTTP request
applicationIndicates the object is added to the StaticObjects collection of the Application object and is shared among all pages in the application
sessionIndicates the object is added to the StaticObjects collection of the Session object and is shared among all pages in the current session

Server-Side Includes

An #include directive inserts the contents of the specified file as-is into the ASP.NET file that uses it. The directive for file inclusion can be used in global.asax pages as well as in .aspx pages. The directive must be enclosed in an HTML comment so that it isn’t mistaken for plain text to be output verbatim:

<!-- #include file="filename" -->
<!-- #include virtual="filename" -->

The directive supports two mutually exclusive attributes—file and virtual. If the file attribute is used, the file name must be a relative path to a file located in the same directory or in a subdirectory; the included file cannot be in a directory above the file with the #include directive. With the virtual attribute, the file name can be indicated by using a full virtual path from a virtual directory on the same Web site.

Note

This technique might sound a bit outdated in the dazzling world of ASP.NET 3.5 with AJAX onboard and awaiting for the even more futuristic features of Silverlight. However, if used for what it is supposed to do—inserting the content of a server-side file—it can be helpful even in ASP.NET 3.5. For example, it can be used to build text-heavy pages that contain a lot of relatively static text. Keeping this text on a separate resource might make it easier to manage and maintain.


Static Properties

If you define static properties in the global.asax file, they will be accessible for reading and writing by all pages in the application:

<script language="C#" runat="server">
    public static int Counter = 0;
</script>

The Counter property defined in the preceding code works like an item stored in Application—namely, it is globally visible across pages and sessions. Consider that concurrent access to Counter is not serialized; on the other hand, you have a strong-typed, direct global item whose access speed is much faster than retrieving the same piece of information from a generic collection such as Application.

To access the property from a page, you must use the ASP.global_asax qualifier, shown here:

Response.Write(ASP.global_asax.Counter.ToString());

If you don’t particularly like the ASP.global_asax prefix, you can alias it as long as you use C#. Add the following code to a C#-based page (or code-behind class) for which you need to access the globals:

using Globals = ASP.global_asax;

The preceding statement creates an alias for the ASP.global_asax class (or whatever name your global.asax class has). The alias—Globals in this sample code—can be used throughout your code wherever ASP.global_asax is accepted.

Response.Write(Globals.Counter.ToString());

Important

You can use the global.asax file to handle any event exposed by the modules called to operate on the request. Handlers for events exposed by an HTTP module must have a name that conforms to the following scheme: ModuleName_EventName. The module name to use is defined in the <httpModules> section of the configuration file.


Tracking Errors and Anomalies

When an error occurs, displaying a friendly page to the user is only half the job a good programmer should do. The second half of the work consists of sending appropriate notifications to the system administrator—if possible, in real time. A great help is the Error event of the HttpApplication object. Write an Application_Error event handler in your global.asax file, and the system will call it back whenever an unhandled error occurs in the application—either in the user code, a component’s code, or ASP.NET code.

In the Application_Error event handler, you first obtain specific information about the error and then implement the tracking policy that best suits your needs—for example, e-mailing the administrator, writing to the Windows Event Log, or dumping errors to a text file. The Server.GetLastError method returns an Exception object that represents the unhandled exception you want to track down. URL information is contained in the Request object, and even session or application state is available.

The following code demonstrates how to write an Application_Error event handler in global.asax to report run-time anomalies to the Event Log. An example of this code in action is shown in Figure 2. The code retrieves the last exception and writes out available information to the event log. Note that the ToString method on an exception object returns more information than the Message property. Additional information includes the stack trace.

<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.Text" %>

<script language="C#" runat="server">
void Application_Error(object sender, EventArgs e)
{
    // Obtain the URL of the request
    string url = Request.Path;

    // Obtain the Exception object describing the error
    Exception error = Server.GetLastError();

    // Build the message --> [Error occurred. XXX at url]
    StringBuilder text = new StringBuilder("Error occurred. ");
    text.Append(error.ToString());
    text.Append(" at ");
    text.Append(url);

    // Write to the Event Log
    EventLog log = new EventLog();
    log.Source = "Core35 Log";
    log.WriteEntry(text.ToString(), EventLogEntryType.Error);
}
</script>

Figure 2. The Event Viewer tracks an error on an ASP.NET application.

Your code doesn’t necessarily have to create the event source. If the source specified in the Source property does not exist, it will be created before writing to the event log. The WriteEntry method takes care of that. Windows provides three log files: Application, Security, and System, which is reserved for device drivers. The Log property of the EventLog class gets and sets the log file to use. It is Application by default.

Caution

To create new event logs, applications should use the static method CreateEventSource on the EventLog class. Note, though, that ASP.NET applications can’t create new event logs because the running account (ASPNET or NETWORK SERVICE) doesn’t have enough permissions. If you want your ASP.NET application to use a custom log, create that at setup time.

Other  
  •  Microsoft ASP.NET 3.5 : The HTTP Request Context - Initialization of the Application
  •  Free Email Everywhere and Anytime
  •  IIS 7.0 : Managing Web Sites - Administrative Tasks - Limiting Web Site Usage, Configuring Web Site Logging and Failed Request Tracing
  •  IIS 7.0 : Managing Web Sites - Administrative Tasks - Adding a New Web Site
  •  IIS 7.0 : Managing Worker Processes and Requests
  •  Websocket: Internet In Real Time
  •  IIS 7.0 : Managing Application Pools (part 3) - Advanced Application Pool Configuration, Monitoring Application Pool Recycling Events
  •  IIS 7.0 : Managing Application Pools (part 2) - Managing Application Pool Identities
  •  IIS 7.0 : Managing Application Pools (part 1) - Application Pool Considerations, Adding a New Application Pool
  •  IIS 7.0 : Managing IIS Manager Extensions
  •  
    Top 10
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
    - Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
    - Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    programming4us programming4us
    programming4us
     
     
    programming4us