Server-side Cookies
by Peter Wone - Wombat & Me
The trouble with Session.Contents
The Session.Contents collection is great, but there are certain limitations -
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. sscookies.inc 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.
Methods
variable = getCookieValue(cookieName,
fieldName)
setCookieValue cookieName, fieldName,
fieldValue
Dependencies
| Item | Description | ||||||||||||||
| Application.Contents("DB") | A connection object accessing a database containing a
Cookies table. | ||||||||||||||
| Cookies |
Cookie data is stored in a database table structured as shown at right. Even though the | ||||||||||||||
| 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() & ")"
rsCookie.open 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.addNew
rsCookie.fields("userID") = getUserID()
rsCookie.fields("Cookie") = cookieName
rsCookie.fields("fieldName") = fieldName
end if
rsCookie.fields("fieldValue") = value
rsCookie.update
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
%>
Using sscookies.inc
Apart from ensuring that the dependencies are satisfied, all you need do is include sscookies.inc near the start of your ASP code.
<!--#include virtual="/includes/sscookies.inc"-->
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.