Dynamic-CD
Search : 
  Powered by FindinSite

ASP Documentation
Overview
• Introduction
• Getting started
• Dynamic-CD wizard
Passwords & Encryption
• Overview
• Example 1
• Example 2
Scripts
• The script language
• Script examples
• Database scripts
Technical details
• Applications
• Built-in objects
• Character Encoding
• Cookies
• Database CDs
• Development tips
• FAQs
• Future developments
• Global.asa
• Network support
• Object registration
• Resources
• ScriptingContext
• Server-side includes
• Sessions
• Technical limits
    
Saving state information

Page
Contents
Introduction Types of state information
Clearing up after you
The Back problem
State transitions

Techniques Saving state using files
Saving state using cookies -  Example script 
Saving state using script session objects
Saving state using URL parameters -  Example script 
Saving state using hidden form variables -  Example script 

Conclusion


Introduction
One of the most important reasons for having scripts is to be able to be able to make your CD interactive.  This means remembering what the user has done before and tailoring each page accordingly.  This process is commonly known as saving the state of an interaction, eg remembering what items someone has ordered.

Writing web page scripts is not like writing an ordinary computer program, where you might simply store a list of parts ordered in an array and wait for the user to choose the next part or opt to complete the order.  Each page request is like running a program from scratch again.  Therefore, to make it feel right to the user, you must "read the state" at the start of each script and "save the state" when you return a page to the user.

There are various techniques available in ASP to help you save the state of user interactions.  Note that saving state in ASP ought to be easier because you should only have one interaction going on at any one time.  In an online ASP based system, there may be many users, each of whom is in the middle of their own interaction.  Some of the techniques commonly used in ASP are available to ASP scripts to make it easier to port code to a Dynamic-CD environment.

If you think you will be dealing with more than one user of your CD on one PC (simultaneously or not), then you will have to find some way of identifying the user, or swapping between users. Read about Multi-User Considerations for further information. The rest of this discussion assumes one person uses one computer.


Types of State Information
It is worth while at this stage considering the types of state information that you might want to store.

Firstly, permanent data is information that you must keep on your online servers. For example, an order for goods must be stored, usually in your server database. 

Long term data is information that you want to store between sessions using the CD, eg after the computer has been restarted.  For example, you might like to store the user's name and address details long term to avoid them having to type it in again.

Short term data is information that you only want to keep during the current period in which someone is using a CD; you don't want it again if the CD is removed or the computer restarted.

Some types of information could be in either long or short term storage.  Suppose the user gets half way through an order but has to stop and switch off their computer.  Two valid approaches are possible and usually acceptable to the user.  When they come back to the CD, either the order appears as they last left it, or they have to begin again.  Both techniques are in use at online web sites.

Transition data is information received from the user telling you what selection they have just made. The transition data is usually added to the saved "old state" and stored as the "new state".

The Conclusion has more thoughts on types of data, and which of the following methods you should use to store information.


Clearing up after you
Being a friendly member of community, you should aim to leave your users' computers untouched after running your CD.  Dynamic-CD helps considerably because it lets you produce an interactive CD without having to install an application.  There's nothing worse than finding someone's pet program cluttering up your computer.

If you create any files on your users' computers then you should aim to delete them when the user has finished using your CD.  This may be hard to achieve in practice if you want to save state between uses of the CD.  The simplest approach is to create any files in the Windows Temporary directory.  When the user does a Disk Cleanup on a drive, they get the option to delete files in this directory that have not been modified in the last week.

If you store files anywhere else, or make any other changes, then you ought to provide an option on your CD to delete the files, etc.


Ouch! - The Back Problem
Before a discussion of state saving techniques, one problem must be pointed out in advance.  A browser lets you press the Back button to return to a previous page.  An unsuspecting user might reasonably assume that any selections since then will be undone.

Some site designers might not be concerned with this issue.  A "Checkout" link might provide a full list of all items ordered and provide options to delete unwanted items.

If you want the Back button to return the user to the displayed state, then you should use the "Hidden form variables" or "URL parameters" methods of storing state information described below.


