Home     Products      Support      Corporate     Sign In 
Support Knowledge Base, Article 676
Product
General
Title
State Maintenance in ASP.NET
Solution

State Maintenance in ASP.NET

by Craig Utley

In traditional Active Server Pages (ASP) applications, there was a great amount of debate about how best to maintain state on the server. Maintaining state in Web applications is an incredibly common task, and it is critical to building usable Web applications. After all, without being able to maintain state, your Web applications would be nothing more than brochure-ware. If you want to have such functionality as allowing people to participate in threaded discussion groups, order products, or see only the areas to which they have access, you will have to use some mechanism for maintaining state information.

ASP applications could benefit from automatic server-side state management, but there were some problems with ASP's implementation that caused many developers to shy away from Microsoft's built-in session state mechanism. This article will discuss how ASP.NET seeks to overcome the ASP limitations with enhancements to server-side state management.

Maintaining State and HTTP

One of the reasons that state management is an issue is because HTTP is a stateless protocol. This means that when a client requests a page, the server responds with the data and then breaks the connection. If the client then requests another page, this request makes a new connection and a new page is served up. The server is seeing every request as a new request.

The stateless nature of HTTP makes maintaining state quite a challenge. With client/server applications, you log into a server and maintain a live connection. Maintaining state information is easy, because the server resources have validated you and keep connections open for you. After a certain period of inactivity, you may be logged out. HTTP doesn't have to log you out after a period of inactivity, because it shuts down the connection as soon as the response has been sent.

It is actually possible to maintain state using HTTP while not using the ASP or ASP.NET state management mechanisms. However, most of these require a significant amount of programming effort from the developer. You can use cookies, hidden fields, or modify the URLs, for example.

  1. The first option for maintaining state on your own is to use cookies. Cookies are files that are stored on the client, and allow you to store data between trips to the server. This means that you can record, in a client-side cookie, any items you need to remember, such as the items the shopper places in a shopping cart. When the user goes to check out, the Web application can request the values from the cookie, and the values are returned to the server, where they can populate the shopping cart and the checkout process can occur.

    Even if you are using client-side cookies, you must have a program of some sort on the server that retrieves the cookie values and processes them. In addition, some users, concerned about privacy, turn off the ability to accept cookies. This would destroy the cookie method as an option of maintaining state, and as you will see, this caused problems for ASP's state management.

  2. A second option is to write all data into the HTML page as hidden fields. HTML forms have a variety of field elements, and one of them is a hidden field. This hidden field can store data that is automatically passed back to the server with each form submission. Therefore, the data can be passed back to the server with each form submission. This approach often requires a significant coding effort on the server in order to insert the values in hidden fields in the HTML page that is going back to the client. You must also pass up all the values with each request from the client browser, as well as having server-side code that extracts the values from the hidden fields.

  3. Another approach is to add a unique identifier into all URLs on a page. When the user first visits your site, you generate a unique number for them, and on any page you send back, you modify the URLs to include the unique identifier. Then, with each subsequent request, they are passing this unique number back to the web server. On the Web server, you are maintaining the rest of their data, usually in a database.

With any of these approaches, it would be common to store some values in a database on the server side. For example, if you are just passing a unique identifier to the client in a cookie, in a hidden field, or by modifying the URLs, you may be storing the products in their shopping cart in a database on the server. For example, if you think about BarnesandNoble.com, they remember who you are when you return to their site, because your user name is stored in a cookie. However, any items in your wish list are stored in a database on the server side. This means that if you log into the site from another machine, you still have access to your wish list and other settings. Cookies are machine-specific, so information stored only in cookies is not available as the user moves from one machine to another.

State Maintenance with ASP.NET

Coding your own state management can be a challenge. There is a significant amount of effort in coordinating cookies, hidden fields, and database values. When Microsoft first released ASP, it allowed you to easily access some of Internet Information Services' (IIS) built-in objects for state maintenance. This made it very easy to maintain state, which was a boon for developers. However, there were some serious limitations to the ASP model, which ASP.NET seeks to remedy. We'll first examine ASP.NET's default state model, which works just as the ASP model does, and has the same limitations.

The three session state options for ASP.NET are:

  • In-Process
  • Out-Of-Process with a Windows Service
  • Out-Of-Process with SQL Server

All three options, however, use the same concept of an Application object, which will be examined first.

Web Applications and the Application Object

When using the term "application" it is often easy to see what is meant with traditional Windows application. There is typically a single executable file, along with several DLLs, and potentially a few additional files. With Web applications, however, there are typically a whole set of ASP, ASPX, and HTML pages, with the potential addition of CSS and other files. Unlike a Windows application, people can start by requesting any individual page, meaning that many Web applications require some coding effort to define a starting point.

An "application" in ASP/ASP.NET terms is defined by a virtual directory and its subdirectories. If you create a virtual directory in IIS, the physical directory to which that virtual directory points, and all of its subdirectories, contain that application. When the first ASP/ASPX page is accessed anywhere in that directory structure, IIS creates an Application object. This Application object then runs until IIS is shut down, which means that in theory, the Application object stays in memory forever. Regardless of how many users access the application, there is only one Application object per application.

