The value of the variables and controls collectively make up the state of a Web page. State management is the process of maintaining state for a Web page across round trips. State management is ubiquitous with desktop-based applications, and programmers need not even care about it while developing these applications. However, because of the disconnected nature of the HTTP, state management is an important issue for Web applications. ASP.NET provides several techniques for preserving state information across page postbacks. I'll broadly categorize these techniques as either client-side or server-side, depending on where the resources are consumed for state management. Client-side Techniques for State ManagementClient-side techniques use the HTML code and capabilities of the Web browser to store state- related information. ASP.NET supports the following techniques for storing state information at the client side:
Query StringsQuery strings are used to maintain state by appending the state information to a page's URL. The state data is separated from the actual URL with a question mark ( ? ). The data attached to the URL is usually a set of key-value pairs, in which each key-value pair is separated by an ampersand ( & ). For example, look at this URL that embeds two key-value pairs ( name and city): www.buddy.com/find.aspx?name=Bill+Gates&city=redmond Because of their simplicity, query strings are widely used for passing a small amount of information to Web pages. However, query strings suffer the following limitations:
Reading information from query strings in an ASP.NET program is easy using the QueryString property of the current HttpRequest object. The QueryString property returns a NameValueCollection object representing the key-value pairs stored in the query string. For example, the following expressions retrieve the value of the name and city, respectively, from the query string used in the previous URL: Request.QueryString["name"] Request.QueryString["city"] CookiesCookies are small packets of informationeach storing a key-value pair at the client side. These packets are associated with a specific domain and are sent along with each request to the associated Web server. Cookies are commonly used to store users' preferences and provide them with a personalized browsing experience on their subsequent visits to a Web page. Use of cookies suffers from the following limitations:
You can use the Cookies property of the HttpRequest object to get an HttpCookieCollection object that represents the cookies sent by the client for the current HTTP request. The following code segment shows how to set a cookie on a user's computer: // Create a cookie called Name HttpCookie cName = new HttpCookie("Name"); cName.Value = txtName.Text; // Set the expiration time of the cookie // to 15 minutes from the current time cName.Expires = DateTime.Now + new TimeSpan(0,0,15,0); // Add the cookie to the response cookies // collection to send it to the client's machine Response.Cookies.Add(cName); To retrieve the value of a cookie, you just need to retrieve it from the HTTP request, as shown in the following code sample: if(Request.Cookies["Name"] == null) { // the Name cookie does not exist, } else { // the Name cookie exists Response.Write(Request.Cookies["Name"].Value); } Hidden FieldsHidden fields contain information that is not visible on the page but is posted to the server along with a page postback. All modern browsers support hidden fields on a Web page. However, hidden fields have the following limitations:
ASP.NET provides an HTML server control, HtmlInputHidden , that maps to the <input type="hidden"> HTML element. The HtmlInputHidden control is not available as a Web server control mainly because ASP.NET uses a similar, but more powerful, technique called view state . View StateView state is the mechanism ASP.NET uses to maintain the state of controls across page postbacks. Just like hidden fields and cookies, you can also use view state to maintain state for noncontrol values in a page. However, it is important to note that view state works only when a page is posted back to itself. The following sections explain how view state works in various scenarios. View State for Postback ControlsSome server controls, such as TextBox , CheckBox , and so on, post their values as part of the postback operation. These types of controls are also known as postback controls . For postback controls, ASP.NET retrieves their values one by one from the HTTP request and copies them to the control values while creating the HTTP response. Traditionally, Web developers had to manually write this code for maintaining state for the postback controls, but now ASP.NET does this automatically. View State for Nonpostback ControlsIn addition to the postback controls, the view state mechanism of ASP.NET also retains values for nonpostback controls (that is, the controls that do not post their values as part of the postback operation, such as a Label control). You might wonder how ASP.NET manages to maintain values for a control even when the controls do not post their values. Actually, no magic is involved; ASP.NET extends the concept of hidden fields to accomplish this. When ASP.NET executes a page, it collects the values of all nonpostback controls that are modified in the code and formats them into a single, base64-encoded string. This string is then stored in a hidden field in a control named __VIEWSTATE , as in this example: <input type="hidden" name="__VIEWSTATE" value= "dDwtMTg3NjA4ODA2MDs7PoYLsizcOhkv2XeRfSJNPt12o1HP" /> The hidden input field is a postback control, so in the next postback of the page, the encoded string stored in the __VIEWSTATE field is also posted. At the Web server, ASP.NET decodes the view state string at page initialization and restores the control's values in the page. Maintaining state using this technique does not require many server resources, but it does increase the size of the HTML file, which therefore increases the amount of time it takes to load the page. View State for Page-level ValuesThe ViewState property of the Page class is a great place to store page-level values. View state saves these values just prior to rendering the page and restores the values at the time of page initialization after the postback operation. This might sound like cookies or hidden fields, but a major improvement is that you are not just limited to storing simple values. You can use the ViewState to store any object as long as it is serializable. The following example demonstrates how to use the view state to maintain state for page-level values, such as the number of posts on a Weblog:
As you can see in the previous example, view state is internally maintained as a hidden field. However, view state provides a higher degree of customizability and other security features that you'll see shortly. Disabling View StateBy default, view state is enabled in an ASP.NET application. As you have observed in the previous example, the size of information stored in view state can increase the size of the HTML for a Web page. ASP.NET provides complete flexibility in disabling view state at various levels:
Protecting View StateASP.NET provides a way of knowing whether somebody has modified the contents of the view state to fool your application. With this technique, the view state is encoded using a hash code (using the SHA1 or MD5 algorithms) when it is sent to the browser. When the page is posted back, ASP.NET checks the encoded view state to verify that it has not been tampered with on the client. This type of check is called a machine authentication check ( MAC ) . By default, ASP.NET has the following entry in its machine.config file: <pages enableViewStateMac="true" /> This enables tamper proofing for all applications running on a Web server. You can also manually enable or disable the tamper-proofing check at page level by setting the EnableViewStateMac attribute of the Page directive to true or false in the ASPX page: <%@ Page EnableViewStateMac="false"%> However, this scheme just makes the view state tamper proof; it does not restrict users from determining the contents of the view state. Although the values are not directly visible as in the cases of query strings or hidden variables, determined users can easily decode the view state. With only a few configuration changes, you can instruct ASP.NET to encrypt the contents of the view state using the Triple DES symmetric algorithm (3DES), making it extremely difficult for the clients to decode the view state. This kind of encryption can be applied only at the machine level by specifying the following setting in the machine.config file: <machineKey validation='3DES' />
Choosing a Client-side State Management TechniqueTable 4.10 lists the advantages and disadvantages of the various client-side state management techniques. This table will help you make a quick decision about which client-side state management technique to choose in a given scenario. Table 4.10. Comparing the Client-side State Management Techniques
Server-side Techniques for State ManagementOne of the advantages of using server-side techniques for state management is that the possibility of a user spoofing or reading the session data is eliminated. However, there is a disadvantage, too: These techniques use server resources, raising scalability issues. ASP.NET supports server-side state management at two levelsat the level of the Web application using the application state and at the level of a user session using the session state. Session StateAn ASP.NET application creates a session for each user who sends a request to the application. ASP.NET distinctly identifies each of these sessions by sending a unique SessionID to the requesting browser. This SessionID is sent as a cookie or is embedded in the URL, depending on the application's configuration. This mechanism of sending a SessionID ensures that when the next request is sent to the server, the server can use the unique SessionID to distinctly identify the repeat visit of the user. Both user visits are considered to belong to the same session. The capability of uniquely identifying and relating requests can be used by Web developers to store session-specific data. A common example is storing shopping cart contents for users as they browse through the store. This session-specific information is collectively known as the session state of the Web application. Comparing ASP.NET Session State with ASPASP.NET comes with a new implementation of session state that removes all the old problems associated with ASP. Table 4.11 compares these improvements. Table 4.11. Managing the Session State
Moreover, session state in ASP.NET is configurable. Depending on the requirements of your Web application, you can change the way the session state is maintained in your application by just changing a few lines in an XML-based configuration file ( web.config ). You learn about session state configuration in Chapter 16, "Configuring a Web Application." Using Session StateASP.NET uses an instance of the HttpSessionState class to provide access to the session data for the user who originated the request. In an ASPX page, this object is accessible through the Session property of the Page class. This property provides access to the HttpSessionState object that stores the session state as a collection of key-value pairs, in which the key is of string type while the value can be any type derived from System.Object . Tables 4.12 and 4.13 explain the properties and methods of the HttpSessionState class, respectively. Table 4.12. Properties of the HttpSessionState Class
Table 4.13. Methods of the HttpSessionState Class
The following example upgrades the Weblog example to maintain the session state at the server side:
The previous example demonstrates that session state is not persistently stored like cookies. The default technique of passing SessionID is with nonpersistent cookies, so this example works only if you are using a cookie-enabled browser. If element> element (web.config)> you want to use a cookieless session instead, you must modify the web.config file associated with this application to set the cookieless attribute to true in the <sessionState> element, like so: <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <sessionState mode="Inproc" cookieless="true" /> ... </system.Web> </configuration> Application StateApplication state is used to store data that is globally used throughout the application. The application state is stored in memory, and unlike the session state, application state can't be configured for storage on another server or a SQL database. This limits the usefulness of the application state for Web farm scenarios. Application state can be easily accessed through the Application property of the Page class. This property provides access to the HttpApplicationState object that stores the application state as a collection of key-value pairs, in which the key is a string type and the value can be any type derived from System.Object . Tables 4.14 and 4.15 discuss the properties and methods of the HttpApplicationState class, respectively. Table 4.14. Properties of the HttpApplicationState Class
Table 4.15. Methods of the HttpApplicationState Class
The following example demonstrates the use of the Application property to store the applicationwide data:
Note that the technique used in the previous example is a volatile way to store the hit count (that is, users only see the total number of hits since the last time the application started). If you want the hit count to persist across application restarts, you should store the hit count periodically to a database. In the example, you modified the contents of the application state using a pair of Application.Lock() and Application.UnLock() methods. Locking is important for keeping application state consistent when multiple users might want to modify the application object's content concurrently. While the application is locked, only the current user can change the contents of the application state. This locking mechanism can severely reduce the scalability of a Web application; therefore, you should usually not store any updatable data in the application state.
|