StateManager Class: Persisting Values Between Pages

Search

 by Remas Wojciechowski

There are more than enough situations where you want or need to pass some values for one page to another. Sometimes the "another" page passes adds some more values and passes the resulting set to yet another page. And so on.

I always found it cumbersome to keep track of the set of values to be passed and to eventually make the value passing happe--be it via the query string or via hidden fields. For some time I have been playing with the thought of creating something that makes my life easier. The VBScript class StateManager is this "something".

Class Members

Properties

Count
Returns the number of items in the class (read-only).
Item
Sets or returns an item for a specified key in the object. Default property (read-write).
Prefix
Sets or returns the prefix that identifies the items of object.

Methods

Add
Adds a key and item pair to a the object.
Remove
Removes a key and item pair from the object.
GetQueryString
Returns the query-string representation of the elements in the object.
GetHiddenField
Returns the hidden-field representation of the elements in the object.
AppendFromQueryString
Adds elements to the object based upon the query-string parameter.
CreateFromQueryString
Overwrites the object with elements based upon the query-string parameter.

Remarks

As you can see, the class utilizes the Dictionary object internally. Some members of the StateManager class correspond with those of the Dictionary object (Count Property, Item Property, Add Method and Remove Method).

Using the StateManager Class

Assume on page1.asp you have a form that collects some information about the user:

<form action="page2.asp" method="post">
<input type="text" name="fname">
<input type="text" name="lname">
<input type="password" name="pwd">
<input type="text" name="email">
<input type="submit" value="Submit">
</form>

In page2.asp you want to perform some operations based on the form data (e.g. write to a database) and pass the data along with the number of users currently in the database to page3.asp. However, for security reasons you don't want to pass the password value.

Since page2.asp doesn't have a visual interface, you'll use the query string to pass the data.

<!-- #include file="statemanager.asp" -->
<%
Dim objStateManager
Dim strQueryString
Dim intNumberOfUsers

'/.../

Set objStateManager = New StateManager
objStateManager.Prefix = ""
objStateManager.AppendFromQueryString(Request.Form)
objStateManager.Add "n", intNumberOfUsers
objStateManager.Remove "pwd"
objStateManager.Prefix = "_"
strQueryString = objStateManager.GetQueryString("page3.asp")
Set objStateManager = Nothing
Response.Redirect(strQueryString)
%>

The value of strQueryString is
page3.asp?_fname=Remigiusz&_lname=Wojciechowski&_email=remasw%40yahoo%2Ecom&_n=17.
Quite smooth, isn't it?

Note: The position where you set the Prefix property is very important. On one hand the methods for batch-filling the object with query string data (AppendFromQueryString and CreateFromQueryString) ignore all items that don't have that prefix. On the other hand the methods for passing the data (GetQueryString and GetHiddenField) use the prefix for the key names. It's advisable to define an application-wide constant for the prefix that you can use for every page in the value-passing chain.

The StateManager Class Source Code

