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
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:
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?
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:
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:
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:
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.
|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.