Home > Articles > Programming > Visual Basic

  • Print
  • + Share This
Like this article? We recommend

Saving and Retrieving the User's State

Now that we know what we need to save, let's code the GetState and SaveState methods that actually read the write the data values. This PublishersWebUI sample application will save the state data for each user into a simple CSV text file in which the filename is based on the UserID property value. I like using CSV files during initial development of Web applications because it's simple to change what gets written to them, and because it's a simple enough matter to open them with Notepad to make sure that everything is being saved correctly. After your application design stabilizes (maybe I should say if it ever stabilizes), you might consider changing it to instead write the data to a binary file or to a table in a relational database.

The logic to save the state information is very simple:

  1. Open a CSV file for output destroying the previous contents if it already exists.

  2. Write the search filter value to a record.

  3. Write the number of selected authors in the collection to a record. This simplifies retrieving them later.

  4. For each author in the collection, write the Publisher ID, Publisher Name, and Publisher Phone.

The source code for the SaveState method looks like this:

' Saves all state information to a simple CSV file.
Public Sub SaveState()
  Dim lFileNbr  As Integer
  Dim lPubState As clsPubState
  
  lFileNbr = FreeFile
  Open StateFileName For Output As lFileNbr
  
  ' Save the state data.
  Write #lFileNbr, Filter
  Write #lFileNbr, Publishers.Count
  For Each lPubState In Publishers
    Write #lFileNbr, lPubState.PubID, lPubState.Name, lPubState.Phone
  Next lPubState
  
  Close lFileNbr
End Sub

Both the SaveState and GetState methods use the StateFileName Private Property procedure:

Private Property Get StateFileName() As String
  StateFileName = App.Path & "\" & mUserID & ".usf"
End Property

This property simply returns the fully qualified filename for the state file. In my example, I'm creating the state filename by simply suffixing the UserID property value with .usf (User State File) and saving it to the same folder as where the component is installed. In reality, the path for the state files should be configurable from an INI file option or a registry setting.

For clsUserState to restore the state information, the GetState method generally works like the SaveState method in reverse. However, there are a couple of exceptions to handle. The first one is that we should expect that sometimes the state file won't exist. This could happen because of the following:

  • This is the first request from the user and we haven't written any state information yet.

  • The state file has expired and been deleted by our external process.

  • The uid query string value has been altered by the user somehow. In this case, the uid query string value will be used to create the state filename as long as it contains valid characters that can be used when naming a file. If it contains invalid characters, the operating system will raise a run-time error, so it might be a good idea to generate a new UserID value if the file cannot be opened.

In all cases, if the file doesn't exist, there is no state information to restore so the Filter and Publishers properties should contain default values.

The second exception to check is to make sure that even if a state file is found, it doesn't have expired data in it. Comparing the modified date/time of the state file with the current system time easily does this. The expiration period can be whatever you want—minutes, hours, and even days or months. If the difference is greater than whatever you want the expiration period to be, simply ignore the contents of the file, and again the Filter and Publishers properties should contain default values. In my example, I assume the state data has expired if the file hasn't been used in the last 60 minutes.

My completed GetState method looks like this:

' Attempt to restore the state information from the CSV file.
' If the state file is not found, or the data in the file hasn't
' been used in the last 60 minutes, then we assume a new session.
Public Sub GetState()
  Dim lFileNbr  As Integer
  Dim lNbrPubs  As Long
  Dim lIndex   As Long
  Dim lID    As Long
  Dim lName   As String
  Dim lPhone   As String
  Dim lPubState As clsPubState
    
  Filter = ""
  Set Publishers = New Collection
  lFileNbr = FreeFile
  
  On Error Resume Next
  Open StateFileName For Input As lFileNbr
  
  'If file not found, then that means no state information exists.
  If Err.Number = 53 Then ' 53 = File Not Found.
    Exit Sub
  ElseIf Err.Number <> 0 Then
    Call Err.Raise(Err.Number, Err.Source, Err.Description)
  End If
  
  On Error GoTo 0 ' Reset error handling so run-time errors get raised.
  
  ' If state information is > 60 minutes old, then ignore it.
  If DateDiff("n", FileDateTime(StateFileName), Now) > 60 Then
    Close lFileNbr
    Exit Sub
  End If
  
  ' Get the state data.
  Input #lFileNbr, Filter
  Input #lFileNbr, lNbrPubs
  For lIndex = 1 To lNbrPubs Step 1
    Set lPubState = New clsPubState
    ' Note the syntax of the Input statement won't allow us to input
    ' directly into an object's properties so instead we have to input
    ' into local variables and then assign to the object.
    Input #lFileNbr, lID, lName, lPhone
    lPubState.PubID = lID
    lPubState.Name = lName
    lPubState.Phone = lPhone
    Call Publishers.Add(lPubState)
  Next lIndex
  
  Close lFileNbr
End Sub
  • + Share This
  • 🔖 Save To Your Account