Class StateManager

   Private objDictionary
  
   ' ##################################################
   ' ### Methods
   ' ###
  
   ' ### Initialize
   Private Sub Class_Initialize()
     Set objDictionary = Server.CreateObject("Scripting.Dictionary")
     Prefix = ""
   End Sub
  
   ' ### Terminate
   Private Sub Class_Terminate()
     Set objDictionary = Nothing
   End Sub
  
   ' ### Add
   Public Sub Add(ByVal strKey, ByVal strItem)
     objDictionary.Add strKey, strItem
   End Sub
  
   ' ### Remove
   Public Sub Remove(ByVal strKey)
     objDictionary.Remove strKey
   End Sub
  
   ' ### GetQueryString
   Public Function GetQueryString(ByVal strBaseUrl)
     Dim aKeys
     Dim aItems
     Dim intLB
     Dim intUB
     Dim i
     Dim strQueryString
     strQueryString = strBaseUrl
     aKeys = objDictionary.Keys
     aItems = objDictionary.Items
     intLB = LBound(aKeys)
     intUB = UBound(aKeys)
     For i = intLB To intUB
       strQueryString = AddToQueryString(strQueryString, Prefix & aKeys(i), aItems(i))
     Next
     GetQueryString = strQueryString
   End Function
  
   ' ### GetHiddenField
   Public Function GetHiddenField()
     Dim aKeys
     Dim aItems
     Dim intLB
     Dim intUB
     Dim i
     Dim strHidden
      strHidden = ""
     aKeys = objDictionary.Keys
     aItems = objDictionary.Items
     intLB = LBound(aKeys)
     intUB = UBound(aKeys)
     For i = intLB To intUB
       strHidden = strHidden & HTML_CreateHiddenField(Prefix & aKeys(i), aItems(i))
     Next
     GetHiddenField = strHidden
   End Function

   ' ### AppendFromQueryString
   Public Sub AppendFromQueryString(ByVal varQueryString)
      Dim item, i
      Dim aItems, aKeyItemPair
     Dim intLB
     Dim intUB
      
      If IsObject(varQueryString) Then
         For Each item In varQueryString
            If IsPersistKey(item) Then objDictionary.Add StripPrefix(item), varQueryString(item)
         Next
      Else
         aItems = Split(varQueryString, "&")
        intLB = LBound(aItems)
        intUB = UBound(aItems)
         If Left(aItems(intLB), 1) = "?" Then aItems(intLB) = Mid(aItems(intLB), 2)
        For i = intLB To intUB
            aKeyItemPair = Split(aItems(i), "=")
            If IsPersistKey(aKeyItemPair(0)) Then objDictionary.Add StripPrefix(aKeyItemPair(0)), aKeyItemPair(1)
         Next
      End If
   End Sub

   ' ### CreateFromQueryString
   Public Sub CreateFromQueryString(ByVal varQueryString)
      Dim item, i
      Dim aItems, aKeyItemPair
     Dim intLB
     Dim intUB
      
      objDictionary.RemoveAll
      AppendFromQueryString(varQueryString)
   End Sub
  
   ' ##################################################
   ' ### Properties
   ' ###
  
   ' ### Count
   Public Property Get Count()
     Count = objDictionary.Count
   End Property
  
   ' ### Item
   Public Default Property Get Item(ByVal strKey)
     Item = objDictionary.Item(strKey)
   End Property
  
   Public Property Let Item(ByVal strKey, ByVal strItem)
      objDictionary.Item(strKey) = strItem
   End Property
  
   ' ### Prefix
   Public Prefix
  
   ' ##################################################
   ' ### Private
   ' ###
  
   ' AddToQueryString
   Private Function AddToQueryString(ByVal strURL, ByVal strKey, ByVal strValue)
       Dim strConChar
       Dim strTemp
       Dim intPos
       intPos = CInt(InStr(strURL, "?"))
       If intPos > 0 Then
           strConChar = "&"
       Else
           strConChar = "?"
       End If
       strTemp = strURL & strConChar & strKey & "=" & Server.URLEncode(strValue)
     AddToQueryString = strTemp
   End Function
  
   ' ### IsPersistKey
   Private Function IsPersistKey(ByVal strKey)
      Dim bTemp
      If Left(strKey, Len(Prefix)) = Prefix Then
         bTemp = True
      Else
         bTemp = False
      End If
      IsPersistKey = bTemp
   End Function
  
   ' ### StripPrefix
   Private Function StripPrefix(ByVal strKey)
      StripPrefix = Mid(strKey, 1 + Len(Prefix))
   End Function

   ' ### CreateHiddenField
   Private Function HTML_CreateHiddenField(ByVal strName, ByVal strValue)
      HTML_CreateHiddenField = "<input type=""hidden"" name=""" & strName & """ value = """ & Server.HTMLEncode(strValue) & """/>"
   End Function
  
End Class