The Application object can be used to hold variables that are accessible to all users of an application. If you think of traditional applications, a global variable is a variable accessible throughout the entire application, but the global variable in one instance of the application is not accessible to other instances of the application. However, with the Application object in ASP/ASP.NET, all users of an application have access to the same Application object. Therefore, if you have something that will be the same for all users, you can store it in the Application object. For example, if you visit BarnesandNoble.com, you will access the database of books. All users are connecting to the same database, and are likely using the same connection information as far as the name of the server and the login credentials. Therefore, it is not unusual to store the database connection string in the Application object, because it is the same for everyone. (Note: This is not saying that the database connection is made in the Application object, just that the connection string is stored there.)

ASP.NET In-Process State Maintenance

ASP.NET has three different ways to store session state, and the default method works just like session state in ASP. When the first user visits an ASPX page, the Application object is created. In addition, a Session object is created. While the Application object is accessible to all users of this Web application, the Session object is specific to a particular user. When the next user comes in requesting a page, a new Session object is created for that user (but they use the same Application object).

Because each Session object is tied to an individual user, you can place user-specific variables in the Session object. For example, storing the user's name at the Application object wouldn't make sense, but storing it at the Session object makes perfect sense. Because each user gets his or her own Session object, you can store their name, what they have ordered, and so forth.

Given that HTTP is a stateless protocol, it is important to understand how subsequent requests from the same user end up referencing the same Session object. When IIS creates a new Session object, it generates a unique number for it, called a SessionID. This SessionID is a property of the Session object, and the value is passed back to the client using the cookie mechanism. The cookie is never written to disk on the client; instead it is stored only in memory. With each subsequent request, however, the SessionID is passed from the client back to the server. IIS sees the SessionID that comes with the request, and sends that request back to the Session object with the same SessionID.

In an ASP/ASP.NET application, there is only one Application object. However, there is a Session object for each user. If you have a Web site with a lot of traffic, there can be many, many Session objects in memory. While the Application object never shuts down, however, the Session objects do shut down after a certain period of inactivity, the default of which is 20 minutes. The Session objects automatically start the timer as soon as they send a page to the client. If the client does not make a new request within the specified timeframe, the Session object will remove itself from memory. Any values in the Session object will be lost, although an event does fire before the Session object is destroyed, and you can use this event to save values if necessary.

While the default method for handling Session state works fine, it is not suitable for every case. There are three major issues with the default ASP.NET session state, and these are the same problems with ASP session state:

  1. By default, the Session object runs in the same process as IIS itself. If IIS is shut down (or the machine crashes), you lose all state in all sessions.

  2. In-Process session state is machine specific. If you are using a Web farm, you are doing so for scalability reasons. However, the Session object is only created on one machine within the farm. Subsequent user requests might get routed to a different server in order to help balance the load. If the user is directed to a different server, their Session object is not there, and no session state is available. To get around this, Web farms can force users to be routed to the same server with each request, but this can destroy some of the scalability you had hoped to gain by moving to a Web farm in the first place.

  3. The default implementation of session state requires cookies on the client. Even though these cookies are memory-only, some clients disable cookies. This destroys the ability to maintain state with Session objects, because the SessionID cannot be stored on the client. This means that each request is seen as a new user, and a new Session object is created on the server with each new request.

ASP.NET addresses each of these problems with new ways of working with session state.

Out-Of-Process with a Windows Service

With ASP.NET, you have two ways of storing state outside of the actual IIS process. You can store state in a Windows service or SQL Server, both of which run outside of IIS. Both have advantages and disadvantages.

Using the Windows service requires you to start the service. The service is in the file aspnet_state.exe, which is found in this path:

C:\Windows\Microsoft.NET\Framework\<version number>

You can start the service by typing:

net start aspnet_state

This will start the service, which will run in a separate process from IIS. Next, you simply configure your application to use the service (described in just a moment), and no coding changes are required to your application.

The advantage of using the Windows service is not just that the service runs out of process to IIS, but that a service running on a single machine can be used by multiple Web servers. This means that you gain the ability to use a Web farm but maintain state using the Session object. A request to any machine in the farm is routed to the machine running the service, and the state information is retrieved.

Out-Of-Process with SQL Server

If you are looking for the highest possible reliability, it is possible to store your session data in SQL Server. SQL Server is robust, thanks to the transaction log and two-phase commits. In addition, it is not uncommon to use SQL Server in a clustered environment, meaning that even if one computer failed, the other computers continue serving up SQL Server. With a Web farm and clustered SQL Servers, you would have the highest possible reliability for your Web application and state management.

In order to use SQL Server, you first need to run a script to create a SQL Server database. A file named InstallSqlState.sql is located in the following directory:

C:\Windows\Microsoft.NET\Framework\<version number>

Running this SQL file against SQL Server will create a new database called ASPState. However, no tables are created in this database; instead, only stored procedures are created. These stored procedures are used to create two tables in the tempdb database. Each session gets added as a row in a table called ASPStateTempSessions. The records have an Expires field and are cleared out periodically when IIS calls a stored procedure to remove expired sessions.

Configuring the Application

