Maintaining Persistent Information on the Web
Yesterday, Day 10, "Working with the Request Object," we discussed how the Request and
Response objects could be used to read and write cookies on clients' computers. Cookies, which
can save small bits of simple information on the user's computer, can be used to
maintain state over long periods of time. Although cookies offer an easy way to persist
information over time, they do have limitations.
To combat these shortcomings, ASP provides two built-in objects: the Session object and
the Application object. The Session object is designed to maintain state for each
visitor to your Web site for the duration of his or her visit. The Application object
provides a mechanism to persist non-user-specific information for great lengths of time. By using these two objects, you can maintain state across your Web site.
The Session and Application objects are easier to use than cookies. Because both the
Session and Application objects can save arrays and objects, something cookies can't
do, many developers prefer to use these two objects in place of using cookies. There is
one caveat, though: Because the Session and Application objects save their information
in the Web server's memory, these two objects, if overused, can lead to major
performance degradation on the Web server. Advantages and disadvantages of using the Session
and Application objects are discussed later today in the sections "The Session Object"
and "The Application Object," respectively.
Today, you will learn the following:
Different methods of maintaining state on the Internet
What the Session object is
Advantages and disadvantages of the Session object
What the Application object is
Advantages and disadvantages of the Application object
How to initialize the Session and Application objects
What Global.asa is, and what purpose it serves
It's a Fact: The Web Is Stateless
Have you ever wondered what, exactly, happens when you type in a URL into your browser's
Address bar? After yesterday, you probably have a better understanding of the detailed
conversation that goes on between the client and the Web server. Recall from Day 1, "Getting
Started with Active Server Pages," that the Internet is based on a client-server model,
where your Web browser is the client, and the Web server is the server. Figure 11.1
provides a graphical representation of the client-server model.
In the client-server model, the client opens up a channel of communication with the
server and requests a resource. The server receives the request, locates the resource
being requested, and sends it to the client, closing the channel of communication.
This is an impersonal transaction between the client and server. The server does not
keep open its channel of communication with the client. The server is not concerned
with who it has talked to recently, what it has sent recently, or what it thinks a
particular client will request next. The server does one job, and it does it well:
wait for a request from the client and then process that request.
Due to this impersonal communication between a Web browser and a Web server, user
information is not persisted from one request to another. Imagine that you wanted to
create a form that would query the user for his or her name. After the user entered his
or her name, it would be nice to display a personal greeting on each Web page on your
Web site. To display a personalized welcome message, you would need some way of
remembering each user's name. Saving such information is referred to as maintaining
state, or persisting state.
Ways to Maintain State
Because the client-server model does not make maintaining state inherently easy, you must
examine some advanced techniques to maintain state. No doubt you'll find that some of
the methods that can be used to persist state seem rather obtuse.
Later today, in the section "Passing Information Through the Querystring," we'll look
at how to maintain state by sending state information through the querystring. Using
this approach can lead to a syntactical headache, and you may find yourself wondering why
maintaining state through the querystring appears to be so confusing. Keep in mind that
the client-server model does not lend itself to state persistence; therefore, some methods
of maintaining state can be unwieldy.
Thankfully, ASP provides some built-in objects and collections to help maintain state. The
Cookies collection, which was discussed yesterday, can be used to maintain simple state
information over lengthy periods of time. The Session and Application objects, discussed later
today in the sections "The Session Object" and "The Application Object," can also be
used to maintain state. By using Active Server Pages, state maintenance is easier to
understand.
You are going to examine other, non-ASP specific approaches as well, though. Each method of
maintaining state has its time and place. Being knowledgeable on each of these methods
enables you to make the best decision regarding how to implement state persistence.
Passing Information Through the Querystring
When you only need to maintain state for the duration of a user's visit to your site,
you have a couple of options. If you only need to save simple data types, a series of
cookies will suffice. If more complex data types need to be used, you can store this
information through the Session object. (The Session object uses cookies to uniquely identify
each visitor to your site. We discuss the inner workings of the Session object later
today in "The Session Object.") The drawback to both these methods is that if the user
has cookies disabled, your Web site will appear to be stateless.
Although the vast majority of Web surfers today have cookies enabled, if it is essential
that your site maintain state for all your visitors, cookies and session variables just
won't do. If this is ever the case, and all you need to persist is simple data types,
you can store your state information in the querystring.
Recall from Day 9, "Collecting the Form Information," that the Request object can process
information from the querystring if it is formatted in name/value pairs, with each name
and value separated by an equals sign (=), and each name/value pair separated from one
another by an ampersand (&). For example, a querystring that contained my name and age
might look like:
?Name=Scott&Age=21
Imagine that when users first come to your Web site, you ask them to enter their name.
You would need to create a form that contained a text box where users could enter their
names, and the form also would need a submit button. Listing 11.1 shows the HTML needed
to create such a form.
Listing 11.1 - What Is Your Name?
1: <FORM METHOD=GET ACTION="Welcome.asp">
2: What is your name?<BR>
3: <INPUT TYPE=TEXT NAME=Name>
4: <P>
5: <INPUT TYPE=SUBMIT VALUE="Login">
6: </FORM>
Line 1 in Listing 11.1 creates the form with the METHOD property set to GET. This sends
the results of the form through the querystring. The code in Listing 11.1 also creates
a text box for the users to enter their names (line 3) and a submit button (line 5).
Figure 11.2 shows the code for Listing 11.1 when viewed through a browser. I have taken
the liberty to enter my name in the text box.
When the form created in Listing 11.1 is submitted, Welcome.asp, the form processing
script, is called. Welcome.asp is passed the name of the user through the querystring.
The information you want to persist is the user's name, which is in the querystring. It's
obvious that Welcome.asp can ascertain the user's name (via Request.QueryString("Name")),
but how can you ensure that other Web pages on your site will have access to this information?
The secret is to make sure that each and every ASP page contains the same querystring that
Welcome.asp contains. If you can ensure uniformity of the querystring across your Web site,
then each ASP page that needed to obtain the user's name could do so by using
Request.QueryString("Name"). The question now is how can each Web page on your site have the
same querystring as Welcome.asp.
Day 9 discussed how you could pass information through the querystring using hyperlinks. A
hyperlink is created with the following syntax:
<A HREF="URL">The title of the link</A>
To pass the querystring to the URL, you need to append a question mark (?) followed by
the querystring. The following code would create a hyperlink titled Click Me that would
pass to ClickMe.asp the querystring Name=Scott:
<A HREF="ClickMe.asp?Name=Scott">Click Me</A>
Creating hyperlinks with a static querystring, however, will not suffice. You need the
hyperlink URL's querystring to be equal to the current querystring in Welcome.asp.
This way, you will maintain state for each user. Recall from Day 9 that for an ASP
page, the entire, current querystring can be read using Request.QueryString. You can create
all your hyperlinks so that they pass the current querystring by using the following
syntax:
The preceding syntax will create a hyperlink that, when clicked, will pass the ASP page
somePage.asp the current querystring. Recall that when an ASP page is requested from a
Web server, all the ASP code is processed on the server[md]the client is sent pure HTML.
The client does not receive:
Rather, the value of Request.QueryString is inserted after somePage.asp?. For example, say
that Welcome.asp's querystring is Name=James. If you create a hyperlink in Welcome.asp
using the following syntax:
the Web browser, when visiting Welcome.asp, would receive the HTML as follows:
<A HREF="somePage.asp?Name=James">Click Me</A>
Now that you have sent the querystring Welcome.asp you received to somePage.asp,
somePage.asp can access the user's name with Request.QueryString("Name"). Listing 11.1
created a form where the user could enter her name. This form, when submitted, sent the
user's name to Welcome.asp through the querystring. All the hyperlinks in Welcome.asp need
to pass the current querystring to their respective URLs. The code for Welcome.asp
can be seen in Listing 11.2.
Listing 11.2 - Inserting the Current Querystring into all the Hyperlinks
Welcome.asp starts by reading in the user's name (line 6). When using the querystring
to maintain state, all the ASP pages on your Web site should start out by reading the
persistent information; in this case, the user's name. Line 10 displays a personalized
greeting, and lines 13 through 16 create a series of hyperlinks. Notice that each
hyperlink passes its URL the current querystring using Request.QueryString. Figure 11.3
shows Welcome.asp when viewed through a browser.
You might be wondering what the HTML the browser received from Welcome.asp looked like.
Listing 11.3 reveals the exact HTML received by the browser when Welcome.asp was sent
Name=Scott in the querystring.
Listing 11.3 - The HTML Received by the Browser When Visiting Welcome.asp
Notice in lines 6 through 9 that the querystring, Name=Scott, was appended to the URL
in the hyperlink. This ensures that when any of these hyperlinks are clicked, it will be sent
the current URL. This ensures that the user's name will persist on the next ASP page on
your site that the user reaches via a hyperlink.
Note
To have the user's name be maintained throughout your Web pages, every page must be
passed the user's name through the querystring. To ensure that every page is passed the
user's name through the querystring, every hyperlink on every ASP page must have
?<%=Request.QueryString%> appended to it! This may seem like a burden and a
headache - it is.
The querystring solution for maintaining state is not without pitfalls. Imagine that a
user entered her information and surfed through a couple of pages on your site by
clicking the hyperlinks[md]so far, so good. Now, imagine that the user wants to visit a
specific URL on your site, so she types it in the Address bar. The user will reach that
URL without having passed the persistent information. At this point, state has been lost. The
querystring method also is a development headache. If you forget to append the
querystring to a hyperlink's URL, when that hyperlink is clicked, state will be lost
because the querystring won't contain the maintained information. Also, the querystring method
cannot persist objects because it would be impossible to express an object via the
querystring. Finally, keep in mind that the querystring method can only persist data
while the user is on your Web site. The second the user leaves your site, state is lost.
The querystring approach, despite its disadvantages, will always work with any browser, whether
or not the user has disabled cookies. Also, the querystring approach is free of
the performance concerns that plague you when dealing with the Session object, which
is discussed in length later today in "The Session Object." If, for the duration of a
user's visit, you must have information persisted, regardless of whether the user has
cookies enabled, the querystring approach is the way to go.