DekGenius.com
[ Team LiB ] Previous Section Next Section

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 Cache—in 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 farm—either 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.

Table 13-1. HttpApplicationState class summary

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.

    [ Team LiB ] Previous Section Next Section