In order to configure your application to use one of the three methods of state management, you modify settings in the Web.config file. This is an XML file that is stored in the root directory of your Web application. There are a number of sections to the Web.config file, but you are interested in the <sessionState /> section. By default, the section looks like this:

<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString=
"data source=127.0.0.1;user id=sa;password="
cookieless="false"
timeout="20"
/>

In this section, the mode is the first thing you see. The default mode is InProc, which means that the Session object runs in the same process as IIS, just as it did in ASP. With InProc set, both stateConnectionString and sqlConnectionString are ignored. The cookieless and timeout values will be discussed in a moment, but are applicable to any of the three modes. Also note that these values are case-sensitive, and may change casing before Visual Studio .NET is released.

In order to use a Windows service to store session state, change the mode to StateServer. Once you specify that you are using a Windows service, the stateConnectionString is used to point to the server hosting the Windows service. By default, the IP address is 127.0.0.1, which is just the current machine. You can change this, but leave the port number at 42424, the port on which the service listens. By changing the IP address, you could point any number of instances of this application, running on multiple servers, to the same instance of the service.

In order to use SQL Server to store session state, change the mode to SQLServer. Now, the stateConnectionString is ignored again, but the sqlConnectionString is used. Again, the default is the local machine, with the infamous "sa/no password" setting for the user credentials. You can change this connection string, but note that it does not ask for an OLE DB provider or a database name. This is because it assumes SQL Server, and a database named ASPState. All this string needs is the server name and the login credentials.

Cookieless Session State

While the three modes all store session information differently on the server, the SessionID is still passed to the client using the cookie mechanism. However, not all clients support cookies, either due to security concerns or because of a less-capable browser. Regardless of the reason, it is possible to pass the SessionID to the client without using cookies. You can set the cookieless attribute to true in order to pass the SessionID without cookies.

Setting cookieless to true causes IIS to pass the SessionID in the URL. Instead of passing the SessionID to the client using cookies, the SessionID is placed into the URL of the page, as well as any relative links on that page. For example, calling a page named WebForm1.aspx when using cookies would return this as the URL:

http://localhost/StateTest/WebForm1.aspx

Setting cookieless to true would show this URL in the browser (your SessionID will vary):

http://localhost/StateTest/(wpnf2emmfafsbc3abdktzp45)/WebForm1.aspx

Changing the Timeout Period

If you want to change the default timeout of 20 minutes, simply change the timeout value in the <sessionState /> section of Web.config. This allows you to modify the timeout, in minutes, using an Integer value. The timeout must be greater than zero, but can be up to 2,147,483,647, if you need a session that lasts over 4,000 years.

A Quick Example

In order to see how the state management works, you'll create a simple ASPX page. Open Visual Studio .NET and create a new ASP.NET Web Application. On the WebForm, add a button and a label. Then, go to the code view and add the code shown in Listing 1 (for VB .NET) or Listing 2 (for C#), both shown below. This is all you will need to do as far as coding.

Listing 1 (for VB NET)

Listing 2 (for C#)

Run the application. Once the page is shown in the browser, clicking the button will increment the label by 1 each time you click. This is because in the code, you are creating a session variable called Name the first time this user calls the page. The IsPostBack property is checked to prevent the user from running the code each time to set the value back to zero.

Now, because you created this with the default session state method, go and stop the IIS Admin service using the Services applet in Windows 2000/XP. Stopping this service will require other services to be stopped, most notably the World Wide Web Publishing service. Once all the necessary services have stopped, this means that IIS has been shut down, and the Session object created for you is gone. Don't click the button yet; instead, restart the IIS Admin service and the World Wide Web Publishing service. Now, click the button again, and you will start back at one. This is because the session was destroyed, and on your next request, you created a new session, and your counter started back at zero.

Close the browser and return to the project. In the Web.config file, change the mode to StateServer. Start the Windows service using the command mentioned earlier, and run the same test: Start the project, click the button a few times, and then stop the IIS Admin service. After restarting the IIS Admin and the World Wide Web Publishing services, you can click the button and the count will resume where you left off; state was not lost due to stopping IIS, because state was being stored outside of IIS. You can test the same scenario using SQL Server if you prefer.

Summary

Many developers were loathe to use ASP's built-in Session object, because it was not scalable in a Web farm scenario. ASP.NET addresses the ASP session state shortcomings by allowing you to store the state out of process in a Windows service or in SQL Server. You can also easily turn off the need for session state to use cookies on the client. These new features reduce some of the major arguments against using built-in state management. However, none of these new features addresses the concern that the built-in state management is slow, but that is the subject for another article.

About The Author

Craig Utley is President of CIO Briefings LLC, a consulting and training firm focused on helping customers develop enterprise-wide solutions with Microsoft technologies. Craig has been using Visual Basic since version 1.0, and he has guided customers through the creation of highly scalable web applications using Active Server Pages, Visual Basic, MTS/Component Services, and SQL Server. Craig's skills in analyzing and designing enterprise-wide solutions have been used by large corporations and start-up companies alike.

Created : 7/11/2003 5:56:25 PM (last modified : 7/11/2003 5:56:22 PM)
Rate this article!
 
Comments