Figure 2.5
Output of Listing 2.1.5 when viewed through a browser.
If you've worked with classic ASP, you are likely familiar with the concept of session-level variables. These variables are defined on a per-user basis and last for the duration of the user's visit to the site. These variables are synonymous with global variables in that their values can be accessed across multiple ASP pages. Session-level variables, which are discussed in greater detail in Chapter 14, "Managing State," are a simple way to maintain state on a per-user basis. Because we want the user's navigation history stack to persist as the user bounces around our site, we will store the Stack class instance in a session-level variable.
To implement a navigation history stack as a session-level variable, we must make sure that we have created such a variable before trying to reference it. Keep in mind that when a visitor first comes to our site and visits that first page, the session-level variable will not be instantiated. Therefore, on each page, before we refer to the navigation history stack, it is essential that we check to ensure that our session-variable, Session["History"], has been assigned to an instance of the Stack class.
--------------------------------------------------------------------------------
Note
To access a session variable using C#, the braces are used around the session variable name. For example, to retrieve the value of the History session variable with C# we'd use:
Session["History"]
With VB.NET, however, parentheses are used in place of the brackets:
Session("History")
--------------------------------------------------------------------------------
Line 6 in Listing 2.1.5 checks Session["History"] to determine whether it references a Stack object instance. If Session["History"] has not been assigned an object instance, it will equal null (or Nothing, in VB). If Session["History"] is null, we need to set it to a newly created instance of the Stack class (line 9).
However, if Session["History"] is not null, we know that the user has already visited at least one other page on our site. Therefore, we can display the contents of the Session["History"] Stack. This is accomplished in lines 12 through 17 with the use of an enumerator. We'll discuss iteration through collections via enumerators in the next section, "Similarities Among the Collection Types." With C#, as opposed to VB, explicit casting must be done when working with the Session object. For example, on line 13, before we can call the GetEnumerator() method (a method of the Stack class), we must cast the Session["History"] variable to a Stack:
// C# code must use an explicit cast
IEnumerator enumHistory = ((Stack) Session["History"]).GetEnumerator();
'VB code, however, does not require an explicit cast
Dim enumHistory As IEnumerator = Session("History").GetEnumerator()
With VB, however, such a cast is not necessary. Casting issues with the Session object are discussed in more detail in Chapter 14.
After either creating a new session-level Stack instance or displaying the Stack's contents, we're ready to add the current URL to the navigation history stack. This could be accomplished with the following simple line of code:
((Stack) Session["History"]).Push(Request.Url.PathAndQuery);
However, if the user refreshed the current page, it would, again, get added to the navigation history stack. It would be nice not to have the same page repeatedly appear in the navigation history stack. Therefore, on line 23, we