Chapter 13. The HttpApplicationState Class
Developers who are new to web-based development
encounter several challenges. Among the most serious is the
realization that rather than a single monolithic application,
web-based applications are just a series of pages. A web server is
like an unusually inattentive waiter. Imagine sitting down for dinner
and placing your order for drinks. When you next see the waiter, he
asks you again what you would like to drink, as if he has never seen
you before. Each request to the web browser is seen as a completely
new request, totally unrelated to any previous request.Several problems with the way web-based applications are structured
need to be resolved:
- Session data (data specific to a single
user across all pages) needs to be available. While it is always a
good idea to minimize session state, it is generally not possible to
completely eliminate session state. - Global data (data required across all pages and to all users) needs
to be exposed. Traditional rich-client applications use global
variables to store needed data application-wide. Classes instantiated
on one page are not available to other pages, so creating global
classes is not a solution.
Session data in ASP.NET can be managed in the
HttpSessionState class,
which will be covered in Chapter 19. Global data
can be stored in the HttpApplicationState class,
which is covered in this chapter.ASP.NET creates the illusion that pages are grouped into an
application. An instance of the
HttpApplicationState class is created the first
time any client requests a URL resource from within the virtual
directory of a particular application. The
HttpContext class
(covered in Chapter 14) exposes a property named
Application that provides access to the
HttpApplicationState class for the application.
The Application property and the HttpApplicationState object it
returns are also available from the Page class.
Since each ASP.NET page inherits from the Page
class, the Application property is available to code on every page.While this chapter covers the HttpApplicationState
class, ASP.NET offers an alternative way to store information with an
application global scope. The Cache class allows a
developer to store data with an application scope. In addition to
caching page output (a topic covered in Chapter 3), ASP.NET allows the developer to store other
information within the Cachein some ways similar to the way
information can be stored in the
HttpApplicationState class. There are, however,
significant differences:
- Information stored in the HttpApplicationState object is stored for
the life of the application. Information stored in the Cache may be
stored for the life of the application (and in any event, may survive
at most for the lifetime of the application), but might be purged
sooner. The ASP.NET runtime can purge any cached item at any time if
system memory becomes scarce. Cached items that are seldom used or
unimportant (as the ASP.NET runtime defines these terms) are
discarded using a technique called scavenging. - Information stored in the Cache can be invalidated based upon a
specific date and time or a time span. HttpApplicationState has no
such ability. - The developer can supply dependency rules to force the Cache to be
refreshed. For instance, you can use a Rube Goldberg-like setup, for
which you cache a dataset and use a trigger in SQL Server to modify a
file in the filesystem on the web server whenever the underlying
table is modified. The cache for a given item can be invalidated
based upon that file changing. Thus, you can cache a dataset and have
the cached dataset refreshed whenever the underlying SQL Server table
is changed. This is not possible with information stored in the
HttpApplicationState object.
One significant limitation of both the Cache and the
HttpApplicationState objects is that they are not shared across
servers in a web farm. While classic ASP programmers will not be
surprised by this, ASP.NET programmers who are familiar with the
HttpSessionState object might be surprised, since in ASP.NET, session
state can be shared across a server
farmeither in a state server or a special SQL Server database.
While having cached items available across all servers on a web farm
would be convenient, the nature of what is stored in the
HttpApplicationState object makes the lack of a shared data store
less critical.The implications of the difference between HttpApplicationState and
the Cache are clear:
- Large chunks of information that might be important should be stored
in the Cache. There is little harm in caching something because if it
is not used and the memory is needed, the item will be scavenged and
the memory used by it freed for the more pressing need. - Information that can change frequently throughout the life of the
application should be stored in the Cache rather than the
HttpApplicationState object. - Information that is stable during the life of the application is best
stored in the HttpApplicationState object. - Information that must always be available and must not be purged
should be stored in the HttpApplicationState object rather than the
Cache. - The Cache class is safe for multithreaded
operations and does not require separate synchronization, unlike the
Application collection (see the method references for the Lock and
UnLock methods later in this chapter).
Classic ASP developers often used the Application object to store
things like database connection strings. In ASP.NET, there is another
alternative for storing small, possibly sensitive bits of information
like connection strings. Inside the configuration files for the
machine or applications, you can place values called
appSettings within the
<configuration> tag. For instance:
<appSettings>
<add key="TestKey" value="TestValue" />
</appSettings>
Multiple add tags can be placed in the
configuration file. To retrieve the value within code, you the
System.Configuration.ConfigurationSettings class.
Specifically, to retrieve the value saved in the TestKey key above,
use the following code:
localVar = ConfigurationSettings.AppSettings("TestKey")While you can place the appSettings section in
web.config or
machine.config , sensitive values are better
stored in the machine.config file.
machine.config is not located in a folder that
is in any way mapped within the web-accessible space. Of course, this
solution for storing application-level information is really only
suitable for static information that does not need to change under
program control as the application is running. Often, you can use
AppSettings and Application state together, caching the value from
AppSettings within the Application object. If a setting with the same
key is contained in both the machine.config and
web.config file, the value in
web.config will be the value returned for the
setting.Much of HttpApplicationState will be familiar to classic ASP
developers. The visible additions and changes from classic ASP are
not dramatic. Most importantly, virtually all existing classic ASP
code dealing with the Application object will work in ASP.NET.When the first client requests a URL from the application, the
Application object's start event is fired. This
event can be handled by creating an event handler in the
global.asax file (the ASP.NET equivalent of
global.asa ) with the following signature:
Sub Application_OnStart( )
'Application initialization code
End Sub
The Application start event is called only once within the lifetime
of an application. This is where you would usually set Application
variables. When the Application ends, a similar event is called with
the following signature:
Sub Application_OnEnd( )
'Application cleanup code
End Sub
In the Application end event, you would dispose of any resources
created in the Application start event. There are a few limitations
to what you can do in the Application-level events, since the
Response, Session, and Request objects are all unavailable.The fact that the Application start event is called once within the
lifetime of an application was mentioned above. However, what exactly
is the lifetime of an application? Whenever the web server starts up,
the first client to request a URL from an application marks the
beginning of the application's lifetime. Similarly,
as the web server stops, either because the underlying service is
stopped or the server itself is restarted, the
application's lifetime ends. Thus, can you presume
that unless the web service restarts or the server itself restarts,
the application will continue running? The short answer is
"No."The longer answer is that to ensure that the Application start and
Application end events called are coherent (i.e., that code has not
been added to Application_End that would require changes to
Application_Start after it had already fired, or vice-versa), any
time the global.asax is changed, the ASP.NET
framework detects that the file has changed. Upon sensing the file
change, the framework completes any current requests and fires the
Application end event (as it existed before the change to
global.asax ). Once the Application end event has
fired, the application restarts, flushing all application information
and client state information. When the next incoming client request
is received, the ASP.NET framework reparses and recompiles the
global.asax file and raises the Application
start event as it appears in the newly saved version of
global.asax . The moral of this story is that
changes to the global.asax file should be
infrequent, presuming the application must be available 24/7.One question that sometimes arises is, "Can the
Application state of one application be accessed from within another
application?" The short answer is
"No." The longer answer is that if
the other application cooperates, you can create a page in one
application that can be called by making an HTTP Request from the
other application. There is no support within the ASP.NET Framework
to do this explicitly.Items can be stored in the Application collection in one of four ways:
- By calling the Add method, passing in the name (or key) to assign to
the item, and the item's value. This value can be of
any type supported by the CLR, including object instances, which are
serialized automatically before being stored. - By calling the Set method, passing in the name (or key) to assign to
the item, and the item's value. This value can be
any type supported by the CLR, including object instances, which are
automatically serialized before being stored. - By explicitly referring to the Item property, passing a name or index
to assign to the new item. - By implicitly referring to the Item property, passing a name to
assign to the new item. This was the most common technique used in
classic ASP.
Items can be accessed in one of four ways:
- By retrieving and iterating over the collection of keys in the
Application collection (see
the Keys collection description for an
example). - By calling the
Get method, passing the name of the item to retrieve. - By explicitly referring to the Item property, passing the name of the
item to retrieve. - By implicitly referring to the Item property, passing the name of the
item to retrieve. This was the most common technique used in classic
ASP.
Items can be removed from the Application collection in one of
several ways:
- By calling the Clear method (clears all items).
- By calling the RemoveAll method (removes all items).
- By calling the Remove method, passing the name of the item to remove.
- By calling the RemoveAt method, passing the index of the item to
remove.
Table 13-1 lists the properties, collections, and
methods exposed by the HttpApplicationState class.
Properties | Collections | Methods | Events[1] |
|---|---|---|---|
Count | AllKeys | Add | Start |
Item | Contents | Clear | End |
Keys | Get | ||
StaticObjects | GetKey | ||
Lock | |||
Remove | |||
RemoveAll | |||
RemoveAt | |||
Set | |||
Unlock | |||
Events | |||
Start | |||
End |
[1] Events are exposed by the
HttpApplication class rather than the HttpApplicationState
class.