State transitions
As a final bit of preamble, it is worth considering how most interactive pages pass information to each other.  Transition data is information received from the user telling you what selection they have just made.

Suppose an order is in progress, with one CD bought so far - this one CD is your "saved state" so far.  The user finds another CD, CD002, and presses the Buy button. This transition information (Buy CD002) is the extra information that you add to make the new "saved state".

Script1, say, can pass transition information to Script2 in one of two ways.  The first method is to use standard HTML forms on the page.  The second method is to use links with "QueryString" information on the URL, eg order.asp?buy=CD002.  (This is actually equivalent to the first method if using METHOD=GET forms.)  Script2 has these initial tasks to do:

  • Read the saved state
  • Process the transition data, ie work out if anything is to be added
  • Store the new saved state
    Script2 can then get on with displaying whatever information needs to be displayed to the user next.

    Quite a few scripts pass information to themselves.  When first run, there is no transition information, so a script would display an initial screen.  Links or forms on the page run the same script.  Therefore the same script keeps compiling information from the user. Other links on the page might take the user onto the next stage, eg to the online checkout.


    Methods of Saving State
    The following methods can be used to save state information when using scripts:

    The Conclusion has various recommendations about which method to use.


    How to save state data using files
    In many ways this is the cleanest method of storing state information - you simply write the information to a file.  However it suffers from the Back problem, described earlier, so you may not find it suitable for your application.

    This example gives an idea of how to use files.  See the  FileSystemObject  documentation for more details of the facilities that are available.

    <%
    ' Declare variables and constants
    PUBLIC fso, StateFile
    CONST ForReading = 1
    CONST ForWriting = 2
    CONST ForAppending = 8
    
    ' Get location of our temporary state file
    DIM TempDir
    TempDir = Request.ServerVariables( "WINDOWS_TEMP_DIR")
    StateFile = TempDir & "\MyState.txt"
    
    ' Get handle to FileSystemObject
    SET fso = CreateObject("Scripting.FileSystemObject")
    
    ' If our file exists, read it line by line
    IF fso.FileExists( StateFile) THEN
        Set FileStream = fso.OpenTextFile( StateFile, _
          ForReading, True)
        While FileStream.AtEndOfStream <> True
            line = FileStream.ReadLine
            ' process line
        Wend
        FileStream.Close
        Set FileStream = Nothing
    END IF
    
    ' Append transition data to end of our file
    Set FileStream = fso.OpenTextFile( StateFile, 
      ForAppending, True)
    FileStream.WriteLine( TransitionData)
    FileStream.Close
    Set FileStream = Nothing
    
    SET fso = Nothing
    %>

    In this case, the file MyState.txt in the Windows temporary directory is used to store the user's state.  If the file exists, it is read line by line.  Any transition data is added as a new line to the end of the file.


    How to save state data using Browser cookies

    A cookie is a string that is saved by each user's browser.  A cookie is sent back to the server on each subsequent page access to the same server/path.  Not all browsers support cookies, and some users may have switched cookies off, so you cannot rely on them to store state information.

    If you are none-the-less storing state information using cookies, then you will need to read the current state from one or more cookies, and use the transition data to set any new cookie values.  You must set any cookies before any HTML is output.

    More then one cookie may be stored for each page/site.  Cookies are shared across all pages on the same server/path, so a cookie set in one script is visible in another script.  Use the  Response.Cookies  collection to set cookies and the  Request.Cookies  collection to get the cookies that have been sent by the current user's browser.  As soon as a cookie is set in  Response.Cookies  it appears in  Request.Cookies .

    Click here to see both the following examples working together on one page.

    <%
    ' Get visit number from existing cookie or 
      initialise to 1
    PUBLIC VisitNo
    VisitNo = Request.Cookies("VisitNo")
    if VisitNo="" then
        VisitNo = 1
    else
        VisitNo = CInt(VisitNo)+1
    end if
    
    ' Set cookie with expiry so it is visible next time round
    Response.Cookies("VisitNo") = CStr(VisitNo)
    Response.Cookies("VisitNo").Expires = "December 31, 2002" 
    %>
    
    <HTML>
    <BODY>
    Number of visits here: <%=VisitNo%>
    </BODY>
    </HTML>

    The above example shows how to get and set cookies.  If a cookie has not been set then getting it returns an empty string.  If you want a cookie to persist beyond the current user session then you must set a suitable expiry date in the  Expires  attribute.

    This next example shows some more features of cookies.  Each individual cookie can store more than one value in a key dictionary.  The  For each  statement can be used to find all cookies, or all keys in a cookie.  Finally, the  HasKeys  attribute returns true if a cookie contains keys instead of one ordinary string.  See the  Request.Cookies  documentation for full details.

    <%
    ' Set two items in a cookie key dictionary
    Response.Cookies("list")("one") = "first"
    Response.Cookies("list")("two") = "second"
    %>
    
    <HTML>
    <BODY>
    <%
    ' List all available cookies
    For Each cookie in Request.Cookies
        If Not Request.Cookies(cookie).HasKeys Then
            ' Ordinary cookie
            Response.Write cookie+" "+Request.Cookies(cookie)+"<BR>"
        Else
            ' Cookie with keys: show all key values
            For Each key in Request.Cookies(cookie)
                Response.Write cookie+"("+key+") "+_
    				Request.Cookies(cookie)(key)+"<BR>"
            Next
        End if
    Next
    %>
    </BODY>
    </HTML>


    How to save state data using Script session objects

    A  Session  object keeps track of a user through their current visit to your site.  You can use a session object to store values in a similar way to cookies, ie session values set in one script are visible in another.  When a session times out, by default after 20 minutes, all stored values are lost.  Sessions are slightly easier to use than cookies because you can set session values after you have started to generate HTML output.

    Although the session object itself is stored on the server, ASP uses a cookie to store a Session Id on each user's computer.  Therefore it has the same problems as cookies (not all browsers support cookies, and some users may have switched cookies off), so you cannot rely on them to store state information.

    Because of this problem, not much more information is given here.  Please consult the  Session  documentation for more details.  Here is brief sampler of the methods available:

    <%
      Session("FirstName") = "Jess"
      Session("LastName") = "Smith" 
    %>
    
    Hello <% =Session("FirstName") %>
    
    <%
    Session.Content.RemoveAll()
    Session.Timeout = 5
    Session.Abandon
    %>


    How to save state data using URL parameters
    If you do not have much state information, then saving your state data using URL parameters makes sense.  Not only does this technique avoid the Back problem, described earlier, but it also allows a user to bookmark a page and get the same information displayed on the next visit.

    The URL used to display a page can contain one or more parameters at the end of the URL These parameters represent the stored state.  Any links on a page will usually contain these same parameters, and then optionally add on more parameters to indicate any further selection, ie the transition data.

    In a simple example, the user's preferred language could be passed as a single parameter to all scripts.  The first script page would have no parameters; it would have a series of clickable links to further pages, eg menu.asp?lang=en for English, menu.asp?lang=fr for French, etc.  Each further page would adjust its output to use the chosen language.  All other links should be dynamically generated to propogate the language selection.

    Parameters to web pages appear after the script name.  Put a question mark (?) and then one or more parameters separated by ampersand (&) characters.  Each parameter consists of key=value strings.  Here are some examples URLs containing parameters:

    menu.asp?lang=en
    menu.asp?lang=en&country=gb
    menu.asp?lang=en&country=gb&Item1=CD%2D001

    A script should use the  Request.QueryString  function to look up the string value for a particular key.  The returned value is an empty string if the key is not present in the URL.

    If the parameter key or value contains any characters that are not normally allowed in strings then they must be encoded in hex.  For example to set the key Item1 to CD-001 use this in the URL: Item1=CD%2D001.  To make this job easier, use the  Server.URLEncode  function.  The encoded characters are correctly decoded when you are looking up a key using  Request.QueryString .

    The following full example can be run by clicking here.

    Items ordered:
    <UL>
    <%
    DIM ItemNo, ItemName, ItemValue, NextURL
    
    ' Get start of next URL
    NextURL = Request.ServerVariables("URL") & "?"
    
    ' Find existing state, ie items already ordered
    ' and remember state in next URL
    ItemNo = 1
    Do While true
        ItemName = "Item"+CStr(ItemNo)
        ItemValue = Request.QueryString(ItemName)
        If ItemValue="" then
            Exit Do
        end if
        NextURL = NextURL & ItemName & "=" &_
          Server.URLEncode(ItemValue) & "&"
        Response.Write "<LI>"+ItemValue
        ItemNo = ItemNo + 1
    Loop
    
    ' Work out next URL for each new part ordered
    NextURL = NextURL & ItemName & "="
    
    DIM Part1URL, Part2URL, Part3URL
    Part1URL = NextURL & Server.URLEncode("CD-001")
    Part2URL = NextURL & Server.URLEncode("Book:Manual")
    Part3URL = NextURL & Server.URLEncode("dcd software")
    %>
    </UL>
    
    Order more items:
    <UL>
    <LI><A HREF="<%=Part1URL%>">Order CD</A>
    <LI><A HREF="<%=Part2URL%>">Order Book</A>
    <LI><A HREF="<%=Part3URL%>">Order Software</A>
    </UL>

    This example builds up an order from a list of three available items.  More than one of each item can be ordered.  The page first shows the items already ordered, and then lists the items that can be added to the order as clickable links.

    The items are stored in URL parameters named Item1, Item2, etc.  The script keeps calling itself with each new order item added onto the list as the next free ItemX parameter.

    The script first works out its own page name using the  Request.ServerVariables  function with the Dynamic-CD specific environment variable "URL".  Note that the returned URL does not include any parameters.  !!! This does not currently work in Navigator browsers, so it might be best to hardcode the page name !!! The script then enters a loop that detects all the ItemX parameters.  As well as displaying the item on the page, the script adds items to the URL that will be used for links out of this page.

    Next, the script works out the three different links that are required for each of the three possible selections.  The following HTML displays the options, with the hyperlinks set using inline script fragments.


    How to save state data using Hidden form variables
    You can use hidden form variables to store your current state.  This technique does not suffer from the Back problem, described earlier.  However a bookmarked page will not usually show exactly same information next time round.

    To use this technique, all selections on a page must be made using a form, ie between <FORM METHOD=post> and </FORM>.  Rather than having clickable links to make selections, the user will have to press a Submit-style button to continue.  If you use <FORM METHOD=post> then the current script is called again when the form Submit button is pressed; if you provide an ACTION attribute to the FORM tag, eg <FORM METHOD=post ACTION=altscript.asp>, then an alternative script will process the form results.

    When you want to save state information, you should generate hidden form variable strings.  Hidden form variables do not appear in the user's display.  Here's how to set hidden variable Item1 to CD-001:

    <INPUT TYPE=hidden NAME=Item1 VALUE="CD-001">

    Use the  Request.Form  function to look up the string value of a form variable.  An empty string is returned if the variable does not exist.   Request.Form  is used to access both hidden and ordinary form variables.

    More than one form can be used on a page if need be.
    If <FORM METHOD=get> is used then the form variables are passed as URL parameters, ie exactly the same as the technique described above, so use  Request.QueryString  to access variables instead.

    As for the earlier techniques, a script's first job is to read the old saved state from the hidden form variables.  It should then interpret the transition data, and generate the new state in hidden form variables in the current output.

    The following full example can be run by clicking here.

    <FORM METHOD=post>
    Items ordered:
    <UL>
    <%
    ' Double quotes character
    PUBLIC dq
    dq = Chr(34)
    
    DIM ItemNo, ItemName, ItemValue
    
    ' Find existing state, ie items already ordered
    ' and output hidden saved state
    ItemNo = 1
    Do While true
        ItemName = "Item"+CStr(ItemNo)
        ItemValue = Request.Form(ItemName)
        If ItemValue="" then
            Exit Do
        end if
        Response.Write "<LI>"+ItemValue
        Response.Write "<INPUT TYPE=hidden NAME="+ItemName+_
          " VALUE="+dq+ItemValue+dq+">"
        ItemNo = ItemNo + 1
    Loop
    %>
    </UL>
    
    Order more items:
    <BLOCKQUOTE>
        <INPUT TYPE=radio NAME=<%=ItemName%> VALUE="CD-001">Order CD<BR>
        <INPUT TYPE=radio NAME=<%=ItemName%> VALUE="Book:Manual">
    	Order Book<BR>
        <INPUT TYPE=radio NAME=<%=ItemName%> VALUE="dcd software">
    	Order Software<BR>
        <P>
        <INPUT TYPE="submit" VALUE="Order selected item">
    </BLOCKQUOTE>
    </FORM>

    This example does the same job as the 'URL parameters' example above.  It gives the user a list of three items to buy.  It keeps accumulating ordered items in the saved state and displays the order to the user.

    The items are stored in hidden form variables named Item1, Item2, etc.  The script keeps calling itself with each new order item added onto the list as the next free ItemX variable.

    The script starts off by looping through all the available ItemX form variables.  As well as displaying each item on the page, the script outputs the item as a hidden form variable so that the current state is remembered on the displayed page.

    Finally the script displays the available items using a set of radio buttons and a Submit form button labelled "Order selected item".  In this case the radio buttons return the selection in exactly the desired format so that the chosen item is added to the order with no extra processing.  In other cases you might need to perform error checking on input data.


    Conclusion
    For CDs as well as online web sites, the aim of some sites is to obtain permanent data in the form of orders in your online database.  In addition, CDs and online sites usually want to remember user information permanently between sessions.

    However the items in an order need not be stored online as the order is built up.  Instead the list of items ordered so far could be stored in temporary storage.  When complete, the list of ordered items could be transferred to the online database in one transaction.
    Online sites could build up an order in the server database.  However even here it might make sense to use temporary storage to avoid trips to the database.  For CDs, the whole point is to build up an order offline, so temporary storage must be used until the last moment when the order is uploaded to the server database.

    This page has discussed various methods of saving state, ie temporary or semi-permanent storage.  On a CD, files can be used to store information on a permanent or semi-permanent basis.  Use files for long term data, ie user information.  With careful use, files can also be used to build up one or more orders.

    All the other methods discussed here are intrinsically temporary, or semi-permanent at best.  Information in cookies is saved permanently if the user's browser supports them, at least until the user clears the cookies.  The other methods (sessions, URL parameters and Hidden form variables) are very temporary in nature and the saved data is lost after a timeout or restart (although URL parameter state could be bookmarked).

    Assuming you want temporary storage while building up an order, you will have to choose one of the above methods.  Your choice will partly be determined by how you want your application to look and feel to the user.  Some methods, such as cookies and sessions, are inherently risky because the user's browser may not support them, or be switched off.  This leaves the URL parameters method which has the advantage of making a page bookmarkable.  Or the Hidden form variables method which might be cleanest.

    (If you are writing online scripts and are concerned about security, using session objects keeps sensitive data on your server. All the other methods store information on the user's computer.)

    The file and cookie methods have the advantage that information will be maintained between sessions, unlike sessions, URL parameters and Hidden form variables.

    If possible it is desirable to use a method that avoids the Back problem, where a user presses the Back button and expects an action to be undone.  The URL parameters and Hidden form variables methods usually avoid this problem.

    For CDs, our recommended approach is to use files for permanent data and Hidden form variables for temporary data.  Don't forget to clear up after you, ie delete temporary files when they are no longer needed.


    Links
    This article online by Mike Alvarez has some useful suggestions for structuring ASP pages and maintaining state: http://www.devx.com/upload/free/features/entdev/1999/07jul99/fe0799/fe0799.asp.
    "But if your Web site has to scale to even hundreds of users, you should be hardly using [the session object] at all."


    © Copyright 2000-2007 PHD Computer Consultants Ltd