Session State

ASP.NET provides the cross-request state information (shopping carts, data scrolling, and so on) infrastructure that Web applications require, with built-in session-state functionality that enables you to take the following actions:

  • Automatically identify and classify requests coming from a single browser client into a logical application session on the server.

  • Store session-scoped data on the server for use across multiple browser requests.

  • Raise appropriate session-lifetime management events (Session_OnStart, Session_OnEnd, and so on) that can be handled in application code.

    Note   The Session_OnEnd event is supported only the in-process session-state mode. This event is not raised if you use State Server or SQL Server modes.

  • Automatically release session data if the browser does not revisit an application within a specified time-out period.

This topic provides an overview of session state, describes how active ASP.NET sessions are identified and tracked, explains the session-state store and general structure, and concludes with a high-level code example.

Session State Overview

HTTP is a stateless protocol, which means that it does not automatically indicate whether a sequence of requests is all from the same client or even whether a single browser instance is still actively viewing a page or site. As a result, building Web applications that need to maintain some cross-request state information (shopping carts, data scrolling, and so on) can be extremely challenging without additional infrastructure help.

ASP.NET provides the following support for sessions:

  • A session-state facility that is easy to use, familiar to ASP developers, and consistent with other .NET Framework APIs.
  • A reliable session-state facility that can survive Internet Information Services (IIS) restarts and worker-process restarts without losing session data.
  • A scalable session-state facility that can be used in both Web farm (multicomputer) and Web garden (multiprocess) scenarios and that enables administrators to allocate more processors to a Web application to improve its scalability.
  • A session-state facility that works with browsers that do not support HTTP cookies.
  • A throughput equivalent to that of ASP (or better) for core session-state scenarios (50/50 read/write when putting items into shopping carts, modifying last page visited, validating credit card details, and so on).

Session state, however, does not persist across Web application boundaries. If a Web application switches to another application during execution, the session information is not available to the new application.

Identifying a Session

Each active ASP.NET session is identified and tracked using a 120-bit SessionID string containing only the ASCII characters that are allowed in URLs. SessionID values are generated using an algorithm that guarantees uniqueness so that sessions do not collide, and randomness so that a malicious user cannot use a new SessionID to calculate the SessionID of an existing session.

The SessionID strings are communicated across client-server requests either by means of an HTTP cookie or a modified URL with the SessionID string embedded, depending on how you configure the application settings.

Session-State Store

ASP.NET provides a simple and easy-to-use session-state model that you can use to store arbitrary data and objects across multiple Web requests. It accomplishes this using a dictionary-based, in-memory cache of object references that live within the IIS process. When using the in-process session-state mode consider the following limitations:

  • When using the in-process session-state mode, session-state data is lost if aspnet_wp.exe or the application domain restarts. These restarts commonly occur in the following circumstances:
    • Setting an attribute in the <processModel> element of the application's Web.config file that causes a new process to start when a condition is met, such as memoryLimit.
    • The Global.asax or Web.config file is modified.
    • Changes to the \Bin directory of the Web application.
    • Antivirus software scans and modifies the Global.asax file, the Web.config file, or a file in the \Bin directory of the Web application.    
  • If you enable Web garden mode in the <processModel> element of the application's Web.config file, do not use in-process session-state mode. Otherwise, random data loss can occur.

Instead of keeping live objects, the .NET State Server simply stores session state in memory when in out-of-proc mode. In this mode the worker process talks directly to the State Server. In SQL mode, session states are stored in a SQL Server database and the worker process talks directly to SQL. The ASP.NET worker processes are then able to take advantage of this simple storage service by serializing and saving (using .NET serialization services) all objects within a client's Session collection at the end of each Web request. When the client revisits the server, the relevant ASP.NET worker process retrieves these objects from the State Server as binary streams, deserializes them into live instances, and places them back into a new Session collection object exposed to the request handler.

In SQL mode, session state can also be configured to work in a failover cluster. A failover cluster is two or more identical, redundant Web servers that store their session data on a separate computer in a SQL Server database. For information on how to set up this configuration, see Configuring SQL Server Mode.

