As challenging as it can be to manage application-state information, the statelessness of HTTP makes maintaining state for individual users even more challenging. First, the Web server needs to be able to identify a series of requests as coming from a single user. Then the Web server must associate these requests with the state information for that specific user.
In classic ASP, these challenges were met with the intrinsic Session object. Each user had his or her own session instance, identified by a session ID, which could be used to store per-user state information. The session ID, a unique generated value for that run of the application, was then stored in a cookie on the client machine. It would then be passed back to the server with each subsequent request, allowing the server to identify the session associated with that user.
Unfortunately, session state in classic ASP had several inherent limitations that made it less than ideal, particularly for applications requiring high scalability. These included the following:
Web farms In classic ASP, session state could not be scaled across multiple servers in a Web farm, limiting its usefulness in high-scalability situations.
Durability In classic ASP, session state would be destroyed by a server restart or crash. This made it a poor choice for such uses as shopping carts, whose contents should survive such events.
Cookie reliance Classic ASP offered no inherent solution for supporting session state with browsers that could not or would not accept cookies. Although aftermarket solutions were available, they often involved unacceptable performance trade-offs.
ASP.NET solves each of these limitations, providing per-user state storage that’s scalable, reliable, and available on browsers that don’t support cookies (or for users who choose not to accept cookies). For more information on the available options for ASP.NET session state and how they solve these limitations, see “Configuring Session State Storage” later in this chapter.
As with the ASP.NET Application object, the ASP.NET Session object is exposed as a property of the Page class, from which all ASP.NET pages inherit. This allows direct access to the Session object.
Session["MySessionVar"] = "MyValue" MyLocalVar = Session["MySessionVar"];
The Session object functionality is provided by the HttpSessionState class, an instance of which is created for each user session that session state has been enabled for.
Like the Application object, the Session object exposes a Contents collection for backward-compatibility with classic ASP. Any values stored in the HttpSessionState collection can also be accessed through the Contents collection alias.
Session.Contents["MySessionVar"] = "MyValue" MyLocalVar = Session.Contents["MySessionVar"];
The Session collection can also be used to store references to object instances, using similar syntax to that used to store object references at the application level. These objects then become part of the Session object’s StaticObjects collection and can be referenced in your ASP.NET Web Form pages by referring to the id attribute associated with the object.
// Global.asa <object runat="server" id="MyClassInstance" class="MyClassName"  scope="Session"> </object> // Web Forms pag Response.Write("Value = " + MyClassInstance.MyValue);
Table 4-3 lists some of the additional properties and methods provided by the Session object to retrieve and manipulate Session collection values.
Method or Property |
Use |
---|---|
Keys property |
Returns a collection of all of the keys by which Session collection values can be accessed. |
Count property |
Returns the number of objects stored in the Session collection. |
SessionID property |
Returns a string containing the session ID for the current session. |
Timeout property |
Returns an Integer value representing the current Session Timeout setting. |
Abandon method |
Destroys the current user session. |
Clear method |
Removes all items from the Session collection. |
RemoveAt method |
Removes a specific item from the Session collection, based on its index within the collection. |
ToString method |
Returns a string that represents an item in the Session collection. Useful when a string value is required rather than an object reference. |
Unlike application state, which is always available to Web applications, session state must be enabled before you can use it. The good news is that the default configuration file at the server level (machine.config) automatically enables session state, so you don’t need to take any additional steps to enable it. Nonetheless, you should be aware that the settings in the machine.config configuration file, as well as in the Web.config configuration file for your application, determine whether session state is enabled or disabled. The pertinent settings are detailed in Appendix B.
If you want to delay the creation of a session until it’s necessary, you can add the EnableSessionState attribute to the @ Page directive of all pages not requiring session state:
<%@ Page EnableSessionState="False" %>
Any attempt to access the Session object from a page on which enableSessionState has been set to False will result in an error. Note that once a session has been created for a given user, setting the enableSessionState attribute to False doesn’t result in the destruction of the existing session. It only prevents access to the Session object from that page.
You can set the session state to read-only for a given page by setting the enableSessionState attribute to ReadOnly. Any attempts to update values stored in the Session collection from that page will be ignored.
Microsoft Visual Studio .NET makes it even easier to enable (or delay enabling) session state in your applications by exposing the enableSessionState attribute as a property of the Document object. This allows you to view and modify its value using the Visual Studio .NET Properties window, shown in the following illustration.
To change its setting, select the enableSessionState entry in the Properties window, click the drop-down list containing the values, and select the desired value. This will update the @ Page directive that appears in the .aspx page currently being edited.
Just as with application state, using Visual Studio .NET to read and write session state is easy. The output for the following example will be written into an ASP.NET Label server control.
Open Visual Studio .NET. Reopen the Chapter_04 project created earlier.
Add a new page to the project by right-clicking the project root in Solution Explorer, and then selecting Add, then Add WebForm from the context menu. When prompted, change the name of the file from WebForm2.aspx to SessionState.aspx and click Open.
Add a label control to the page.
With the label control selected, change the ID of the label from Label1 to Message.
From the View menu, select Code or press F7 to open the code editor.
Locate the Page_Load method, and add the following code:
//Initialize looping variabl int loopCount = 0 Session["TestString"] = "Hello" Session.Add("TestNumber", 43) Message.Text="There are " + Session.Count.ToString() " items in the Session collection.<br/>" while (loopCount < Session.Count Message.Text += "Session(" + loopCount.ToString() +  ") = " + Session[loopCount] + "<br/>" loopCount += 1 }
Save the application by using the File, Save All menu option (or by pressing Ctrl+Shift+S).
From the Build menu, select Build Chapter_04 to build the application.
Test the page by right-clicking SessionState.aspx and selecting View In Browser. The resulting screen should look similar to the following illustration.
Session state’s ease of use makes it easy to overuse or abuse. Table 4-4 lists examples of when you might or might not want to store information in session state, as well as alternatives for storing such information.
State Information |
Issues |
Alternative |
---|---|---|
User-specific settings |
Depending on how frequently these values are accessed, session state might not be the most efficient way to store these settings. |
For infrequently accessed values, consider storing user- specific settings in a database. |
Datasets containing frequently read data |
Caching frequently used data at the session level can be efficient, but there’s little automatic control over when the data is refreshed. It’s very important to consider the cost of storing a dataset for each user session over the cost of retrieving the dataset from the database. |
Use the ASP.NET cache engine to cache expensive or frequently read data. The ASP.NET cache engine provides fine-grained control over how and when data is refreshed or purged from the cache. See Chapter 12 for more information on caching. |
References to object instances |
Storing references to objects with the wrong threading model (such as legacy COM components created with Visual Basic) can severely affect the scalability of an application. It’s important to consider the cost of storing a reference to an object for each user session. |
If it’s absolutely necessary to store a reference to an object instance, ensure that the class from which the object is created is thread safe. |
Thanks to a number of new features in ASP.NET, the primary limitation of session state in ASP.NET is that of memory. As with application state, session state is limited by the memory available on the Web server. Once the available physical memory on the Web server has been exhausted, information will be stored in much slower virtual memory.