Managing State in ASP.NET Web Applications
The Internet is a stateless application. In a nutshell, that means every call to the server is separate from the next or the previous call. Unlike Windows Forms applications in which you can set global variables and have a bunch of hidden forms open to maintain the state of the data, the Web doesn't afford you that luxury. So, the challenge is to keep track of where the user is in your Web application, and where to take her next. This is done by maintaining state.State can be maintained in several ways, and some ways are better than others. Where you maintain state can be broken down into two categories: on the client and on the server.
Managing State on the Client
When I say managing state on the client, I mean handling page-level state in the browser. This can be done in the following ways:
- The Viewstate control
- Cookies
- The HTML Hidden control
- The browser's query string
Using Cookies
The most familiar way to handle state client-side is by using cookies. Cookies are a key-value paring of collection data that are saved on the client's hard drive. When you need to store information about someone's profile, you normally save a cookie that uniquely identifies him on his machine. If he closes the browser and revisits your site, you check for the cookie in a Page_Load event. If it exists, you use it to customize the look and feel of the HTML output. Or, you might simply have a Welcome Back Bob label on your home page, to let the user know he's logged in to your server, or that he's a returning visitor.Before .NET, cookies were a problem because an end user can decide not to accept cookies on his machine. Because spam emailers and pop-up ads abuse cookies, many people fear them. To get around this, you can modify the Web.Config file to use sessionless cookies, meaning the cookie data is encrypted and passed in the query string of the browser, so no data is actually stored on the end user's machine. To change the cookies option in the Web.Config file, locate the sessionState section of the Web.Config file and modify the cookieless attribute to true, as the following code demonstrates:
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;user id=sa;password="
cookieless="true"
timeout="20"
/>
To access cookies in code, you access the Cookies property of the Request or Response object, depending on whether you're writing a cookie or reading a cookie. The following code snippet checks for a UserID cookie. If one doesn't exist, the code writes the cookie out.
Dim cookie As HttpCookie = Request.Cookies("UserID")
If cookie Is Nothing Then
Response.Cookies("UserID").Value = "Jason"
Response.Cookies("UserID ").Expires = "January 1, 2010"
Response.Cookies("UserID ").Path = "/"
Else
Response.Write(Request.Cookies("UserID")
End If
When using the Cookies object, you must set the Expires property to actually save the cookie. If you don't set the Expires property, the cookie is deleted when the user's browser session ends.
Note
In ASP, you could simply check the value of a cookie in server-side VBScript by using this syntax:
If Request.Cookies("UserID") = " Then
This won't work in .NET if the cookie does not exist. You get an error message that says there's no instance of the Cookie object. You must explicitly check whether the HttpCookie object is Nothing, and then get or set the values of the cookie.
Understanding View State
View state is a new way of storing state data if you're coming from an ASP background. Each control and ASPX page has an EnableViewState property, which is set to True by default. When a page is processed that has ViewState enabled, a hidden field named Viewstate is added to the ASPX page and all the page data for the form is preserved in the hidden control. Each time a page is posted back to the server, the contents of the ViewState control are updated so that the correct data is in the fields when the same page is rerendered. This makes it so individual controls on a page don't lose their data each time the page is sent to the server.Because ViewState is a page-level state management option, the data for each page is simply passed back and forth from the browser to the server inside the page itself. However, this can be problematic for scalability. Because the page data is kept in the hidden control, the page size can grow. For example, if you have a DataGrid control that lists all the authors in the Pubs database, all this information is stored in the page's ViewState control. Each time the page is rendered to the browser, the amount of data sent down the pipe is literally doubled. To avoid this, you can set the EnableViewState property to False for the control, thus eliminating the state data from being kept.If you want to set ViewState data in code, you can use a key-value pair similar to a Cookies or Session object, as the following code demonstrates:
Viewstate("UserID") = "Bob"
Using the HTML Hidden Control
The HTML Hidden control is an HTML element in the Toolbox. Using hidden fields is a common way to store information in ASP. The concept is the same with the HTML Hidden controlyou can set the Value property of the control to store page-specific information.
Using the Query String
Passing data between pages using the query string of the browser is a common way to keep page information safe, while not having to worry about cookies on the client or saving too much data with the ViewState control. When you post a page using HTTP-GET, which is set using the Method=Get attribute on the Form tag in the HTML of your page, you automatically send all the data in the fields through the query string of the browser. When you pass values of a form using HTTP-GET, the initial control ID is separated from the requested page by an ampersand, and the remaining fields are separated by the question mark character. If you were to pass the data to the Success.aspx page using HTTP-GET in the code you wrote for the Login.aspx page, the query string would look something like this:
http://localhost/helloweb_vb?Username=jason@fladotnet&Password=password
Of course, it isn't a wise idea to send secret information in plain text through a query string, so using HTTP-GET with password information isn't recommended.
Managing State on the Server
To manage state on the server side, you use either session state or application state. When developing in ASP, there are long-winded arguments about how, when, and where to store session-level state. This is because IIS can't scale very well if there are too many session variables in memory. For example, assume that you keep 10 session-level variables for each person who hits your site. On average, you have 1,000 hits an hour. That means IIS has to manage 100,000 unique objects in memory to keep track of each browser's session data. This would kill Web servers. In .NET, this is no longer an issue.
Using Session State
Using session-level state enables you to track variable data for a user throughout his visit to your Web site. Using the HttpSessionState class, you can use the same key-value pair syntax for Session objects that you use for ViewState. Each time a browser hits your site, IIS creates a unique session ID for the browser session if you access the Session object in code. If you don't reference the Session object in code, IIS doesn't create a unique ID for the end user's session on your site.Session information is useful to save data between multiple page calls. For example, when I visit my bank's Web site, I must enter my username and password every time I visit, which means the bank isn't storing such high-security data in a cookie. But after I log in to the site, each page I navigate knows who I am, so the data is being passed to all pages for my session through the use of session state. To set or retrieve values for session state, you use this syntax:
If Session("UserID") = "Bob" then ...
Reponse.Write(Session("UserID"))
After the browser window is closed or the end user navigates to another site, the session data is lost. When the end user returns to the site, you must create new session information based on the user's current session.In .NET, the Web.Config file gives you options as to where session-level state can be stored for a site. By default, session state is stored in the same process as IIS. If you need greater scalability, you can store session state in SQL Server or in an out-of-process state server. To change where the state is stored, you modify the mode attribute in the sessionState section of the Web.Config file. If you want to store your Session data in SQL Server, you modify Web.Config to look like this:
<sessionState
mode="SqlServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;user id=sa;password="
cookieless="false"
timeout="20"
/>
You must also supply the correct authentication information, and run a special SQL script that creates database and temporary tables in SQL Server to hold the state data.In the Global.asax file, you can also write code in the Session_OnStart and Session_OnEnd events. You could use this to ensure that a session-specific event, such as updating a hit counter in a database, is occurring each time a session begins or ends.
Using Application State
Application-level state is the top level in the state management hierarchy. The first time someone accesses your Web site, the Application object for the site is created. The Application object is alive until the server is rebooted, IIS is restarted, or a new copy of the Web site is deployed. In the Global.asax file, there are Application_OnStart and Application_OnEnd events that you can write code to respond to; they're similar to the Session_OnStart and Session_OnEnd events. The difference is that application-level variables are global for all sessions for your Web site, not for individual users.