The Global.asax and Global.asax.cs files are added to an ASP.NET project when C#Builder generates the ASP.NET application. Their purpose is to supply entry points into the application for each request. For example, an ASP.NET application will start executing when the first request for the page is made. Some type of initialization may need to be performed at that point in time to make sure the application is ready to handle the request. Additionally, there are methods to handle different types of events that may occur during an application's lifecycle. Table 12.1 outlines what those events are by specifying the method that handles a given event and what it is for.
C#Builder creates a Global.asax file with a single Application directive, identified by the line with <%@ Application ... %>. The following line shows an Application directive tha t C#Builder creates by default. Definition of the attributes is outlined in Table 12.2. <%@ Application Codebehind="Global.asax.cs" Inherits="Global.Global" %>
The Global.asax file appears in the designer surface as a plain white surface where components and controls can be added. This file only executes on the server and will never render a visual appearance for the client. Therefore, adding a visual control doesn't make sense because it has no effect. However, adding nonvisual components, such as data components, would be useful in situations where database interaction facilitates request processing. Chapter 15, "ADO.NET and File I/O," discusses data components in depth. The Global.asax.cs file is the code-behind file that contains the code for application events. Each method corresponds to an entry in Table 12.1. Listing 12.1 demonstrates the sequence of event handling in Global.asax.cs. The code uses the Application state object, discussed in the next section, to build a logging system that is passed to the main Web page, which is shown in Listing 12.2. You can view this listing in C#Builder by loading the code that comes with this book. Listing 12.1 Application Event Handling Code (Global.asax.cs)using System; using System.Collections; using System.ComponentModel; using System.Web; using System.Web.SessionState; namespace Global { /// <summary> /// Summary description for Global. /// </summary> public class Global : System.Web.HttpApplication { public const string LogName = "GlobalLog"; ArrayList globalLog = new ArrayList(); public Global() { InitializeComponent(); WriteAppLog("Initializing Global.asax."); } protected void WriteAppLog(string logEntry) { if (Application != null && Application[LogName] != null) { globalLog = (ArrayList)Application[LogName]; } globalLog.Add(logEntry); if (Application != null) { Application[LogName] = globalLog; } } protected void Application_Start(Object sender, EventArgs e) { WriteAppLog("Executing Application_Start."); } protected void Session_Start(Object sender, EventArgs e) { WriteAppLog("Executing Session_Start."); } protected void Application_BeginRequest(Object sender, EventArgs e) { WriteAppLog("Executing Application_BeginRequest."); } protected void Application_EndRequest(Object sender, EventArgs e) { WriteAppLog("Executing Application_EndRequest."); } protected void Application_AuthenticateRequest(Object sender, EventArgs e) { WriteAppLog("Executing Application_AuthenticateRequest."); } protected void Application_Error(Object sender, EventArgs e) { WriteAppLog("Executing Application_Error."); } protected void Session_End(Object sender, EventArgs e) { WriteAppLog("Executing Session_End."); } protected void Application_End(Object sender, EventArgs e) { WriteAppLog("Executing Application_End."); } #region Web Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { } #endregion } } Listing 12.2 Web Form Displaying Application Eventsusing System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; namespace Global { /// <summary> /// Summary description for WebForm1. /// </summary> public class WebForm1 : System.Web.UI.Page { private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here ArrayList globalLog = (ArrayList)Application["GlobalLog"]; if (globalLog != null) { foreach (string logEntry in globalLog) { Response.Write(logEntry + "<br>"); } } } #region Web Form Designer generated code override protected void OnInit(EventArgs e) { // // CODEGEN: This call is required by the ASP.NET Web Form Designer. // InitializeComponent(); base.OnInit(e); } /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.Load += new System.EventHandler(this.Page_Load); } #endregion } } The purpose of Listing 12.1 is to create a logging mechanism that captures the sequence of events throughout the application life cycle. This will help you understand when each event handler fires and offer a framework that you can experiment with for different scenarios. Although the next section explains the Application state object, the code here uses it to facilitate the logging mechanism as shown in the following line, which is an excerpt from Listing 12.1: protected void WriteAppLog(string logEntry) { if (Application != null && Application[LogName] != null) { globalLog = (ArrayList)Application[LogName]; } globalLog.Add(logEntry); if (Application != null) { Application[LogName] = globalLog; } } The WriteAppLog method accepts a string that is meant to be appended to a list of strings that form a logging mechanism for application events. The Application state object maintains a state bag of objects that are accessible for the life of an application. Because this method is called from the constructor, as well as other event handlers, there must be a check to see if the Application state object exists yet, which it won't if being called from the constructor. Additionally, the code must make sure that the globalLog ArrayList has been added to the Application state. Accessing it without these checks could result in a NullReferenceException being thrown. So, the logic of getting the globalLog ArrayList from Application state, adding the new string, and adding globalLog back to Application state is nicely encapsulated into this method. Now, both the constructor and event handlers can call this method with a single method call, simplifying their syntax. Because the same Application state object is available to the entire Web application, the main Web Form accesses it to print the current log. The listing that follows is an excerpt from Listing 12.2 that shows how this is done: private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here ArrayList globalLog = (ArrayList)Application["GlobalLog"]; if (globalLog != null) { foreach (string logEntry in globalLog) { Response.Write(logEntry + "<br>"); } } } As shown in the preceding code, the Page_Load method pulls the ArrayList from the Application state object and iterates through the entries, printing each to the client browser. For output, the code uses the Write method of the Response object, which renders the string passed in to the client browser. Because the output is HTML, the code appends a line break tag, <br>, to the string. Figure 12.1 shows how this output appears. Figure 12.1. Display of application events.The output in Figure 12.1 shows the application starting up and all the steps it goes through. Each request to the page generates an Application_BeginRequest / Application_AuthenticateRequest / Application_EndRequest event sequence. There will be two of these calls because there is an extra request to establish the session. Clicking the Refresh button on the browser generates a new Application_BeginRequest / Application_AuthenticateRequest / Application_EndRequest event sequence, but not a new Session_Start. To generate a new Session_Start, close and reopen the browser. To generate a new Application_Start event, close the browser. Build the application by clicking Project, Build <project name> (Shift+F9), and reopen the browser. The rebuild causes the application to restart.
|