:::: MENU ::::

Tuesday, December 16, 2008

Caching is an excellent way to improve the performance of a web application, and ASP.NET offers a rich caching API. Caching data typically involves the Cache object, which serves as an in-memory cache available to all requests to a web application. For example, when a visitor reaches the Top Selling Products page you can store the results retrieved from the database in the Cache object. When the next visitor reaches this page the list of top products can be pulled from the cache rather than from the database. This style of caching is referred to as a per-application cache because the data in the Cache object is shared among all requests to a specific web application and its data survives as long as the application.

There is another style of caching known as per-request caching in which the cache is specific to each request and the items in the cache only exist for the duration of the request. This style of caching is useful for sharing information among the many actors that are involved in a particular request to an ASP.NET resource. Consider an ASP.NET page that uses a Master Page and contains a User Control. When this page is requested there are three actors involved in the request: the Master Page, the User Control, and the ASP.NET page. Each of these actors have their own declarative markup and code, and in many cases they may need to work with the same data. For example, in an online message board website the Master Page might display a synopsis of the currently logged on user's information. This particular ASP.NET page might also load information about the currently logged on user, as might the User Control. Without any form of per-request caching, the Master Page, User Control, and ASP.NET page will each need to go to the database to get the currently logged on user's information, whereas in a perfect world this information would have only been retrieved once.

Every time the ASP.NET engine receives a request for a resource it creates an instance of the HttpContext class responsible for handling that request. The core objects that every ASP.NET developer is familiar with - Response, Request, Session, and so on - are actually properties of this HttpContext object. A lesser known property of the HttpContext class is the Items collection, which provides a key/value collection that can be used to share state during the lifetime of the request. The Items collection is an ideal location for a per-request cache store.

The following code snippet shows the HttpContext class's Items collection in action in terms of the messageboard website example described above. While the Items collection could be accessed directly from the code in the Master Page, User Control, and ASP.NET page, ideally it would be moved outside of these actors and located within the architecture. Within the application architecture there might be a MessageboardUser class with properties describing the attributes of a user and methods for retrieving information about all users, about a particular user, about certain subsets of users, and so on. The following code snippet shows the GetUser(userId) method and the use of the Items collection.

  1. public class MessageboardUser  
  2. {  
  3.     public MessageboardUser GetUser(int userId)  
  4.     {  
  5.         // See if the user information is in the Items collection  
  6.         MessageboardUser u = HttpContext.Current.Items["GetUser" + userID.ToString()]   
  7.            as MessageboardUser;  
  8.         if (u == null)  
  9.         {  
  10.             // The user is NOT in the cache... Get the user information from the  
  11.             // database  
  12.             u = GetUserFromDatabase(userId);  
  13.             // Put the user information into the cache  
  14.             HttpContext.Current.Items["GetUser" + userID.ToString()] = u;  
  15.         }  
  16.         return u;  
  17.     }  
  18. }  

With this small addition to the architecture code the site now takes advantage of a per-request cache and can save unneeded work when there are more than one actor in a single request using the same functionality or information.

Note that to access the Items collection from outside of an ASP.NET page you need to use HttpContext.Current.Items. Furthermore, you need to have added using System.Web to the class file and reference the System.Web.dll assembly in the Class Library project where your architecture is implemented.