By cleanly separating the storage of session data from the application's use of it, ASP.NET supports several powerful scenarios that were unavailable with earlier versions of ASP:

  • Recovery from application crashes, because the memory used for session state is not within the ASP.NET worker process.

    Because all state is stored separately from an individual worker process, it is not lost if the process crashes due to an access violation or is forcibly restarted by the IIS Admin Service in the event of a deadlock or memory leak.

  • Partitioning an application across multiple worker processes.

    Because all state is stored separately from worker processes, you can cleanly partition an application across multiple processes. Such partitioning can dramatically improve both the availability and the scalability of an application on multiple-process computers. Moreover, because it associates each worker process with a single computer, ASP.NET is able to eliminate cross-processor lock contention, one of the major scalability bottlenecks in earlier versions of ASP.

  • Partitioning an application across multiple Web farm computers.

    Because all state is stored separately from worker processes, you can partition an application across multiple worker processes running on multiple computers. The model for communicating state between a worker process and a state service running on different computers is almost the same as that for processes and servers running on the same computer. In either case there can only be one State Server per Web farm.

Session State Structure

ASP.NET-based applications use an event-based execution organization to enable multiple .NET Framework class modules to participate in the processing of a single Web request.

The SessionState Module

The .NET Framework implements session state through the SessionStateModule class (derived from IHttpModule), which participates in the execution of each request received by a .NET-based application. The SessionStateModule is responsible for either generating or obtaining unique SessionID strings and for storing and retrieving state data from an external state provider.

Session State Collections

The SessionState class exposes two state collections: Contents and StaticObjects. The Contents collection exposes all variable items that have been added to the session-state collection directly through code. For example:

