Cookie State





Cookie State

Although not part of the HTTP specification (yet), cookies are often used to store user preferences, session variables, or identity. The server issues a Set-Cookie header in its response to a client that contains the value it wants to store. The client is then expected to store the information associated with the URL or domain that issued the cookie. In subsequent requests to that URL or domain, the client should include the cookie information using the Cookie header. Some limitations of cookies include the fact that many browsers limit the amount of data sent through cookies (only 4,096 bytes are guaranteed) and that clients can potentially disable all cookie support in their browser.

ASP.NET provides an HttpCookie class for managing cookie data. Listing 10-16 shows the HttpCookie class definition and the cookie collection properties exposed by the request and response objects. Note that the request and response objects both expose the collection of cookies through the HttpCookieCollection type, which is just a type-safe derivative of the NameObjectCollectionBase class, designed for storing HttpCookie class instances. Each cookie can store multiple name/value pairs, as specified by RFC 2109, which are accessible through the Values collection of the HttpCookie class or indirectly through the default indexer provided by the class.

-16 The HttpCookie Class
NotInheritable Public Class HttpCookie
  Public          Property Domain  As String
  Public          Property Expires As DateTime
  Public ReadOnly Property HasKeys As Boolean
  Public Default  Property Item( _
              ByVal key As String) As String
  Public          Property Name    As String
  Public          Property Path    As String
  Public          Property Secure  As String
  Public          Property Value   As String
  Public ReadOnly Property Values  As NameValueCollection
  '...
End Class

NotInheritable Public Class HttpRequest
  Public ReadOnly Property Cookies As HttpCookieCollection
  '...
End Class

NotInheritable Public Class HttpResponse
  Public ReadOnly Property Cookies As HttpCookieCollection
  '...
End Class

To request that a client set a cookie, add a new HttpCookie instance to the response cookie collection before your page rendering. To access the cookies that the client is sending with any given request, access the Cookies collection property of the request object. Listing 10-17 shows an example of a page that sets and uses a cookie named "Age". If the cookie has not been set, the page adds the cookie to the Response.Cookies collection with a value from a field on the form (ageTextBox). If the cookie has been set, the current value is pulled from the Request.Cookies collection and is used instead.

-17 Using Cookies in ASP.NET
Private Sub Page_Load(ByVal sender As Object, _
                      ByVal e As EventArgs)
  Dim age As Integer = 0
  If (Request.Cookies("Age") Is Nothing) Then
    ' "Age" cookie not set, set with this response
    Dim ac As HttpCookie = New HttpCookie("Age")
    ac.Value = ageTextBox.Text
    Response.Cookies.Add(ac)
    age = Convert.ToInt32(ageTextBox.Text)
  Else
    ' use existing cookie value...
    age = Convert.ToInt32(Request.Cookies("Age").Value)
  End If
  ' use age to customize page
End Sub

Although cookies are typically used to store user-specific configuration information and preferences, they can be used to store any client-specific state needed by an application (as long as that state is converted to string form). It is interesting to contrast our earlier shopping cart implementation using session state with an equivalent implementation using only cookies. The major change in our implementation is the population and retrieval of the shopping cart contents from cookies instead of directly from session state. This can be done by converting the contents of the shopping cart into string form so that it can be sent back as cookies to the client and later restored on subsequent requests. To facilitate this, we have added two new functions to our Item class: HydrateArrayListFromCookies and SaveArrayListToCookies. The first function is called from within the Load event handler of our shopping Page class, and the second function is called from within the PreRender event handler. The implementation of these two functions is shown in Listing 10-18. The rest of our code remains the same because we have changed only how the ArrayList is persisted. Listing 10-19 shows the cookie-based implementation of our shopping cart application.

-18 Item Class with Cookie Serialization Support
Public class Item
  Public Shared Function HydrateArrayListFromCookies() _
                         As ArrayList
    Dim itemCount As Integer = 0
    Dim itemCountCookie As HttpCookie = _
           HttpContext.Current.Request.Cookies("ItemCount")
    If (Not itemCountCookie Is Nothing) Then
      itemCount = Convert.ToInt32(itemCountCookie.Value)
    Else
      itemCountCookie = New HttpCookie("ItemCount")
      itemCountCookie.Value = "0"
      HttpContext.Current.Response.Cookies._
                                   Add(itemCountCookie)
    End If

    Dim cart As ArrayList = New ArrayList()
    Dim i As Integer
    Dim cn As String
    For i = 0 To itemCount - 1
      cn = i.ToString() & "cost"
      Dim cost As Integer = Convert.ToInt32( _
             HttpContext.Current.Request.Cookies(cn).Value)

      cn = i.ToString() & "desc"
      Dim desc As String = _
             HttpContext.Current.Request.Cookies(cn).Value
      cart.Add(New Item(desc, cost))
    Next i

    Return cart
  End Function

  Public Shared Sub SaveArrayListToCookies(_
                                   ByVal cart As ArrayList)

    ' Save array size first
    Dim itemCountCookie As HttpCookie = _
                                New HttpCookie("ItemCount")
    itemCountCookie.Value = cart.Count.ToString()
    HttpContext.Current.Response.Cookies.Add( _
                                           itemCountCookie)

    Dim i As Integer = 0
    Dim it As Item
    For Each it In cart
      Dim descCookie As HttpCookie = _
                     New HttpCookie(i.ToString() + "desc")
      descCookie.Value = it.Description
      HttpContext.Current.Response.Cookies.Add(descCookie)

      Dim costCookie As HttpCookie = _
                    New HttpCookie(i.ToString() & "cost")
      costCookie.Value = it.Cost.ToString()
      HttpContext.Current.Response.Cookies.Add(costCookie)
      i = i + 1
    Next it
  End Sub
  ' remainder of class unchanged from Listing 10-4
End Class
-19 Cookie State Shopping Page Example
Public Class PurchasePage
  Inherits Page

    ' Maintain private cart array variable
  Private m_Cart As ArrayList

  Private Sub Page_Load(ByVal sender As Object, _
                        ByVal e As EventArgs)
    m_Cart = Item.HydrateArrayListFromCookies()
  End Sub
  Private Sub Page_PreRender(ByVal sender As Object, _
                             ByVal e As EventArgs) _
                             Handles MyBase.PreRender
    Item.SaveArrayListToCookies(m_Cart)
  End Sub

  Private Sub AddItem(ByVal desc As String, _
                      ByVal cost As Integer)
    m_Cart.Add(New Item(desc, cost))
  End Sub

  ' remaining code identical to Listing 10-7
End Class

Although it is technically possible to store any type of client-specific state using cookies, as shown in the previous shopping cart example, there are several drawbacks compared with other models. First, all of the state must be mapped into and out of strings, which in general requires more space to store the same amount of data. Second, as mentioned earlier, clients may disable cookies or may have a browser that does not support cookies, thus rendering the application inoperative. Finally, unlike session state, cookie state is passed between the client and the server with every request.


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows