This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


This article assumes you're familiar with VBScript and Active Server Pages
Download the code (4KB)

Bake in Persistent State with Cookies
William McLuskie

If you're using Active Server Pages to serve up your Web site to users, you can easily use cookies to keep track of visitors.
By design, HTTP is a stateless environment. The client browser requests individual documents from the Web server, which in turn receives the request, processes it, returns a document, and discards the request. HTTP does not provide any mechanism to associate a particular request with any previous one.
      With Active Server Pages (ASP), state can be maintained using session variables. Unfortunately, as their name implies, session variables are available only within the session or Web application in which they were created. Your Web application may appear as one logical application to the user, but it may actually be composed of several components, each in its own virtual directory. By using cookies, you can maintain application state across multiple Web applications.

Got Milk?
      Cookies are a general mechanism that server-side connections can use to both store and retrieve information on the client side of the connection. The server-side code can create chunks of state information (cookies), which are returned to the browser in the document's header. The browser then stores the cookies on the client computer. Each cookie includes a range of URLs for which that cookie is valid. Any future requests made by the browser that fall within that range of URLs will include the cookie data as part of the request.
      There is a limit to the amount of data that can be stored in cookies. All of the cookie data is transmitted in the header of the document. The exact format of the header is not important, since ASP hides the implementation from the programmer. The maximum amount of data that can be sent is approximately 5,063 characters, and the maximum number of cookies per page is 130.
      This leaves you quite a bit of room to work with. But before you stuff 5KB of information in there, just remember that the more data stored in a cookie, the more data that must cross the wires on a page request.

Which Flavor Would You Like?
      There are two types of cookies: disk cookies and RAM cookies. Both types of cookie can be created as either a single or a dictionary cookie.
      Disk cookies are written to the disk by the browser. The lifetime of a disk cookie is controlled by setting the cookie's expiration attribute. Disk cookies are stored on the client's hard drive and sent to the server with each request until they expire. They can be deleted before they expire by setting their expiration attribute to a past date.
      RAM cookies are kept in memory, and they are never written to disk. These cookies exist until the user exits the browser application. RAM cookies are created if the expiration attribute on a cookie is not set.
      Single cookies are simple CookieName to CookieValue mappings. Some examples are:


 CustomerName   = William McLuskie
 ShoppingCartID = 53188
 CustomerPhone  = (704) 555-0030
Dictionary cookies use an array metaphor of CookieName(Key) = CookieValue.

 Customer(Name)    =    William McLuskie
 Customer(CartID)  =    53188
 Customer(Phone)   =    (704) 555-0030

Is That My Cookie?
      There are a few problems associated with using cookies. First, since cookies are stored on the client machine or kept in memory by the browser, they do not follow the user from machine to machine. Second, the browser does not take into consideration who the current user is, so multiple users on the same machine will overwrite each other's cookie files. Third, cookie files are not protected, so it is possible to delete them from the hard drive. Finally, the cookie files are not encrypted. Thus, disk cookies are not the right place to store passwords or sensitive information.

Figure 1: Security Options in Internet Explorer 4.0
Figure 1: Security Options in Internet Explorer 4.0

      If you plan to use cookies in your application, you must ensure that your users have not disabled cookies in their browsers. This is a purely client-side decision. To enable cookies in Microsoft® Internet Explorer 4.x, select View | Internet Options and go to the Advanced tab. Scroll down to the Security section and select "Always accept cookies" (see Figure 1). If the user wants to see each cookie that the browser receives, they should select "Prompt before accepting cookies" in the Advanced tab and a Security Alert dialog will appear before a cookie is accepted (see Figure 2). Remember that you can have up to 130 cookies per page—and you'll have to click OK on that dialog after every one of them before your page is displayed.
Figure 2: Cookie Security Alert
Figure 2: Cookie Security Alert

Let's Bake a Batch
      When working with VBScript to design an ASP-based application, the details required to implement cookies are hidden. This makes using cookies very simple. Outgoing cookies (to be sent to the browser) can be created with the Cookie collection of the Response object. Incoming cookies (from the browser) are available in the Cookie collection of the Request object.
      The Request object's Cookie collection does not distinguish between disk and RAM cookies, but it does have one attribute, HasKeys, which can be used to determine whether a cookie is a single cookie or a dictionary cookie. If your cookie is called CookieName, it can be retrieved with Request.Cookies(CookieName). If CookieName is a dictionary cookie and has a key of KeyName, it can be retrieved with Request.Cookies(CookieName)(KeyName). Take a look at the cookieReadAll subroutine in Figure 3 for an example of using the Request object's Cookie collection. Each cookie created in the Response object's Cookie collection has four attributes: Expires, Domain, Path, and Secure (see Figure 4).
      You must place the code for all of your cookies before the <HEAD> tag of the file. If you don't, you'll get the following error message: "The HTTP headers are already written to the client browser. Any HTTP header modifications must be made before writing page content."
      The code to create the cookies described earlier would look something like this:


 Response.Cookie(CustomerName).Expires = DateAdd("d", 7, Now()) '== 1 week
 Response.Cookie(CustomerName) = "William McLuskie"
 Response.Cookie(ShoppingCartID).Expires = DateAdd("d", 7, Now())
 Response.Cookie(ShoppingCartID) = "53188"
 Response.Cookie(CustomerPhone).Expires = DateAdd("d", 7, Now())
 Response.Cookie(CustomerPhone) = "(704) 555-0030"

 Response.Cookie(Customer).Expires = DateAdd("d", 7, Now()) '== 1 week
 Response.Cookie(Customer)(Name) = "William McLuskie"
 Response.Cookie(Customer)(CartID) = "53188"
 Response.Cookie(Customer)(Phone) = "(704) 555-0030"

Allow Them to Cool Before Eating
      Running the code in Figure 5 creates the cookies listed in Figure 6. The first three are single RAM cookies, the fourth is a single disk cookie, and the last three comprise a dictionary RAM cookie. Notice that the Path attribute is set for Flavor3.
      Running the code in Figure 7 from a directory called Cookies displays all of the cookies returned by the browser for the Web application (see Figure 8). Note that Flavor3 was not returned. Running the same code from a directory called Cookies/Test displays all of the cookies returned by the browser with the page (see Figure 9). Flavor3 was returned this time because Flavor3 was the only cookie with a value assigned to its Path attribute (see Figure 6).
      Be careful when setting the Path attribute for a cookie. In ASP, the case of the path for the requested page must exactly match the case of the string in the Path attribute. If you run Cookies/Test/CookieRead.asp and Cookies/test/CookieRead.asp from your browser, the same ASP file will execute, but the cookies will be different. Cookies/test/CookieRead.asp will not contain the Flavor3 cookie since the "test" in the requested path does not match the "Test" in the Path attribute of the cookie.

Time to Clean Up
      If you had "Prompt before accepting cookies" turned on, you may have noticed that you received a cookie whose name began with ASPSESSIONID. This cookie is generated by ASP and is used to keep track of your session. ASP is using the same method that I described earlier to do its own work. When you display all of the cookies returned by the browser, you will not see the ASP Session ID. ASP conveniently hides it from your code (see Figure 10).

Figure 10: ASPSESSIONID Cookie Alert
Figure 10: ASPSESSIONID Cookie Alert

Conclusion
      Using cookies inside ASP is simple, and it's much easier than trying to use cookies in CGI scripts written in C, Perl, or Java. The team that created ASP did a lot of work in the background to make sure you don't have to concern yourself with the nuts and bolts of getting cookies across the wire. Just remember that cookies are best when they are kept small and don't contain any confidential information.

From the November 1998 issue of Microsoft Interactive Developer.