State Management
The values of the variables and controls collectively make up the state of a Web page. State management is the process of maintaining the state of a Web page across round trips.
State management is ubiquitous with desktop-based applications and programmers need not even care about it while developing their applications. However, because of the disconnected nature of the HTTP protocol, state management is a big issue for Web applications.
ASP.NET provides several techniques to preserve state information across page postbacks. I'll broadly categorize these techniques as either client-side or the server-side depending on where the resources are consumed for state management.
Client-side Techniques for State Management
Client-side techniques use the HTML code and the 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 strings
Cookies
Hidden Fields
ViewState
Query Strings
A query string maintains 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 where each key-value pair is separated using an ampersand (&). For example, look at this URL that embeds two key-value pairs, name and city:
http://www.buddy.com/find.aspx?name=Bill+Gates&city=Redmond
Because of their simplicity, query strings are widely used for passing small amounts of information to the Web pages. However, query strings suffer from the following limitations:
Most browsers restrict the length of the query string; this reduces the amount of data that you can embed to a URL.
Query strings do not provide any support for structured data types.
The information stored in query strings is not secure because they are directly visible to the users.
Reading information from query string in an ASP.NET program is easy. You can use the QueryString property of the current HttpRequest object. QueryString returns a NameValueCollection object representing the key-value pairs stored in the query string.
STEP BY STEP 3.7 - Using Query Strings in a Web Application
-
Add a new Web Form to the project. Name the Web Form StepByStep3-7.aspx. Change the pageLayout property of the DOCUMENT element to FlowLayout.
-
Add two Label controls, two TextBox controls (txtName, txtEmail), and a Button control (btnSubmit) to the Web Form.
-
Double-click the button control and add the following code in the Click event handler:
Private Sub btnSubmit_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnSubmit.Click ' Redirect to a page with a query string ' containing name and email Response.Redirect("StepByStep3-7a.aspx?Name=" & _ txtName.Text & "&Email=" & txtEmail.Text)
End Sub
-
Add a new Web Form to the project. Name the Web Form StepByStep3-7a.aspx. Change the pageLayout property of the DOCUMENT element to FlowLayout.
-
Add a Label control (lblInfo) on the Web Form.
-
Add the following code in the Page_Load() event handler:
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' If the query string collection contains Name If Not Request.QueryString("Name") Is Nothing Then ' Display a message by getting Name and Email ' from the query string collection lblInfo.Text = Request.QueryString("Name") & _ ", thanks for registering with us! " lblInfo.Text &= "You are subscribed at " & _ Request.QueryString("Email") End If
End Sub
-
Set StepByStep3-7.aspx as the start page for the project.
-
Run the project. Enter a name and email address in the text boxes and click the Submit button. You should see that the button redirects the response to the StepByStep3-7a.aspx with the name and email address data as the query string. The new form then displays a message along with the name and email address fetched from the query string as shown in Figure 3.8.
Figure 3.8 Query string is used to maintain state by appending the state information to a page's URL.
If you observe the URL in Figure 3.8, you'll note that the name and email address are embedded in the URL itself. The query string is a very easy way to pass small, nonsensitive pieces of information.
Cookies
Cookies are small packets of information, each storing a key-value pair, stored on the client's computer. These packets are associated with a specific domain and are sent along with each request to the associated Web server.
A cookie can be set to expire when a user session ends or you can request the browser to persist the cookies on the user's computer for a specified period. Cookies are commonly used to store a user's preferences and provide them personalized browsing experience on their repeated visits to a Web page.
Use of cookies suffers from the following limitations:
Most browsers limit the size of information that you can store in a cookie. A typical size is 4096 bytes with older browser versions and 8192 bytes with the newer browser versions.
Some users configure their browsers to refuse cookies.
When you request the browser to persist a cookie on the user's computer for a specified period, browsers may override that request by using their own rules for cookie expiration.
Because cookies are stored at the client, they may be tampered with. You cannot trust the data that you receive from a cookie.
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.
STEP BY STEP 3.8 - Using Cookies to Maintain Client-side State
-
Copy the Web Form StepByStep3-1.aspx and change its name to StepByStep3-8.aspx. Open the ASPX file and the VB file and change all occurrences of StepByStep3_1 to StepByStep3_8. Add a Label control with the id of lblName to the form.
-
Switch to the code view and modify the Page_Load() method as shown here:
Private Sub Page_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Request.Cookies("Name") Is Nothing Then ' If the Name cookie does not exists ' ask user to enter name Response.Redirect("StepByStep3-8a.aspx") Else ' If cookie already exists then show ' a personalized welcome message to the user lblName.Text = "Welcome " & _ Request.Cookies("Name").Value End If If Not Page.IsPostBack Then ' If page is requested for the first time ddlCategories.Items.Add("Web development") ddlCategories.Items.Add( _ "Programming Languages") ddlCategories.Items.Add("Certifications") Else ' On postback, change the case of textbox txtTitle.Text = txtTitle.Text.ToUpper() End If ' Set the text of the label ' control on each page load lblQuestion.Text = _ "What do you want to write about " & _ ddlCategories.SelectedItem.Text + " today?"
End Sub
-
Double-click the Post button control and modify the Click event handler as follows:
Private Sub btnPost_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnPost.Click ' Format the data entered by the user and ' use the name of the user stored in a cookie ' append it all to the existing ' contents of lblWeblog lblWeblog.Text = "<b>" & _ ddlCategories.SelectedItem.Text & _ " :: " & txtTitle.Text & ":: by " & _ Request.Cookies("Name").Value & "</b> (" & _ DateTime.Now.ToString() & ")<HR>" & _ txtMessage.Text & "<p>" & _ lblWeblog.Text
End Sub
-
Add a new Web Form to the project. Name the Web Form StepByStep3-8a.aspx. Change the pageLayout property of the DOCUMENT element to FlowLayout.
-
Add a Label control, a TextBox control (txtName), a Button control (btnSubmit), and a CheckBox control (cbRemember) on the Web Form.
-
Double-click the Submit button control and add the following code in the Click event handler:
Private Sub btnSubmit_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnSubmit.Click ' Create a cookie called Name ' Set the cookie with the Text of the text box Dim cName As HttpCookie = New HttpCookie("Name") cName.Value = txtName.Text ' Check if the checkbox "remember me" is checked If cbRemember.Checked Then ' Set the expiration time of the cookie ' to 15 minutes from the current time cName.Expires = DateTime.Now.Add( _ New TimeSpan(0, 0, 15, 0)) End If ' Add the cookie to the response ' cookies collection ' To send it to the client's machine Response.Cookies.Add(cName) ' Redirect the response to the message post page Response.Redirect("StepByStep3-8.aspx")
End Sub
-
Set StepByStep3-8.aspx as the start page for the project.
-
Run the project. You should see that you have been redirected to StepByStep3-8a.aspx. Enter a name, select the checkbox, and click the Submit button. You'll now see StepByStep3-8.aspx with a personalized greeting. Post a message, and you should see that your name is now posted along with the title of the message as shown in Figure 3.9.
Figure 3.9 Cookies can be used to provide personalization settings for individual users.
-
Close this browser window. Open another browser window and browse to StepByStep3-8.aspx. Assuming you checked the "Remember me" checkbox, the form will display your name immediately.
Step by Step 3.8 demonstrates how cookies can be used to persist state across browser restarts. If you don't select the checkbox, cookies will just be stored in the primary memory and will be destroyed when the browser window is closed. The program also demonstrates how you can request the browser to set an expiration date and time for the cookie. Step by Step 3.8 sets the expiration time of the cookie to 15 minutes from the current time. You should note that this is just a request; browsers are free to override this with their own settings.
Hidden Fields
Hidden fields contain information that is not visible on the page but is posted to the server along with a page postback. Most browsers support hidden fields on a Web page. However, hidden fields have some limitations as mentioned in the following list:
Although the information stored in hidden fields is not visible on the page, it is still part of the page's HTML code and users can view them by viewing the HTML source of the page. Hidden fields are therefore not a good choice for storing information that you would like to keep secure.
Hidden fields are part of the page HTML. If you store more information in hidden fields, it increases the size of HTML page making it slow for users to download.
Hidden fields only allow you to store a single value in a field. If you want to store structured values such as a customer record, you'll have to use several hidden fields.
ASP.NET provides an HTML server control, HtmlInputHidden, that maps to the <input type="hidden"> HTML element. Step by Step 3.9 demonstrates the use of hidden fields to maintain the number of posts on the Web log page created in Step by Step 3.1.
STEP BY STEP 3.9 - Using Hidden Fields to Maintain Client-side State
-
Copy the Web Form StepByStep3-1.aspx and change its name to StepByStep3-9.aspx. Open the ASPX file and the VB file and change all occurrences of StepByStep3_1 to StepByStep3_9.
-
Place a Label control (lblPosts) and an HTML Hidden control (txtPosts) next to the Post button control on the form. Right-click the txtPosts control and select Run As Server Control. Set the value property of txtPosts to 0.
-
Switch to the code view and modify the Click event handler of the btnPost control as shown here:
Private Sub btnPost_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnPost.Click ' Format the data entered by the user and ' append it to the existing contents of lblWeblog lblWeblog.Text = "<b>" & _ ddlCategories.SelectedItem.Text & _ " :: " + txtTitle.Text & "</b> (" & _ DateTime.Now.ToString() & ")<HR>" & _ txtMessage.Text & "<p>" & _ lblWeblog.Text ' As one more post is added ' Increment the value of the hidden control Dim intPostCount As Int32 = _ Int32.Parse(txtPosts.Value) + txtPosts.Value = intPostCount.ToString() lblPosts.Text = "Total Posts: (" & _ txtPosts.Value & ")"
End Sub
-
Set StepByStep3-9.aspx as the start page for the project.
-
Run the project. Make a few entries in the Web log. You will see that with each entry in the Web log, the total posts value is increased by 1 as shown in Figure 3.10.
Figure 3.10 Contents of hidden fields are posted to the Web server with each page postback.
Step by Step 3.9 shows a typical example in which hidden fields can be used to maintain state information. Here, because a hidden field is an input type of control, its value is posted back to the Web server with each page postback. Hidden fields can be used to store page-scope values between round trips.
NOTE
Programmatic Hidden Fields If you only need a hidden field in some circumstances, you can create it programmatically. The RegisterHiddenField method of the Page object allows you to create hidden fields at runtime.
The HtmlInputHidden control is not available as a Web server control. This is mainly because ASP.NET uses a similar but more powerful technique called ViewState.
ViewState
ViewState is the mechanism that ASP.NET uses to maintain the state of controls across page postbacks. Just like hidden fields and cookies, you can also use ViewState to maintain state for noncontrol values in a page. You must keep in mind that ViewState works only when a page is posted back to itself.
The following sections explain how ViewState works in various scenarios.
ViewState for Postback Controls
Some server controls such as TextBox or CheckBox post their values as part of the postback operation. These types of controls are known as the 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 write this code manually to maintain state for the postback controls but now ASP.NET does this automatically.
ViewState does not require any additional storage either on the client side or on the server side for maintaining state for postback controls.
ViewState for Non-postback Controls
In addition to the postback controls, the ViewState mechanism of ASP.NET also manages to retain values for non-postback controls (that is, the controls that do not post their values as part of the postback operation, such as Label controls). You may wonder how ASP.NET manages to maintain values for control even when the controls do not post their values. Actually, there is no magic involved; ASP.NET extends the concept of hidden fields to accomplish this.
When ASP.NET executes a page, it collects the value of all non-postback 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="dDwtMTg3NjA4ODA2MDs7PoY LsizcOhkv2XeRfSJNPt12o1HP" />
The hidden input field is a postback control, and 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 ViewState string at page initialization and restores the controls values in the page.
Maintaining state using this technique does not require many server resources but it definitely increases the size of the HTML file and therefore increases the amount of time it takes to load the page.
ViewState for Page-level Values
The ViewState property of the Page class is a great place to store page-level values. ViewState will save these values just prior to rendering that page and restore the values at the time of page initialization after the postback operation. This may sound like a cookie or hidden field but a major improvement is that you are not just limited to store simple values. You can use the ViewState to store any object as long as it is serializable.
A good practice is to expose a page level value as a property that internally manipulates the ViewState of the page. I'll use this technique in Step by Step 3.10 to maintain the number of posts on the Web log using ViewState.
STEP BY STEP 3.10 - Using ViewState to Maintain State for Page-level Values
-
Make a copy the Web Form StepByStep3-1.aspx and change its name to StepByStep3-10.aspx. Open the ASPX file and the VB file and change all occurrences of StepByStep3_1 to StepByStep3_10.
-
Place a Label control (lblPosts) next to the button control on the form.
-
Switch to the code view and the following property to the class StepByStep3_10 definition:
' Get or set the number of posts in the Weblog Protected Property NumberOfPosts() As Integer Get If ViewState("NumberOfPosts") Is Nothing Then ' The NumberOfPosts key is not ' present in the ViewState NumberOfPosts = Else ' Retrieve the NumberOfPosts ' from the ViewState Return Convert.ToInt32( _ ViewState("NumberOfPosts")) End If End Get Set(ByVal Value As Integer) ' Set the NumberOfPost in the ViewState ViewState("NumberOfPosts") = Value End Set
End Property
-
Modify the event handler for the Click event of btnPost control as shown below:
Private Sub btnPost_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnPost.Click ' Format the data entered by the user and ' append it to the existing contents of lblWeblog lblWeblog.Text = "<b>" & _ ddlCategories.SelectedItem.Text & _ " :: " + txtTitle.Text & "</b> (" & _ DateTime.Now.ToString() & ")<HR>" & _ txtMessage.Text & "<p>" & _ lblWeblog.Text ' One more post is added ' Increment the value of NumberOfPost ' key in the Page's ViewState NumberOfPosts = NumberOfPosts + lblPosts.Text = "Total Posts : (" & _ NumberOfPosts & ")"
End Sub
-
Set StepByStep3-10.aspx as the start page for the project.
-
Run the project. Make a few entries in the Web log. You should see that with each entry in the Web log, the total posts value is increased by 1, just as it did in Step by Step 3.10.
-
View the HTML code rendered in the Web browser. You'll note that the value associated with the __VIEWSTATE field changes as you post more messages to the Web log.
As you see from Step by Step 3.10, internally ViewState is also maintained as hidden field. However, ViewState provides a higher degree of customizability and other security features that you'll see shortly.
Disabling ViewState
By default, ViewState is enabled in an ASP.NET application. As you have observed in the previous examples, the size of information stored in ViewState can increase the size of HTML for a Web page. This is especially important when your application contains complex controls such as a DataList or DataGrid. To optimize a Web page size you may want to disable ViewState in the following cases:
When a page does not postback to itself
When there are no dynamically set control properties
When the dynamic properties are set with each request of the page
ASP.NET provides you complete flexibility to disable ViewState at various levels as mentioned in the following list:
-
At the level of a control If you populate the control's state on each request, you may disable ViewState at the control level by setting the EnableViewState property of the control to false:
<asp:DataGrid EnableViewState="false" .../>
-
At the level of a page If the page doesn't post back to itself, you may disable ViewState at the page level by setting the EnableViewState attribute of the @Page directive to false in the ASPX file:
<%@Page EnableViewState="false" %>
-
At the level of an application If no page in an application posts back to itself, you may disable ViewState at the application level by adding the following line to the web.config file:
<Pages enableViewState="false"/>
-
At the level of machine In the unlikely case where you want to disable ViewState for all the applications running on a Web server, you can do so by adding the following statement to the machine.config file:
<Pages enableViewState="false"/>
Protecting ViewState
By default the ViewState of a page is not protected. Although the values are not directly visible as in the case of query string or hidden variables, it is not difficult for determined users to decode the storage format.
NOTE
ViewState Decoder You can decode the contents stored in the __VIEWSTATE hidden input control using the ViewState Decoder utility written by Fritz Onion. You can download this utility from http://www.develop.com/devresources/resourcedetail.aspx?type=t&id=827.
However, only with a few configuration changes, ASP.NET allows you to store ViewState in a much more secure way. ASP.NET provides two ways to increase the security of ViewState:
-
Tamper-proofing the ViewState Tamper-proofing does not protect against someone determining the contents of ViewState. It instead provides a way of knowing whether somebody has modified the contents of ViewState to fool your application. Using this technique, the ViewState 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 ViewState to verify that it has not been tampered with on the client. This type of check is called machine authentication check (MAC). By default, ASP.NET has the following entry in its machine.config file:
<pages enableViewStateMac='true' />
NOTE
Secure Only When Needed Running security algorithms puts additional overhead on your Web server and makes applications slower. Therefore, you should enable security for ViewState only when it is a must.
-
Chapter - This enables tamper-proofing for all the applications running on a Web server. You can also manually enable or disable the tamper-proofing check at a page level by setting the EnableViewStateMac attribute of the @Page directive to true or false in the ASPX file:
<%@ Page EnableViewStateMac="true"%>
NOTE
ViewState Security on a Web Farm When securing the ViewState for applications running on a Web Farm configuration, you must use the same validation key for all the machines on a Web Farm. To do this use a manually assigned key instead of the default auto generated key with the <machineKey> setting in the machine.config file.
-
Encrypting the ViewState This technique instructs ASP.NET to encrypt the contents of ViewState using Triple DES symmetric algorithm (3DES) making it extremely difficult for the client to decode the ViewState. This kind of encryption can be applied only at the machine level by specifying the following setting in machine.config file:
<machineKey validation='3DES' />
Choosing a Client-side State Management Technique
Table 3.10 lists the advantages and disadvantages of the various client-side state management techniques. This table will help you take a quick decision about which client-side state management technique to choose in a given scenario:
Table 3.10 - Comparing the Client-side State Management Techniques
Technique |
Advantage |
Disadvantage |
QueryString |
Requires no postback operation. |
Most browsers limit the length of data that can included in a query string. No security. No options for persistence. No support for storing structured values. |
Cookies |
State may be persisted on user's computer. |
Requires no postback operation. Some users disable cookies in their browsers. Size restriction by browser (~4 to 8KB). No support for storing structured values. No security. |
Hidden fields |
Can be used for pages that post to themselves or to other pages. |
Increases HTML size. No support for storing structured values. No security. No options for persistence. |
ViewState |
Support for structured values. |
Involves less coding. Easy configuration options for security. Increases HTML size. Only works when a page posts back to itself. No options for persistence. |
Server-side Techniques for State Management
Unlike client-side techniques for state management, server-side techniques use server resources for storing and managing state. One of the advantages of using server-side techniques for state management is that the possibility of user spoofing or reading the session data is eliminated, but there is a disadvantage too; because these techniques use server resources, they raise scalability issues.
ASP.NET supports server-side state management at two levels: at the level of the Web application using application state, and at the level of a user session using session state.
Session State
An ASP.NET application creates a session for each user that 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 to the URL depending on the application's configuration.
This mechanism of sending 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 and both the 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 to store the shopping cart contents for the users as they browse through the store. This session specific information is collectively known as the session state of a Web application.
Comparing ASP.NET Session State with ASP
The concept of SessionID and session state is not new to ASP.NET. ASP.NET's predecessor ASP also supported these features. ASP.NET comes with a new implementation of session state that removes all the old problems and provides several enhancements that are equally useful to small and very large Web sites. Table 3.11 compares these improvements.
Table 3.11 - Managing the Session State
The ASP Way |
The ASP.NET Way |
ASP maintains the state in the same process that hosts ASP. If the ASP process somehow fails, the session state is lost. |
ASP.NET allows you to store session state out-of-process in a state service or in a database. |
Each ASP Web server maintains its own session state. This creates a problem in Web Farm scenario where user's request can be dynamically routed to a different server in the Web farm. |
Because ASP.NET can store its session state out-of-process, several computers in a Web Farm can use a common computer as their session state server. |
ASP session does not work with browsers that don't support cookies or where the users have disabled the cookies. |
ASP.NET supports cookie-less sessions by storing the SessionID in the URL itself (if the application is configured to do so). |
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 will learn about session state configuration in Chapter 15.
Using Session State
ASP.NET provides access to the session data for the user who originated the request using an instance of the HttpSessionState class. 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, where the key is a string and the value can be any type derived from System.Object. Tables 3.12 and 3.13 explain the properties and methods of the HttpSessionState class.
Table 3.12 - Properties of HttpSessionState class
Property |
Description |
CodePage |
Specifies the code page identifier for the current session. This provides compatibility with ASP. Response.ContentEncoding.CodePage should be used instead. |
Contents |
Gets a reference to the session state (HttpSessionState) object. This provides compatibility with ASP. |
Count |
Gets the number of objects in the session state. |
IsCookieless |
Indicates whether the session is managed using a cookie-less session. |
IsNewSession |
Indicates whether the session has been created with the current request. |
IsReadOnly |
Indicates whether the session is read-only. |
IsSynchronized |
Indicates whether access to the session state is read-only (thread-safe). |
Keys |
Gets a collection of all session keys. |
LCID |
Specifies the locale identifier (LCID) of the current session. |
Mode |
Gets the current session state mode. The values are defined by the SessionStateMode enumerationOff (disabled), InProc (session state is stored in process with aspnet_wp.exe), SqlServer (session state is stored in SQL Server) and StateServer (session state stored in state service). |
SessionID |
Represents the unique session identifier used to identify a session. |
StaticObjects |
Gets a collection of objects declared by <object runat="server" scope="Session"> tags within the ASPX application file global.asax. |
SyncRoot |
Gets an object that can be used to synchronize access to the collection of session state values. |
Timeout |
Specifies the timeout period (in minutes) allowed between requests before the session state provider terminates the session. |
Table 3.13 - Methods of HttpSessionState Class
Property |
Description |
Abandon |
Cancels the current session. |
Add |
Adds a new object to the session state. |
Clear |
Removes all objects from the session state. |
CopyTo |
Copies the session state values to a single-dimensional array at the specified index. |
GetEnumerator |
Gets an enumerator of all session state values in the current session. |
Remove |
Removes an object from the session state. |
RemoveAll |
Removes all the objects from the session state. Calls Clear() method internally. |
RemoveAt |
Removes an object from the session state at a particular index. |
Step by Step 3.11 demonstrates the use of session state by upgrading the cookie example that you used in Step by Step 3.8 to maintain the session state at the server side instead of maintaining state at the client side.
STEP BY STEP 3.11 - Using Session State
-
Copy the Web Form StepByStep3-1.aspx and change its name to StepByStep3-11.aspx. Open the ASPX file and the VB file and change all occurrences of StepByStep3_1 to StepByStep3_11. Add a Label control named lblName to the form.
-
Switch to the code view and modify the Page_Load() method as shown here:
Private Sub Page_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If Session("Name") Is Nothing Then ' The Name key is not present in the session ' navigate to accept name of the the user Response.Redirect("StepByStep3-11a.aspx") Else ' The Name key is present in the session ' display a greeting lblName.Text = "Welcome " & _ Session("Name").ToString() End If If Not Page.IsPostBack Then ' If page is requested for the first time ddlCategories.Items.Add("Web development") ddlCategories.Items.Add( _ "Programming Languages") ddlCategories.Items.Add("Certifications") Else ' On postback, change the case of textbox txtTitle.Text = txtTitle.Text.ToUpper() End If ' Set the text of the label ' control on each page load lblQuestion.Text = _ "What do you want to write about " & _ ddlCategories.SelectedItem.Text + " today?"
End Sub
-
Double-click the Post button control and add the following code in the Click event handler:
Private Sub btnPost_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnPost.Click ' Format the data entered by the user and ' append it to the existing contents of lblWeblog lblWeblog.Text = "<b>" & _ ddlCategories.SelectedItem.Text & _ " :: " & txtTitle.Text & ":: by " & _ Session("Name").ToString() & "</b> (" & _ DateTime.Now.ToString() & ")<HR>" & _ txtMessage.Text & "<p>" & _ lblWeblog.Text
End Sub
-
Add a new Web Form to the project. Name the Web Form StepByStep3-11a.aspx. Change the pageLayout property of DOCUMENT element to FlowLayout.
-
Add a Label control, a TextBox control (txtName), and a Button control (btnSubmit) on the Web Form.
-
Double-click the Submit button control and add the following code in the Click event handler:
Private Sub btnSubmit_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnSubmit.Click ' Add the Name entered in the Session ' Redirect the response to the Weblog page Session("Name") = txtName.Text Response.Redirect("StepByStep3-11.aspx")
End Sub
-
Set StepByStep3-11.aspx as the start page for the project.
-
Run the project. You see that you have been redirected to StepByStep3-11a.aspx. Enter a name and click the Submit button. You'll now see StepByStep3-11.aspx page with a personalized greeting. Post a message; you should see that your name is now posted along with the title of the message (refer to Figure 3.9).
-
Close this browser window. Open another browser window and browse to StepByStep3-11.aspx. You should see that you have been again redirected to StepByStep3-11a.aspx to enter your name information.
Step by Step 3.11 demonstrates that session state is not persistently stored like cookies. The default technique of passing SessionID is with nonpersistent cookies, so this example only works if you are using a cookie-enabled browser. If you instead want to use a cookie-less session, you'll have to modify the web.config file associated with this application to set the cookie-less attribute to true in the <sessionState> element:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <sessionState mode="Inproc" cookieless="true" /> </system.Web> </configuration>
Application State
Application state is used to store data that is globally used by 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 in 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, where the key is a string type while value can be any type derived from System.Object. Tables 3.14 and 3.15 discuss the properties and methods of the HttpApplicationState class.
Table 3.14 - Properties of the HttpApplicationState Class
Property |
Description |
AllKeys |
Gets the collection of all the key names in the application state in a string array. |
Contents |
Gets a reference to the application state (HttpApplicationState) object. This provides compatibility with ASP. |
Count |
Gets the number of objects in the application state. |
Keys |
Gets the NameObjectCollectionBase.KeysCollection collection of all the key names in the application state. |
StaticObjects |
Gets all objects declared via an <object runat="server" scope="Application"></object> tag within the ASP.NET application. |
Table 3.15 - Methods of HttpApplicationState Class
Methods |
Description |
Add |
Adds a new object to the application state. |
Clear |
Removes all objects from the application state. |
Get |
Gets an object from the application state by key name or index. |
GetKey |
Gets an object from the application state by index. |
Lock |
Locks access to the application state object. This is used to prevent other clients from changing data stored in the application state. |
Remove |
Removes an object from the application state. |
RemoveAll |
Removes all the objects from the application state. Calls Clear() method internally. |
RemoveAt |
Removes an object from the application state at a particular index. |
Set |
Updates the value of an object stored in the application state. |
Unlock |
Unlocks the access to the application state. |
Step by Step 3.12 demonstrates the use of Application property to store applicationwide data.
STEP BY STEP 3.12 - Using the Application State
-
Add a new Web Form to the project. Name the Web Form StepByStep3-12.aspx. Change the pageLayout property of the DOCUMENT element to FlowLayout. Add a Label control named lblInfo to the Web Form.
-
Switch to the code view and add the following code in the Page_Load() event handler:
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' Lock the Application because the ' application state value needs to be modified Application.Lock() If Not Application("HitCount") Is Nothing Then ' Increment the HitCount variable ' stored in the application state Application("HitCount") = _ CInt(Application("HitCount")) + Else Application("HitCount") = End If ' Unlock the application now ' that the changes are done Application.UnLock() ' Display the hit count of this page by ' fetching the value from the HitCount key ' in the application state lblInfo.Text = "This page has been accessed " & _ Application("HitCount").ToString() + " times!"
End Sub
-
Set StepByStep3-12.aspx as the start page for the project.
-
Run the project. You should see that the page shows the number of times it is accessed. Refresh the page and you should see that the page accessed counter increments by 1 as shown in Figure 3.11.
Figure 3.11 Application state allows you to store global information.
-
Close this browser window. Open another browser window and browse to StepByStep3-12.aspx. You should see that the page retains the value of the counter and increments it by 1.
In Step by Step 3.12, I am modifying the contents of application state in between calls to the Application.Lock() and Application.UnLock() methods. Locking is important to keep the application state consistent when multiple users may want to modify its content concurrently. Although the application is locked, only the current user will be able to change the contents of the application state. That this locking mechanism can severely reduce the scalability of a Web application is one reason not to store any updateable data in application state.
In Chapter 15, you'll learn about an alternative way of maintaining global state for an application by using the application data cache. In fact, the application data cache provides all that application state offers and provides several other advanced features such as cache expiration policy. I recommend using application state only when you are migrating ASP applications to ASP.NET and want to write as little new code as possible. In all other cases and for all new ASP.NET application you should use the application data cache as your preferred choice for storing global data.
Review Break
ASP.NET uses a hidden input control named __VIEWSTATE to maintain state for all non-postback controls that are modified in the code. When ASP.NET executes a page, it collects values for all these controls and formats them into a single base64-encoded string. This string is then stored in the __VIEWSTATE control.
You can use the ViewState property of the Page class to store page level values. The ViewState property allows you to store structured data as long as the data is serializable.
ViewState is easily configurable. ASP.NET provides configuration schemes for disabling, tamper-proofing, or protecting the contents of the ViewState.
ASP.NET provides session state to store session specific data for each user. The session state can be scaled to support multiple Web servers in a Web farm with just minor configuration changes.
ASP.NET provides two ways to store data that is globally used throughout the application. One is Application state and the other is Application data cache. The application data cache provides all that application state offers and also provides several other advanced features such as a cache expiration policy.