Skip navigation

Bake ASP.NET Apps With Cookie Classes

Take control of browser cookies with the .NET Framework's HttpCookie and HttpCookieCollection classes.

ClassAct

LANGUAGES: VB .NET

TECHNOLOGIES: Cookies

 

Bake ASP.NET Apps With Cookie Classes

Take control of browser cookies with the .NET Framework's HttpCookie and HttpCookieCollection classes.

 

By Ken Getz

 

HTTP cookies allow a Web server to communicate with a browser making the request for a page. Each cookie takes the form of a name/value pair, passed between the server and the client in the HTTP header. Cookies are stored either in memory (and are only valid for the current session) or are persisted to disk if the Web page designer assigns them an expiration date in the future. In memory, the HTTP header includes a string like this one, which contains multiple cookies:

 

ASP.NET_SessionId=4mqbrkbd35cibwychzbuzw3b;

UserName=Mary; FontInfo=FontName=Tahoma&

FontColor=DeepSkyBlue&FontSize=Medium

 

In this example, the HTTP header contains three cookies. First, ASP.NET_SessionID contains the session ID ASP.NET uses to retrieve session variables from its internal lookup table. Next, UserName contains the value "Mary." Finally, FontInfo contains multiple named values: FontName, FontColor, and FontSize.

 

This simple example points out some interesting facts. First of all, ASP.NET (and ASP) relies on a cookie to maintain the session state - without that cookie, there's no way for ASP to track the current session. (Luckily, ASP.NET offers an alternative to using a cookie for this purpose as many users disable the availability of cookies from within their browsers. See documentation in the web.config file for more information.) Cookies can contain a single value (as in the case of the UserName cookie) or multiple values (as with the FontInfo cookie). If a cookie contains multiple values, it appears in the HTTP header much like a standard query string within an HTTP request, with name/value pairs separated by an ampersand (&).

 

Cookies cannot contain anything but text because they're passed in the HTTP header, which limits their capabilities. They also must be relatively small - less than 1,024 bytes. So you can't store objects in cookies unless you serialize them as small amounts of text. But that's not really what cookies were meant for. They were meant only to pass small amounts of textual information between the client and the server, stored on the client side.

 

If the Web site you're visiting creates one or more cookies and assigns them a future expiration date, your browser creates a cookie file on disk corresponding to the response to your request for data. For example, after I visited the sample site you'll investigate throughout this article, I found a cookie file on my hard drive (see Figure 1).

 


Figure 1. Requesting a page from a site that creates persistent cookies adds cookie files to your hard drive. The files don't get deleted even after the cookies expire, so you might want to clean this folder occasionally.

 

Corresponding to the HTTP header information shown previously, the keng@localhost[2].txt file contained this text:

 

UserName

Mary

localhost/

1024

351393792

29499798

3124092368

29499742

*

FontInfo

FontName=Tahoma&FontColor=DeepSkyBlue&FontSize=Medium

localhost/

1024

351393792

29499798

3124092368

29499742

*

 

Although most of the contents are meaningless to human readers, it's still relatively clear how this text corresponds to the in-memory HTTP headers. In any case, cookie files are simply text and available to anyone who can access the folder containing them. You should be careful about what types of information you place into users' cookies; that is, you want to store information your site can use to locate information in server-side databases - you won't want to store confidential information in a user's cookie.

 

When you request a page from a specific URL, the browser can look in your cookies folder and find the cookie file corresponding to the site you're requesting a page from. If it finds the file, the browser will load the contents into memory and insert them into each subsequent HTTP request to the Web server. ASP.NET can then retrieve the name/value pairs from the HTTP_COOKIE section of the HTTP request header and use them to determine the page's HTML output. Additionally, ASP.NET can tell the browser to add, delete, or update the cookies with new values and expiration dates by including them in the HTTP response's header.

 

As you'll see, the .NET Framework makes working with cookies trivially easy. I created sample page (see Figure 2) that demonstrates the concepts involved in creating and retrieving cookies. It's not terribly elegant, but it shows off several features involved in creating and consuming cookies. Most of the code you'll find in the sample manages the drop-down lists on the page. Very little of the page's code handles the cookies; they don't require much effort.

 


Figure 2. The sample page allows you to enter a name, and select various font attributes for the controls on the page. The page saves the name into a single cookie, and all the font information into a second cookie.

 

Use the HttpCookie and HttpCookieCollection Classes

Both the Request and Response properties of a page - that is, HttpRequest and HttpResponse objects provided as properties of an object and of the CurrentContext property of a thread - provide a Cookies property. This property is an HttpCookieCollection object that provides the methods you might expect for working with a collection of objects, such as Add, Clear, Remove, and Set (the Set method updates the value of an existing cookie). The HttpCookieCollection class also provides useful methods and properties for manipulating key/value pairs, such as the GetKey method, which returns the key at a particular index within the collection; and the AllKeys property, which returns a string array containing all the key names within the collection. To retrieve a single cookie from the Request or Response object's Cookies property (I think this is the technique you'll use most often), write code like this:

 

