| The
ASP.NET HttpApplication
class hides a number of complex concepts in order to simplify the programming
model. Some of these simplifications are designed to handle compatibility
issues with the classic Microsoft Active Server Pages (ASP) Application object in order to make
migration easier. Therefore, it may be important for developers to understand
some of the differences, in particular where performance issues are a
concern.
Application
Class and Application Instances
An
application class is defined in the Global.asax file. The code in Global.asax
defines a new class that is derived from System.Web.HttpApplication. Consider the following code in Global.asax, which adds a new object array
to the Application object:
public class Global : System.Web.HttpApplication
{
public Global()
{
InitializeComponent();
}
protected void Application_Start(Object sender, EventArgs e)
{
this.Application.Add("TestItem",new object[]{"one","two","three"});
}
And here, in the Page_Load event handler of a page in our Application ,
we will pull it back out:
private void Page_Load(object sender, System.EventArgs e)
{
object[] MyStuff=(object[])Page.Application["TestItem"];
for(int i=0;i<MyStuff.Length;i++)
Response.Write(MyStuff[i]+" <br/>");
} In
the absence of a Global.asax file, the base class, HttpApplication, is used as the application class.
The ASP.NET runtime creates as many instances of application classes as
needed to process requests simultaneously. For most applications, this
number is limited to the number of threads and remains in the range of
1 through 100, depending on the hardware, server load, configuration,
and so on. Many requests reuse application instances, and a list of free application instances is kept during periods of reduced load. Application
instances are used in a thread-safe manner, that is, one request at a
time. This has important implications:
- You
do not have to worry about locking when you access non-static members
of the application class.
- Application
code can store request data for each request in non-static members of
the application class (except after
the EndRequest
event because this event can maintain the request for a long time).
Because
static members of any class, including an application class, are not thread-safe,
the user code must provide appropriate locking for access to static members.
This applies to any static member that you add to the application class.
Microsoft provides the following guidelines to access the application
instance that is associated with the current request:
- From
the Global.asax, use the this
(Me in
VB.Net) object.
- From
a page, every page includes a strongly-typed ApplicationInstance property (e.g., "Page.Application["TestItem"]")
- From
the HttpContext
object, use the HttpContext.ApplicationInstance
property (which you type as HttpApplication):
HttpApplication ctx=(HttpApplication)HttpContext.Current.ApplicationInstance;
object[] MyAppStuff=(object[])ctx.Application["TestItem"];
for(int j=0;j<MyAppStuff.Length;j++)
Response.Write(MyAppStuff[j]+"<BR/>");
Because Application refers to the global application
state dictionary in classic ASP, ASP.NET uses ApplicationInstance and not Application as a property name to
refer to the application instance that processes the current request.
Application
Events
The
lifetime of a request (commonly referred to as the "Http pipeline") consists
of a series of the application events (and some implicit steps that ASP.NET
implements). These events are listed below in the order in which they
are executed:
1.
BeginRequest
2.
AuthenticateRequest event
3.
DefaultAuthentication internal event
4.
AuthorizeRequest event
5.
ResolveRequestCache event
6.
Internal
step to "map handler" (when compilation takes place, a page
instance is created)
7.
AcquireRequestState event
8.
PreRequestHandlerExecute event
9.
Internal
step to "execute handler" (when the page code is executed)
10.
PostRequestHandlerExecute event
11.
ReleaseRequestState event
12.
Internal
step to filter responsesUpdateRequestCache
event
13.
UpdateRequestCache event
14.
EndRequest event
The
following items can handle these events:
- Internal
ASP.NET page framework (for example, steps 6, 9, and 12 in the preceding
list).
- HTTP
modules that are configured for the application. The default list of
HTTP modules is defined in the Machine.config file. Additional custom
modules may be specified by the developer in the web.config for the
application.
- Code
in Global.asax that is hooked through the Application_[On]EventName method or that is hooked explicitly
when you add event handlers for an alternative handler name:
protected void Application_OnBeginRequest(Object sender, EventArgs e)
{
Response.Write("OnBeginRequest Fired!");
}
Each
event can have synchronous and asynchronous subscribers. Asynchronous
subscribers are executed first. Not all events are always executed; the
only event that is always executed is EndRequest.
As a result, you should perform all after-request cleanup in the EndRequest event:
protected void Application_OnEndRequest(Object sender, EventArgs e)
{
Response.Write("OnEndRequest Fired!<br/>");
}
In most cases, the actual response content is sent to the client after
the application instance is finished with the response (which is after
EndRequest).
Application_OnStart
and Application_OnEnd
ASP.NET
introduces the Application_OnStart
and Application_OnEnd
"events" for compatibility with classic ASP. These handlers
are executed only once in the lifetime of an application and not for every
application instance. So, if you change non-static members in these methods,
you affect only one application instance and not all instances. You can
initialize one application instance either in the constructor or by overriding
the Init method.
Application_OnStart
is a logical equivalent to the class constructor for the application class,
but it offers one advantage: the code has access to the HttpContext for the first request
to the application.
Application
State
Application
state is a global dictionary of late-bound objects, which classic ASP
introduces to compensate for the absence of global variables in Microsoft
Visual Basic Scripting Edition (VBScript). In ASP.NET, you can access
application state through one of the following:
- Application property (which is defined in both HttpApplication and Page classes)
- HttpContext.Application
ASP.NET
includes application state primarily for compatibility with classic ASP
so that it is easier to migrate existing applications to ASP.NET. It is
recommended that you store data in static members of the application class
instead of in the Application
object. This increases performance because you can access a static
variable faster than you can access an item in the Application dictionary.
To access static application members from pages in Microsoft Visual C#
.NET and Microsoft Visual Basic .NET, you must use the ClassName attribute in Global.asax to name your application
class. For example, in a "Script Only" global.asax:
<%@
Application Language="C# | VB" ClassName="MyClass"
%>
In CodeBehind:
public class Global
: System.Web.HttpApplication
{
public static string StaticTest ="This is the original value";
. . .
If a static member is named MyStaticMember
in your Global.asax file, you can use MyClass.MyStaticMember
to access it from your page.
The code in the sample Web application
for this article writes items to the output stream that illustrate some
of these unique properties as they are set or fired from within the global.asax
or the Page itself, and will make it easier to examine and / or experiment
with the unique Application Object.
Download
the Code that accompanies this article
| |
| | Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform. |
|