The HttpContext Items Collection

Monday, March 15, 2004

ASP.NET offers a variety of techniques to manage state: application state, session state, view state, and more. You can read more about these other state management collections in the resources section at the bottom of this page, because in this article we are only going to focus on the Items collection of the HttpContext class. First, let’s be clear and state that what you keep in the Items collection will have a very limited scope. Anything you place into the Items collection will only be around for the duration of a single web request, unlike the Session collection, which will keep it’s contents around for each user as long as they continue to make requests. Nevertheless, we will demonstrate several useful techniques with the Items collection in this article.

To understand how to use the Items collection, which is a member property of the HttpContext class, let’s first take a look at the HttpContext class itself.

HttpContext

An HttpContext object will encapsulate specific details of a single HTTP request. Properties of this class include the Request object, the Response object, the Session object, and an AllErrors property which keeps an array of Exception objects accrued during the current request. You can easily access the context for a request from any member function of a Page class:

private void Page_Load(object sender, System.EventArgs e)
{
   Context.Items["MyObject"] = new object();

   object o = Context.Items["MyObject"];
}

In the code above you can see the Items collection is as easy to use as the Session object. Underneath the covers, the Items container is a Hashtable object holding key and value pairs. Ask for an item by name to retrieve an object reference.

Another way to get to the context from anywhere within an ASP.NET application is to use the HttpContext.Current property. Current is a static property which will return the HttpContext object for the current HTTP request. You can use Current from any object in the logical thread of execution for the request (more details to come in another article). The following is an example:

public class TestContext : System.Web.UI.Page
{
   private void Page_Load(object sender, System.EventArgs e)
   {
      MyClass myClass = new MyClass();
      myClass.DoFoo();
   }

   // generated code
}

class MyClass
{
   public void DoFoo()
   {
      HttpContext.Current.Response.Write("Doing Foo");
   }
}

Being able to grab an HttpContext item from anywhere in the ASP.NET application is a powerful concept, but be careful not to abuse the privilege. For example, you wouldn’t want middle tier objects writing out directly to the Response object as this would break the encapsulation rules of an n-tier architecture.

HttpContext.Items

Now that we know how to get to the Context, let’s take a look at some of the uses for the Items collection it contains. One use of the Items collection is to transfer values to another WebForm when using Server.Transfer. As an example, let’s look at the Load event handler for WebForm1.aspx

private void Page_Load(object sender, System.EventArgs e)
{
   ArrayList list = new ArrayList(3);
   list.Add("This list ");
   list.Add("is for ");
   list.Add("WebForm2 to see.");

   Context.Items["WebForm1List"] = list;

   Server.Transfer("WebForm2.aspx");
}

Here we are populating an ArrayList to place into the Items collection and transferring control to WebForm2.aspx. The Load event for WebForm2.aspx prints the contents of the list.

private void Page_Load(object sender, System.EventArgs e)
{
   ArrayList list = Context.Items["WebForm1List"] as ArrayList;

   if(list != null)
   {
      foreach(string s in list)
      {
         Response.Write(s);
      }
   }  
}

Note this technique does not work if you use Response.Redirect. A Redirect results in another round trip to the client and a new HTTP request – thus a new Context object without our ArrayList. To span requests, you’ll need to use the Session object or another state container. Also, there are other techniques you can use to pass state between two forms when using Server.Transfer, these other techniques can be found in the resources section of the article.

Another place to use Context.Items is in the Application_BeginRequest method. Visual Studio generates this method in the Global class of global.asax.cs. If you want to catch a request at the very beginning of the ASP.NET pipeline, Application_BeginRequest is the place to be. This is so early in the pipeline, Session state has not yet been associated with the request. Trying to use the Session object in the event handler will force the following exception:

System.Web.HttpException: Session state is not available in this context.

You can, however, use Context.Items during Application_BeginRequest. This is an ideal spot to load request specific state to carry through until ASP.NET completes the request. You could, for instance, inspect the incoming request URL and load a preferences object with different settings if the site is balitmore.odetocode.com versus www.odetocode.com. Later, during the Load event of any page, you can inspect the Preferences object in the Items collection to make changes to the UI

protected void Application_BeginRequest(Object sender, EventArgs e)
{     
   string prefix = Request.Url.Host.ToUpper();
   
   if(prefix.StartsWith("BALTIMORE"))
   {
      Context.Items["PREFERENCES"] = // Load Baltimore preferences
     }
   else
   {
      Context.Items["PREFERENCES"] = // Load default preferences
   }
}

Using the Context.Item collection you can pass state anywhere during the lifetime of the request – across HttpModules, HttpHandlers, Webforms, and Application events.

 

--

by K. Scott Allen (scott @ OdeToCode.com)

Additional Resources

Personalization in ASP.NET 1.1

Passing Server Control Values Between Pages

Nine Options for Managing Persistent User State in Your ASP.NET Application

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!