If Not Request.Cookies("UserName") Is Nothing Then

  txtName.Text = Request.Cookies("UserName").Value

End If

 

This example determines whether the browser sent the UserName cookie in the current request and if so, displays its value in a text box on the page. Note that you must check to ensure a cookie isn't Nothing before you work with it; attempting to retrieve properties or call methods of an object that doesn't exist causes a NullReferenceException to be thrown.

 

The HttpCookie class provides a number of useful properties, and no methods specific to the class. You can call the class's constructor explicitly, passing in either a name for the cookie, or a name and a value for the cookie, like this:

 

Dim ck As New HttpCookie("UserName")

ck.Value = "Mary"

' or

Dim ck As New HttpCookie("UserName", "Mary")

 

Note the lack of a default constructor in this example. If you use the constructor, you'll need to supply at least a name. You also can retrieve the Name or Value properties once you've created the cookie.

 

To force a cookie to be preserved across sessions, you can set its expiration date to some date and time in the future using the Expires property. For example, this code causes the cookie to be available for the next 24 hours:

 

ck.Expires = Today.AddDays(1)

 

To demonstrate this behavior, try browsing to Cookies.aspx from the sample project. On the sample page, try making some changes to the controls, then click on the Home link to browse to another page within the same session. Now, navigate back to the Cookies.aspx page - your cookies remain in memory. But if you close the session and restart, your settings disappear. If you repeat the experiment after selecting the Save Information? check box, however, your settings will be preserved across sessions for up to 24 hours.

 

Cookies can contain more than one value, and you can add name/value pairs to the Values property of a single cookie. For example, the sample page stores all the font information in a single cookie. This code, from Cookies.aspx, retrieves font information from the DropDownList controls on the page and stores it all into a single cookie:

 

Dim ckFont As New HttpCookie("FontInfo")

ckFont.Values("FontName") = ddlFont.SelectedItem.Text

ckFont.Values("FontColor") = ddlColor.SelectedItem.Text

ckFont.Values("FontSize") = ddlSize.SelectedItem.Text

 

To retrieve one of these "subitems," use syntax like this:

 

Dim ck As HttpCookie

ck = Request.Cookies("FontInfo")

 

Dim strTemp As String

strTemp = ck.Values("FontName")

 

This code retrieves a cookie from the page's Request object, then retrieves one of its subvalues.

 

Investigate the Project

When you first load the sample page Cookies.aspx in a browser, the browser can't locate the associated cookie file (obviously, ASP.NET hasn't saved it on the client yet). In this case, your request doesn't include any cookie information, so no cookie values are loaded. Try out the sample page: Navigate to Cookies.aspx in a browser window, enter a name, and select various font attributes. Click on the Submit button to trigger a post-back, updating the page display. After each round trip, you should see the changes you requested and the values for cookies from the previous round trip. Why are the cookies "out of date"? Remember, you're seeing the cookie values as they're submitted in the request - as they're stored on the client. These are always one version old, compared to the latest settings you see on the page.

 

When you post back to the page, code in the page's Load event handler managing the post-back creates cookies in the Response object's Cookies collection based on the values you've sent to the page. These cookies are sent back to the browser, which simply posts them back to the server in the next request or, if you choose, also saves the cookies to disk (you must set the expiration date in your code to do this). The code in Figure 3 runs in the sample page's Load event handler.

 

If Page.IsPostBack Then

  Response.Cookies("UserName").Value = txtName.Text

 

  Dim ckFont As New HttpCookie("FontInfo")

  ckFont.Values("FontName") = ddlFont.SelectedItem.Text

  ckFont.Values("FontColor") = ddlColor.SelectedItem.Text

  ckFont.Values("FontSize") = ddlSize.SelectedItem.Text

  Response.Cookies.Add(ckFont)

 

  If chkSaveCookies.Checked Then

    ' Expire the cookie in one day.

    Response.Cookies("UserName").Expires = _

     Today.AddDays(1)

    Response.Cookies("FontInfo").Expires = _

     Today.AddDays(1)

  End If

Else

  ' Code removed here...

Figure 3. If you're posting back to the sample page, code in the page's Load event handler adds a cookie to the HttpResponse object's Cookies collection.

 

Note that the code in Figure 3 uses an alternative technique for creating a new cookie. Instead of instantiating a new HttpCookie object, setting its value, and adding to the Cookies collection, you can allow the collection to create the cookie on the fly using this code:

 

Response.Cookies("UserName").Value = txtName.Text

 

It's the equivalent to this:

 

Dim ck As New HttpCookie("UserName", txtName.Text)

Response.Cookies.Add(ck)

 

If the page isn't posting to itself, the code will attempt to retrieve existing cookies from the Request object; if it finds existing cookies, it renders the page according the saved values it finds (see Figure 4).

 

If Page.IsPostback Then

  ' Code removed here...