' Visual Basic code from within a page, a handler, or Global.asax.
Session("Message") = "MyMsg"
Session("AppStartTime") = Now
[C#]
// C# code from within a page, a handler, or Global.asax.
Session["Message"] = "MyMsg";
Session["AppStartTime"] = DateTime.Now;

For compatibility with earlier versions of ASP, these values also can be accessed through a Contents property on the application object, as in the following example.

' Visual Basic code from within a page, a handler, or Global.asax.
Session.Contents("Message") = "MyMsg"
Session.Contents("AppStartTime") = Now
[C#]
// C# code from within a page, a handler, or Global.asax.
Session.Contents["Message"] = "MyMsg";
Session.Contents["AppStartTime"] = DateTime.Now;

The StaticObjects collection exposes all variable items that have been added to the session-state collection through <object runat="server"> tags with the scope of "Session" within the Global.asax file. For example:

' Global.asax definition.
<OBJECT RUNAT="SERVER" SCOPE="SESSION" ID="MyInfo" PROGID="Scripting.Dictionary">
</OBJECT>

Objects cannot be added to the StaticObjects collection from anywhere else within an ASP.NET application. The collection throws a NotSupportedException if users attempt to add objects directly through code.

Note   The ASP.NET page compiler automatically injects member references into all objects stored within the StaticObjects collection at page compilation time.

Page developers can access Session objects directly at page request time without having to go through the StaticObjects collection, as shown in the following example:

<html>
   </body>
      Number of entries: <%= MyInfo.Count %>
   <body>
</html>

Session State Configuration and Startup

There are three session state modes in ASP.NET. You can choose between in-process, State Server, and SQL Server. Regardless of which mode you choose, the basic configuration process is the same.

ASP.NET configures session state in two stages. First, the session state module is inserted in the HTTP request. By default this is done at the root of the configuration hierarchy in the computer-wide Machine.config file.

The following example shows a sample entry in the Machine.config file. For the configuration file to work correctly, you must provide the fully qualified assembly name to the appropriate version of the System.Web.SessionState.SessionStateModule assembly. This version is usually the version that is associated with the .NET Framework version used by your application. For information on how to obtain the fully qualified assembly name, see Assembly Names.

<httpmodules>
   ...
    <!-- You must supply a valid fully qualified assembly name here. -->
    <!-- For this example to work correctly, the version number for -->
    <!-- the referenced assemby must match the version installed on -->
    <!-- your computer by the .NET Framework. -->
    <add name="sessionState" type="System.Web.SessionState.SessionStateModule, Version=1.0.3300.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" />
   ...
</httpmodules>

Then, depending on which session state mode you want to use, set the appropriate session state service attributes in the <sessionState> configuration element.

Configuring In-process Mode

In-process is the default session state mode. To use in-process mode, set the mode attribute of the <sessionState> element to Inproc.

The following shows a sample configuration setting for in-process mode.

<configuration>
    <system.web>
        <sessionState mode="Inproc"
                      cookieless="false"
                      timeout="20"/>
        </sessionState>
    </system.web>
</configuration>

Configuring State Server Mode

To use State Server, you must first make sure ASP.NET state service is running on the remote server used for the session store. This service is installed with ASP.NET and Visual Studio .NET at the following location:

systemroot\Microsoft.NET\Framework\versionNumber\aspnet_state.exe

Next, set the mode attribute of the <sessionState> element to StateServer in the Web.config file of the application. Finally, set the connectionString attribute to **tcpip=serverName:**portNumber.

The following shows a sample configuration setting for State Server mode.

<configuration>
    <system.web>
        <sessionState mode="StateServer"
                      stateConnectionString="tcpip=dataserver:42424"
                      cookieless="false"
                      timeout="20"/>
        </sessionState>
    </system.web>
</configuration>

Configuring SQL Server Mode

To use SQL Server, first run either InstallSqlState.sql or InstallPersistSqlState.sql on the computer with SQL Server that will store the session state. Both scripts create a database called ASPState that includes several stored procedures. The difference between the scripts is where the ASPStateTempApplications and ASPStateTempSessions tables are placed. The InstallSqlState.sql script adds these tables to the TempDB database, which loses session data if the computer is restarted. The InstallPersistSqlState.sql script, on the other hand, adds these tables to the ASPState database, which allows session data to be retained when the computer is restarted.

Both of these script files are installed by default at the following location:

systemroot\Microsoft.NET\Framework\versionNumber

Next, set the mode attribute of the <sessionState> element to SQLServer in the Web.config file of the application. Finally, set the sqlConnectionString attribute to Integrated Security=SSPI;data source=serverName;.

The following shows a sample configuration setting for SQL Server mode.

<configuration>
    <system.web>
        <sessionState mode="SQLServer"
                      sqlConnectionString=" Integrated Security=SSPI;data source=dataserver;"
                      cookieless="false"
                      timeout="20"/>
        </sessionState>
    </system.web>
</configuration>

In SQL Server mode, session state can also be configured to work in a failover cluster. A failover cluster is two or more identical, redundant Web servers that store their session data on a separate computer in a SQL Server database. If a Web server fails, another server in the cluster can take over and serve requests without session data loss. To configure a failover cluster, set the <machinekey> element in the Web.config file of the Web servers to the same value. Then set the SQL connection string of the Web servers to point to the SQL Server database on the computer that stores the session data.

High-Level Code Example

The following example shows how to access existing session-state data in a read-only manner to dynamically generate a page containing user information and personal stock portfolio information.

<%@ Language=VB EnableSessionState=true %>
<html>
   <head>
      <script runat="server">
         Sub Page_Load(ByVal Sender as Object, ByVal E as EventArgs)
              ' Obtain data table of user's personal stock data.
              Dim MyStocks as DataTable
              Dim Stock as DataRow
              MyStocks = _
                 CType(Session("PersonalStockData"), DataTable)
              ' Update HTML output with session values.
              Name.InnerText = Session("FirstName").ToString()
              SpouseVal.InnerText = Session("SpouseName").ToString()
              For Each Stock In MyStocks.Rows
                 StockList.AddItem(Stock("Symbol") & ": " & Stock("Name"))
              Next
         End Sub
      </script>
   </head>
   <body>
      Hi <span id="Name" runat=server/>, your spouse is: <span id="SpouseVal" runat="server"/>.
      Here are the stocks you and your spouse currently own:
      <acme:listbox id="StockList" runat="server">
         <! — List box is dynamically populated from code. -->
      </acme:listbox>
   </body>
</html>
[C#]
<%@ Language=C# EnableSessionState=true %>
<html>
   <head>
      <script runat=server>
         void Page_Load(Object Sender, EventArgs E) {
              // Obtain data table of user's personal stock data.
              DataTable MyStocks =
                 (DataTable)Session["PersonalStockData"];
              // Update HTML output with session values.
              Name.InnerText = Session["FirstName"].ToString();
              SpouseVal.InnerText = Session["SpouseName"].ToString();
              foreach (DataRow Stock in MyStocks.Rows) {
                 StockList.AddItem(Stock["Symbol"] + ": "
                                 + Stock["Name"]);
              }
         }
      </script>
   </head>
   <body>
      Hi <span id="Name" runat="server"/>, your spouse is: <span id="SpouseVal" runat="server"/>.
      Here are the stocks you and your spouse currently own:
      <acme:listbox id="StockList" runat="server">
         <! — List box is dynamically populated from code. -->
      </acme:listbox>
   </body>
</html>

See Also

ASP.NET State Management