Table 13-1 summarizes the main features of the various state objects.
|
Object |
Lifetime |
Data Visibility |
Location |
|---|---|---|---|
|
Cache |
Implements an automatic scavenging mechanism, and periodically clears less frequently used contents |
Global to all sessions |
Does not support Web farm or Web garden scenarios |
|
HttpApplicationState |
Created when the first request hits the Web server, and released when the application shuts down |
Same as for Cache |
Same as for Cache |
|
HttpContext |
Spans the entire lifetime of the individual request |
Global to the objects involved with the request |
Same as for Cache |
|
HttpSessionState |
Created when the user makes the first request, and lasts until the
|
Global to all
|
Configurable to work on Web farms and gardens |
|
ViewState |
Represents the calling context of each page being generated |
Limited to all requests queued for the same page |
Configurable to work on Web farms and gardens |
In spite of their quite unfamiliar
| Note |
In this chapter, we'll review several objects involved, at various levels, with the state management. We won't discuss cookies in detail, but cookies are definitely useful for storing small amounts of information on the client. The information is sent with the request to the server and can be manipulated and re-sent through the response. The cookie is a text-based structure with simple key/value pairs, and it consumes no resources on the server. In e-commerce applications, for example, cookies are the preferred way of storing user preferences. In addition, cookies have a configurable expiration policy. The downside of cookies is their limited
|
The HttpApplicationState object makes a dictionary available for storage to all request handlers invoked within an application. In classic ASP, only pages have access to the application state; this is no longer true in ASP.NET, in which all HTTP handlers and modules can store and retrieve values within the application's dictionary. The application state is accessible only within the context of the originating application. Other applications running on the system cannot access or modify the values.
An instance of the HttpApplicationState class is created the first time a client requests any resource from within a particular virtual directory. Each running application holds its own global state object. The most common way to access application state is by means of the Application property of the Page object. Application state is not shared across either a Web farm or Web garden.
The HttpApplicationState class is sealed and inherits from a class named NameObjectCollectionBase . In practice, the HttpApplicationState class is a collection of pairs, each made of a string key and an object value. Such pairs can be accessed either using the key string or the index. Internally, the base class employs a hashtable with an initial capacity of zero that is automatically increased as required. Table 13-2 lists the properties of the HttpApplicationState class.
|
Property |
Description |
|---|---|
|
AllKeys |
Gets an array of strings containing all the keys of the items currently stored in the object. |
|
Contents |
Gets the current instance of the object. But wait! What this property returns is simply a reference to the application state object, not a clone. Provided for ASP compatibility. |
|
Count |
Gets the number of objects currently stored in the collection. |
|
Item |
Indexer property, provides read/write access to an element in the collection. The element can be specified either by
|
|
StaticObjects |
Gets a collection including all instances of all objects declared in global.asax using an <object> tag with the scope attribute set to Application . |
Notice that static objects and actual state values are stored in separate collections. The exact type of the static collection is HttpStaticObjectsCollection .
The set of methods that the HttpApplicationState class features are mostly specialized versions of the typical methods of a name/value collection. As Table 13-3 shows, the most significant extension entails the locking mechanism necessary to serialize access to the state values.
|
Method |
Description |
|---|---|
|
Add |
Adds a new value to the collection. The value is boxed as an object . |
|
Clear |
|
|
Get |
Returns the value of an item in the collection. The item can be specified either by key or index. |
|
GetEnumerator |
Returns an enumerator object to iterate through the collection. |
|
GetKey |
Gets the string key of the item stored at the specified position. |
|
Lock |
Locks writing access to the whole collection. No concurrent caller can write to the collection object until UnLock is called. |
|
Remove |
Removes the item whose key matches the specified string. |
|
RemoveAll |
Calls Clear . |
|
RemoveAt |
Removes the item at the specified position. |
|
Set |
Assigns the specified value to the item with the specified key. The method is thread-safe, and the access to the item is blocked until the writing is completed. |
|
UnLock |
Unlocks writing access to the collection. |
Note that the GetEnumerator method is inherited from the base collection class and, as such, is oblivious to the locking mechanism of the class. If you enumerate the collection using this method, each returned value is obtained through a simple call to one of the get methods on the base NameObjectCollectionBase class. Unfortunately, that method is not aware of the locking mechanism needed on the derived HttpApplicationState class because of the concurrent access to the application state. As a result, your enumeration would not be thread-safe. A better way to enumerate the content of the collection is by using a while statement and the Get method to access an item. Alternatively, you could lock the collection before you enumerate.
Notice that all operations on
HttpApplicationState
require some
You don't need to wrap a single call to Set , Clear , or Remove with a lock/unlock pair of statements—those methods, in fact, are already thread-safe. Using Lock in these cases will only have the effect of producing additional overhead, increasing the internal level of recursion:
// This operation is thread-safe Application["MyValue"] = 1;
Use
Lock
instead if you want to shield a
// These operations execute atomically Application.Lock(); int val = (int) Application["MyValue"]; if (val < 10) Application["MyValue"] = val + 1; Application.UnLock();
Reading methods such as
Get
, the
get
accessor of
Item
, and even
Count
have an internal synchronization mechanism that, when used along with
Lock
, will protect them against concurrent and cross-thread
// The reading is protected from concurrent read/writes Application.Lock(); int val = (int) Application["MyValue"]; Application.UnLock();
You should always use
Lock
and
UnLock
together. However, if you omit the call to
UnLock
, the
Instead of writing global data to the
HttpApplicationState
object, you could use public
Whatever form you choose to store the global state of an application, some general considerations apply about the opportunity of storing data globally. For one thing, global data storage results in permanent memory occupation. Unless explicitly removed by the code, any data stored in the application global state is removed only when the application shuts down. On one hand,
For this reason, it is extremely important that you consider using the
Cache
object (which is discussed further in the
Storing data globally is also
// Retrieve data public object GetGlobalData(string entry) { object o = Application[entry]; if (o == null) { // TODO:: Reload the data from its source return Application[entry]; } return o; }