Else

  If Not Request.Cookies("UserName") Is Nothing Then

    txtName.Text = Request.Cookies("UserName").Value

  End If

 

  If Not Request.Cookies("FontInfo") Is Nothing Then

    Dim ck As HttpCookie = Request.Cookies("FontInfo")

 

    ' Handle font information.

    Dim strTemp As String

    If ck.HasKeys Then

      strTemp = ck.Values("FontName")

      SelectItem(ddlFont, strTemp)

      SetFontName(strTemp)

 

      ' Repeated for font size and color.

 

    End If

  End If

End If

Figure 4. If you're not posting back to the sample page, the Load event handler attempts to load information from the cookie passed in the HttpRequest object's Cookies collection.

 

You've seen much of the code from Figure 4 previously. Note that this fragment not only checks to ensure that the FontInfo cookie exists, it also uses the HasKeys property to verify that the cookie has subkeys:

 

If Not Request.Cookies("FontInfo") Is Nothing Then

  Dim ck As HttpCookie = Request.Cookies("FontInfo")

 

  ' Handle font information.

  Dim strTemp As String

  If ck.HasKeys Then

 

For each of the three font cookie values, the code retrieves the value, selects the matching value in the DropDownList control, and calls code to iterate through all the controls on the page, setting the appropriate property:

 

strTemp = ck.Values("FontName")

SelectItem(ddlFont, strTemp)

SetFontName(strTemp)

 

Dig Deeper

You've now seen all the code you'll find in this article's sample project (see the Download box for details), but the HttpCookie and HttpCookieCollection classes provide more methods and properties than those you've seen here. If you need to manipulate cookies within the Request or Response object's Cookies property, take some time to look into the HttpCookieCollection's documentation. For working with a single cookie, you'll need to investigate the HttpCookie class's documentation. Specifically, this class provides three properties not covered here: Domain, Path, and Secure. These properties determine whether or not the cookie is transmitted to the client. If you set the Domain property, you can limit the cookie's transmission to clients requesting the cookie from the specific domain. For example, on my server, if I set the Domain property of a cookie to "microsoft.com", the cookie never gets sent to the client - the client didn't request the cookie from microsoft.com, so the server didn't send it. The Path property lets you build a complete path for a specific URL that the cookie applies to. ASP.NET combines this property value with the Domain property value to create the full path associated with the cookie. Finally, the Secure property allows you to specify that the cookie is transmitted only over secure connections (that is, only if the request was made using the HTTPS protocol).

 

A special thanks to Andy Baron for providing the basis for this demonstration, as part of the ASP.NET courseware we co-wrote with Mary Chipman for Application Developer's Training Company (http://www.appdev.com). In addition, thanks to Paul D. Sheriff, who reminded me of the steps required to iterate through all the controls on a page. This is one of those obscure techniques that's useful, but not terribly obvious.

 

The sample code in this article is available for download.

 

Ken Getz is a senior consultant with MCW Technologies and splits his time between programming, writing, and training. He specializes in tools and applications written in Visual Studio .NET and Visual Basic, and he is co-author of Access 2002 Developer's Handbook Desktop Edition as well as the training materials for AppDev's ASP.NET, Access 97 and 2000, Visual Basic 5.0, and Visual Basic 6.0 classes. He speaks frequently at technical conferences and is a contributing writer for asp.netPRO. E-mail Ken at mailto:[email protected].

 

The SelectItem and SetFontName Procedures

Although not directly related to the HttpCookie class, The SelectItem and SetFontName Procedures are interesting. The SelectItem method allows you to specify a DropDownList control and the text of the item you want to select. It uses the FindByText method of the control's Items collection, then passes the value its ListItem object finds to the control's IndexOf method. Finally, given the index of the item you specify, the code sets the SelectedIndex property of DropDownList:

 

Private Sub SelectItem( _ ByVal ddl As DropDownList, ByVal Value As String)

 

  ddl.SelectedIndex = _

   ddl.Items.IndexOf(ddl.Items.FindByText(Value))

End Sub

 

The SetFontName procedure (along with the SetFontSize and SetFontColor procedures) iterates through all the controls on the page, skipping HyperLink controls (hyperlinks look odd if you modify their fonts and colors). It's not obvious how to visit each control on the page until you know the trick: The HtmlForm object corresponding to your page's HTML

tag is the actual container of the controls, and the form is exposed as a control within the page. The SetFontName procedure (with its exception handling and special casing for the HyperLink control removed) looks like this:

 

Private Sub SetFontName(ByVal FontName As String)

  Dim ctl As Control

 

  For Each ctl In Page.FindControl("Form1").Controls

    CType(ctl, WebControl).Font.Name = FontName

End Sub

 

The other two related procedures are almost identical. These procedures use the Page object's FindControl method to locate the HtmlForm containing all the controls. For this sample page, the HtmlForm object's name is Form1 (you can view the page in HTML view to verify the name), so that's the control the code locates using the FindControl method. (To be honest, I was tempted to use delegates to shorten this code - it's awfully repetitive in the sample page. But doing so would have complicated the page, and I would have used more space explaining the delegate handling than in writing the HttpCookie class itself.)

 

Tell us what you think! Please send any comments about this article to [email protected]. Please include the article title and author.

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish