An ASP.NET application consists of all the Web pages and code files that can be invoked from a virtual directory and its subdirectories on a Web server. Besides .aspx files and code-behind files such as those we have already examined, an application can also have a global.asax file and a configuration file config.web. In this section we examine the features of ASP.NET applications. We then investigate the mechanisms for working with application state and session state and for configuring Web applications. Our illustration will be our Acme Case Study (Step 2).
To appreciate the Web application support provided by ASP.NET, we need to understand the concept of a Web session. HTTP is a stateless protocol. This means that there is no direct way for a Web browser to know whether a sequence of requests is from the same client or from different clients. A Web server such as IIS can provide a mechanism to classify requests coming from a single client into a logical session. ASP.NET makes it very easy to work with sessions.
An ASP.NET application can optionally contain a file Global.asax, which contains code for responding to application-level events raised by ASP.NET. This file resides in the root directory of the application. Visual Studio will automatically create a Global.asax file for you when you create an ASP.NET Web Application project. If you do not have a Global.asax file in your application, ASP.NET will assume you have not defined any handlers for application-level events.
Global.asax is compiled into a dynamically generated .NET Framework class derived from HttpApplication.
Here is the Global.asax file for our AcmeWeb case study, Step 2.
' Global.asax Imports System.Web Imports System.Web.SessionState Imports OI.NetVb.Acme Public Class Global Inherits System.Web.HttpApplication #Region " Component Designer Generated Code " ... Public Shared acmedat As Acme Sub Application_Start(ByVal sender As Object, _ ByVal e As EventArgs) ' Fires when the application is started acmedat = New Acme() End Sub Sub Session_Start(ByVal sender As Object, _ ByVal e As EventArgs) ' Fires when the session is started Session("UserId") = "" End Sub Sub Application_BeginRequest(ByVal sender As Object, _ ByVal e As EventArgs) ' Fires at the beginning of each request End Sub Sub Application_AuthenticateRequest( _ ByVal sender As Object, ByVal e As EventArgs) ' Fires upon attempting to authenticate the use End Sub Sub Application_Error(ByVal sender As Object, _ ByVal e As EventArgs) ' Fires when an error occurs End Sub Sub Session_End(ByVal sender As Object, _ ByVal e As EventArgs) ' Fires when the session ends End Sub Sub Application_End(ByVal sender As Object, _ ByVal e As EventArgs) ' Fires when the application ends End Sub End Class
The most common application-level events are shown in this code. The typical life cycle of a Web application would consist of these events:
Application_Start is raised only once during an application's lifetime, on the first instance of HttpApplication. An application starts the first time it is run by IIS for the first user. In your event handler you can initialize a state that is shared by the entire application.
Session_Start is raised at the start of each session. Here you can initialize session variables.
Application_BeginRequest is raised at the start of an individual request. Normally you can do your request processing in the Page class.
Application_EndRequest is raised at the end of a request.
Session_End is raised at the end of each session. Normally you do not need to do cleanup of data initialized in Session_Start, because garbage collection will take care of normal cleanup for you. However, if you have opened an expensive resource, such as a database connection, you may wish to call the Dispose method here.
Application_End is raised at the very end of an application's lifetime, when the last instance of HttpApplication is torn down.
In addition to these events, there are other events concerned with security, such as AuthenticateRequest and AuthorizeRequest. We will discuss ASP.NET security in Chapter 16.
In the case study, we instantiate a single global Acme object instance acmedat in Application_OnStart. This single instance is stored as a shared data member of Global.
In the Session_Start event handler we initialize the session variable UserId to be a blank string. We discuss session variables later in this section.