Removing Session Variables in a Loop

(Return to Main Code Corner Page)

Even though the use of session variables can be resource costly, sometimes the application logic makes them the most attractive solution. For example, if you have a series of forms that need to be populated, and you don't want to commit the data to the database until all of the forms are completed, the use of session variables to store the form values temporarily can be a very attractive approach: it allows the user to navigate both backward and forward without losing entered data.

In order to minimize resource drain, however, it is useful to destroy unwanted session variables when you are done with them. Of course, you can call Session.Abandon() to clear all variables, but what if you only want to remove certain variables rather than all of them? Moreover, what if you want to do so programmatically by looping through the collection?

At first glance, this does not seem to be an issue. Consider the code in Example 1. We start by initializing all of our variables. Next, we display them using a simple for loop.

<%
'Clear all contents
Session.abandon()
'Set new variables
Session("strCity") = "Miami"
Session("strState") = "Florida"
Session("strEmail") = "Someone@Somewhere.com"
Session("strWebsite") = "www.FairfieldConsulting.com"
Session("strFirstName") = "Patrick"
Session("strMiddleName") = "Kenneth"
Session("strLastName") = "Fairfield"
Session("strNickName") = "Fritz the Blank"
Session("strPhone") = "(123) 456-7890"
Session("strFax") = "(123) 098-7654"
%>
<!--Display the variables-->
<h2>Before Removal:</h2>
<%
for each objItem in Session.Contents
    response.write(objItem & ": " & Session.Contents(objItem) & "<br />")
next
%>

Now imagine that we want to preserve for other pages in the site all variables that have the string "Name" in them, i.e., strFirstName, strMiddleName, strLastName, strNickName but to remove all other session variables. At first, one might expect that the code like that in Example 2 should do the trick.

<%
'remove contents without Name in it
for each objItem in Session.Contents
    if InStr(objItem,"Name")<1 then
        Session.Contents.Remove(objItem)
    end if
next
%>
<!--Display the variables after contents removed-->
<h2>After Removal:</h2>
<%
for each objItem in Session.Contents
    response.write(objItem & ": " & Session.Contents(objItem) & "<br />")
next
%>

However, when you test the page, we can see that is not the case!

What happened? Why have the variables for the state, web site, and fax number remained?

The problem lies in the interaction of two processes that don't work well together. On the one hand, we are using a for loop that iterates through the collection, and on the other, we are using the .Remove() method which modifies the collection during this iteration. As a result, the for loop will operate in an unexpected manner.

Fortunately, a solution is at hand. The first step is to loop through the collection to create a list of items to be removed. Next, we create an array based on that loop. Finally, we iterate through the array and remove each item in the array from the session contents as in Example 3:

<%
'Create a list of variables to remove
strListToRemove= ""
for each objItem in Session.Contents
    if InStr(objItem,"Name") <1 then
        strListToRemove = strListToRemove & "~"& objItem
    end if
next
'Split the list into an array, loop through and remove the contents
arrItemsToRemove = Split(strListToRemove,"~")
for i=0 to UBound(arrItemsToRemove)
    Session.Contents.Remove(arrItemsToRemove(i))
next
%>

Now when we test the page, we get the results we expect.

This article is significant in two respects. I have received many inquiries from programmers attempting to do something similar to the above with session variables, and they were convinced that the problem resulted from a bug in VBScript or with ASP. However, as I show here, this is standard for VBScript collections, and rather than being a bug, it is an error in program logic that is devilishly difficult to isolate. In a larger context, the same logic applies to dealing with VBScript collections in general, and the approach discussed here can be used in all such instances.

(Return to Main Code Corner Page)