Image of Navigational Map linked to Home / Contents / Search Server-side Cookies

by Peter Wone - Wombat & Me
Image of Line Break

The trouble with Session.Contents

The Session.Contents collection is great, but there are certain limitations -

  1. All values are discarded when the session is abandoned.
  2. All values are session local. Generally this is a wonderful trait, but what about global named values? You just can't do this with the Session.Contents collection, simply because it's session local.
  3. Microsoft Internet Information Server (IIS) gives you a new session whenever you use an absolute URL.
  4. You get a new session when posting via Microsoft Posting Acceptor. This doesn't always happen - it's erratic - but for practical purposes you must operate on the assumption that you are going to get a new session - and therefore will lose access to any values stored in Session.Contents.

It is true that IIS applications can store global values in the Application.Contents collection, but these need to be initialised, so either you rather wastefully initialise everything an application could possibly want, or you find an alternative.

An alternative

The question is how can we implement persistent named values, so the answer is a database. is designed to be included near the start of your ASP file. It declares rsCookies and creates an updateable recordset in which it keeps named values. It lets you get or set named values. If you set the value of an item that doesn't exist, it is created, otherwise the value is updated. This code declares all of its variables, so it won't break under the influence of Option Explicit.


variable = getCookieValue(cookieName, fieldName)
setCookieValue cookieName, fieldName, fieldValue

Item Description
Application.Contents("DB") A connection object accessing a database containing a Cookies table.
Field Type
userID Long
Cookie Text(50)
fieldName Text(50)
Global Yes/No
fieldValue Text(255)
Comment Text(255)

Cookie data is stored in a database table structured as shown at right.

Even though the Comment field isn't necessary for the code in to work, nevertheless it is a very good idea to annotate global persistent values because these are essentially constants that have been moved out of your ASP code and into a database. Like any other code, they need to be commented.

getUserID() A function that you must provide that returns something uniquely identifying the user. Values are local to individual users, except for those marked as Global.

The code

dim rsCookie, temp

set rsCookie = createObject("ADODB.recordSet")
rsCookie.cursorType = adOpenKeyset
rsCookie.lockType = adLockOptimistic
temp = "select * from Cookies where Global " + _
  "or (userID=" & getUserID() & ")" temp, Application("DB"), , , adCmdText

function getCookieValue(cookieName, fieldName)
  dim temp
  temp = _
    "(Cookie='" & cookieName & "') and " + _
    "(fieldName='" & fieldName & "')"
  rsCookie.Filter = temp
  getCookieValue = ""
  getCookieValue = rsCookie.fields("fieldValue")
end function

sub setCookieValue(cookieName, fieldName, value)
  dim temp
  temp = _
    "(Cookie='" & cookieName & "') and " + _
    "(fieldName='" & fieldName & "')"
  rsCookie.Filter = temp
  if (rsCookie.recordCount = 0) then 
    rsCookie.fields("userID") = getUserID()
    rsCookie.fields("Cookie") = cookieName
    rsCookie.fields("fieldName") = fieldName
  end if
  rsCookie.fields("fieldValue") = value
end sub

Implementing getUserID()

The easiest way to get a unique value is to interrogate Session.SessionID. Assign this value to the user by writing it into the response.Cookie. The following code will get it from Sessions when possible and failing that retrieve it from the cookie.

function getUserID()
  dim id
  on error resume next
  id = Session("userID")
  if ((id = "") or IsNull(Session("userID")) ) then
    id = request.cookies("userID")
    session("userID") = id
  end if
  getUserID = id
end function


Apart from ensuring that the dependencies are satisfied, all you need do is include near the start of your ASP code.

<!--#include virtual="/includes/"-->

Then you can use the methods getCookieValue and setCookieValue.

Global constants

You can achieve global constants by manually inserting values into the Cookies table and setting Global to true for the rows in question. Note that you can update the value of such a global constant. It would be possible to code against this but I didn't bother.

Written by: Peter Wone
February '99

Image of Arrow linked to Next Article
Image of Line Break