Home > Articles

  • Print
  • + Share This
This chapter is from the book

State Management

Implement navigation for the user interface.

  • Manage the view state.

  • Use session state to manage data across pages.

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 roundtrips.

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 a big 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 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

  • View State

Query Strings

Query 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, where each key-value pair is separated by 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 its simplicity, query strings are widely used for passing a small amount of information to Web pages. However, query strings suffer the following limitations:

  • Most browsers restrict the length of the query string; this reduces the amount of data that you can embed in a URL.

  • Query strings do not provide any support for structured data types.

  • The information stored in a query string is not secure because it is directly visible to users in the browser's address field.

Reading information from query string in an ASP.NET program is easy using 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 shows you how query strings can be used for client-side state management.

STEP BY STEP

3.7 Using Query Strings in a Web Application

  1. 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.

  2. Add two Label controls, two TextBox controls (txtName, txtEmail), and a Button control (btnSubmit) on the Web form.

  3. Double-click the button control and add the following code in the Click event handler:

  4. private void btnSubmit_Click(object sender, 
      System.EventArgs e)
    {
      // Redirect to StepByStep3_7a.aspx page,
      // with a query string containing name and 
      // email appended to the URL
      Response.Redirect("StepByStep3_7a.aspx?Name=" + 
        txtName.Text + "&Email=" + txtEmail.Text);
    }
  5. 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.

  6. Add a Label control (lblInfo) to the Web form.

  7. Add the following code in the Page_Load() event handler:

  8. private void Page_Load(
      object sender, System.EventArgs e)
    {
      // If the query string collection contains Name
      if(Request.QueryString["Name"] != null)
      {
        // 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"];
      }
    }
  9. Set StepByStep3_7.aspx as the start page in the project.

  10. Run the project. Enter a name and an email 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 in 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.8Figure 3.8 The 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 addresses are embedded in the URL itself. Query string is a very effective way to pass small non-sensitive pieces of information.

Cookies

Cookies are small packets of information—each 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.

A cookie can be set to expire when a user session ends, or you can request that the browser persist the cookie on the user's computer for a specified period. 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:

  • Most browsers limit the size of information that you can store in a cookie. The typical size is 4,096 bytes with older browser versions and 8,192 bytes with the newer browser versions.

  • Some users configure their browsers to refuse cookies.

  • When you request that the browser persist a cookie on a user's computer for a specified period, the browser might override that request by using its own rules for cookie expiration.

  • Because cookies are stored at the client, they might be tampered with. You cannot trust 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 shows you how cookies can be used for client-side state management.

STEP BY STEP

3.8 Using Cookies to Maintain Client-Side State

  1. Make a copy of the Web form StepByStep3_1.aspx and change its name to StepByStep3_8.aspx. Open the ASPX file and the CS file and replace all occurrences of StepByStep3_1 with StepByStep3_8.

  2. Switch to the code view and add the following code above the existing code in the Page_Load() event handler:

  3. private void Page_Load(
      object sender, System.EventArgs e)
    {
      if(Request.Cookies["Name"] == null)
      {
        // If the Name cookie does not exist,
        // ask user to enter name 
        Response.Redirect("StepByStep3_8a.aspx");
      }
      else
      {
        // If cookie already exists, show
        // a personalized welcome message to the user
        lblName.Text="Welcome " + 
         Request.Cookies["Name"].Value;
      }
    ...
    }
  4. Double-click the Post button control and add the following code in the Click event handler:

  5. private void btnPost_Click(
      object sender, System.EventArgs e)
    {
      // Format the data entered by the user and
      // use the name of the user stored in a cookie
      // Append to it 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 + "</p>";
    }
  6. 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.

  7. Add a Label control, a TextBox control (txtName), a Button control (btnSubmit), and a CheckBox control (cbRemember) on the Web form.

  8. Double-click the Submit button control and add the following code in the Click event handler:

  9. private void btnSubmit_Click(object sender, 
      System.EventArgs e)
    {
      // Create a cookie called Name
      // Set the cookie with the Text of the text box
      HttpCookie cName = new HttpCookie("Name");
      cName.Value = txtName.Text;
      // Check if the checkbox remember me is checked
      if(cbRemember.Checked)
      {
        // 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);
      // Redirect the response to the message post page
      Response.Redirect("StepByStep3_8.aspx");
    }
  10. Set StepByStep3_8.aspx as the start page in the project.

  11. 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. You should see that your name is now posted along with the title of the message, as shown in Figure 3.9.

  12. Figure 3.1 Figure 3.9 Cookies can be used to provide personalization settings for individual users.

  13. Close this browser window. Open another browser window and browse to StepByStep3_8.aspx. Assuming that you checked the Remember Me check box in step 8, you should see the Weblog window personalized with your name.

Step by Step 3.8 demonstrates how cookies can be used to persist state across browser restarts. If you don't select the check box, 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. All modern browsers support hidden fields on a Web page. However, hidden fields have some limitations as mentioned in the following list:

  • Although information stored in a hidden field is not visible on the page, it is still part of the page's HTML code and users can see the value of a hidden field 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 the 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 those in 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 Weblog page created in Step by Step 3.1.

STEP BY STEP

3.9 Using Hidden Fields to Maintain Client-Side State

  1. Make a copy of the Web form StepByStep3_1.aspx and change its name to StepByStep3_9.aspx. Open the ASPX file and the CS file and replace all occurrences of StepByStep3_1 with StepByStep3_9.

  2. Place a Label control (lblPosts) and an HTML Hidden control (txtPosts) next to the Post button control on the form.

  3. Switch to the code view and modify the Click event handler of the btnPost control as follows:

  4. private void btnPost_Click(object sender, 
      System.EventArgs e)
    {
      // 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 + "</p>";
    
      // As one more post is added 
      // Increment the value of the hidden control
      Int32 intPostCount = 
        Int32.Parse(txtPosts.Value) + 1;
      txtPosts.Value = intPostCount.ToString();
      lblPosts.Text = "Total Posts: (" + 
        txtPosts.Value + ")";
    
    }
  5. Set StepByStep3_9.aspx as the start page in the project.

  6. Run the project. Make a few entries in the Weblog. You will see that with each entry in the Weblog, the total posts value is increased by 1, as shown in Figure 3.10.

Figure 3.10Figure 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 the hidden fields can be used to maintain state information. Here, because a hidden field is an input control, its value is posted back to the Web server with each page postback. The hidden fields can be used to store page scope values between roundtrips. 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 State

View state 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 view state to maintain state for non- control values in a page. However, it is important to note that the 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 Controls

Some 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 does not require any additional storage either on the client side or on the server side for maintaining state for the postback controls.

View State for Non-postback Controls

In addition to the postback controls, the view state mechanism of ASP.NET also retains values for non-postback 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 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=
"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 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, which therefore increases the amount of time it takes to load the page.

View State for Page-Level Values

The ViewState property of the Page class is a great place to store page-level values. View state will save these values just prior to rendering the page and will restore 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.

A good practice is to expose a page-level value as a property that internally manipulates the ViewState of the page. For example,

protected int NumberOfPosts
{
  get
  {
    if(ViewState["NumberOfPosts"] == null)
    {
      return 0;
    }
    else
    {
      return Convert.ToInt32(
        ViewState["NumberOfPosts"]);
    }
  }
  set
  {
    ViewState["NumberOfPosts"] = value;
  }
}

I'll use this technique in Step by Step 3.10 to maintain the number of posts on the Weblog using the view state.

STEP BY STEP

3.10 Using View State to Maintain State for Page-Level Values

  1. Make a copy of the Web form StepByStep3_1.aspx and change its name to StepByStep3_10.aspx. Open the ASPX file and the CS file and replace all occurrences of StepByStep3_1 with StepByStep3_10.

  2. Place a Label control (lblPosts) next to the button control on the form.

  3. Switch to the code view and add the following property to the class StepByStep3_10 definition:

  4. // get or set the number of posts in the Weblog
    protected int NumberOfPosts
    {
      get
      {
        if(ViewState["NumberOfPosts"] == null)
        {
          // The NumberOfPosts key is not
          // present in the ViewState
          return 0;
        }
        else
        {
          // Retrieve the NumberOfPosts key
          // from the ViewState
          return Convert.ToInt32(
              ViewState["NumberOfPosts"]);
        }
      }
      set
      {
        // Set the NumberOfPosts key in the ViewState
        ViewState["NumberOfPosts"] = value;
      }
    }
  5. Modify the event handler for the Click event of the btnPost control as shown here:

  6. private void btnPost_Click(
      object sender, System.EventArgs e)
    {
      // 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 + "</p>";
      // One more post is added 
      // Increment the value of NumberOfPosts
      // key in the Page's ViewState
      NumberOfPosts = NumberOfPosts + 1;
      lblPosts.Text = "Total Posts : (" + 
        NumberOfPosts + ")";
    }
  7. Set StepByStep3_10.aspx as the start page in the project.

  8. Run the project. Make a few entries in the Weblog. You should see that with each entry in the Weblog, the total posts value is increased by 1, just as it did in Step by Step 3.10.

  9. View the HTML code rendered in the Web browser. You'll note that the value associated with the __VIEWSTATE field increases as the size of the text in the lblWeblog control increases.

As you can see in Step by Step 3.10, 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 State

By default, view state is enabled in an ASP.NET application. As you have observed in Step by Step 3.10, the size of information stored in view state 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's size, you might want to disable view state 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 view state 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 can disable view state 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 can disable view state at the page level by setting the EnableViewState attribute of the Page directive to false in the ASPX page:

  • <%@ Page EnableViewState="false" %>
  • At the level of an application—If none of the pages in an application post back to themselves, you can disable view state at the application level by adding the following line to the web.config file:

  • <Pages EnableViewState="false"/>
  • At the level of the machine—In the unlikely case in which you want to disable view state for all applications running on a Web server, you can do so by adding the following statement to the machine.config file:

  • <Pages EnableViewState="false"/>
Protecting View State

To prevent malicious users from manipulating the view state, ASP.NET provides a way of knowing if somebody has modified the contents of the view state to fool your application. Using 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" />

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

This enables tamper proofing for all 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 page:

<%@ Page EnableViewStateMac="false"%>

Secure Only When Needed

Running security algorithms puts additional overhead on your Web server and makes applications slower. Therefore, you should enable security for view state only when it is a must.

However, this scheme just makes the view state tamper proof. It does not restrict the 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 readily decode the view state.

View State Security on a Web Farm

When securing the view state 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 autogenerated key with the <machineKey> setting in the machine.config file.

With only a few configuration changes, it's possible to instruct ASP.NET to encrypt the contents of view state using 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 Technique

Table 3.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 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 include in a query string.

 

 

No Security.

 

 

No options for persistence.

 

 

No support for storing structured values.

Cookies

State can be persisted on user's computer.

Some users disable cookies in their browsers.

 

Requires no postback operation.

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.

View State

Support for structured values.

Increases HTML size.

 

Involves less coding.

Works only when a page posts back to itself.

 

Easy configuration options for security.

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 a user spoofing or reading the session data is eliminated, but there is a disadvantage, too: These techniques use server resources, raising scalability issues.

ASP.NET supports server-side state management at two levels—at the level of the Web application using the application state, and at the level of a user session using the session state.

Session State

An 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 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 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 concepts of SessionID and session state are not unique to ASP.NET. ASP.NET's predecessor, ASP, also supported these features. However, session state in ASP was considered a flaw and many large sites wrote their own code for maintaining session state. 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 database.

Each ASP Web server maintains its own session state. This creates a problem in the Web farm scenario, where the user's requests can be dynamically routed to different servers 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 sessions do not work with browsers that don't support cookies or where the users have disabled cookies.

ASP.NET supports cookieless sessions by storing the SessionID in the URL itself by changing the application configuration.


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 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, where the key is of string type while the value can be any type derived from System.Object. Tables 3.12 and 3.13 explain properties and methods of the HttpSessionState class, respectively.

Table 3.12 Properties of the 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 cookieless 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 synchronized (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 enumeration—Off (disabled), InProc (default, session state is stored in process with aspnet_wp.exe), SqlServer (session state is stored in SQL Server), and StateServer (session state is 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 the 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 the 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

  1. Make a copy of the Web form StepByStep3_1.aspx and change its name to StepByStep3_11.aspx. Open the ASPX file and the CS file and change all occurrences of StepByStep3_1 with StepByStep3_11.

  2. Switch to code view and add the following code above the existing code in the Page_Load() event handler:

  3. private void Page_Load(
      object sender, System.EventArgs e)
    {
      if(Session["Name"] == null)
      {
        // The Name key is not present in the session
        // state, navigate to StepByStep3_11a page
        // to accept name of the user
        Response.Redirect("StepByStep3_11a.aspx");
      }
      else
      {
        // The Name key is present in the session
        // state, display a greeting
        lblName.Text="Welcome " + 
          Session["Name"].ToString();
      }
    ...
    }
  4. Double-click the Post button control and add the following code in the Click event handler:

  5. private void btnPost_Click(object sender, 
      System.EventArgs e)
    {
      // 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 + "</p>";
    }
  6. Add a new Web form to the project. Name the Web form StepByStep3_11a.aspx. Change the pageLayout property of the DOCUMENT element to FlowLayout.

  7. Add a Label control, a TextBox control (txtName), and a Button control (btnSubmit) to the Web form.

  8. Double-click the Submit button control and add the following code in the Click event handler:

  9. private void btnSubmit_Click(object sender, 
      System.EventArgs e)
    {
      // Add the Name entered in the Session
      // Redirect the response to the Weblog page
      Session["Name"] = txtName.Text;
      Response.Redirect("StepByStep3_11.aspx");
    }
  10. Set StepByStep3_11.aspx as the start page in the project.

  11. Run the project. You will see that you have been redirected to StepByStep3_11a.aspx. Enter a name and click the Submit button. You'll now see the 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).

  12. Close this browser window. Open another browser window and browse to StepByStep3_11.aspx. You should see that you have again been 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 non-persistent cookies, so this example only works if you are using a cookie-enabled browser. If you instead want to use a cookieless session, you'll have to modify the web.config file associated with this application to set the cookieless 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 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, where the key is a string type, and the value can be any type derived from System.Object. Tables 3.14 and 3.15 discuss properties and methods of the HttpApplicationState class, respectively.

Table 3.14 Properties of the HttpApplicationState Class

Property

Description

AllKeys

Gets the collection of all key names in the application state as 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 the HttpApplicationState Class

Property

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 a key 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 the 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 access to the application state.


Step by Step 3.12 demonstrates the use of Application property to store the application-wide data.

STEP BY STEP

3.12 Using the Application State

  1. 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.

  2. Switch to code view and add the following code in the Page_Load() event handler:

  3. private void Page_Load(
      object sender, System.EventArgs e)
    {
      // Lock the Application as the 
      // application state value needs to be modified
      Application.Lock();
      if(Application["HitCount"] != null)
      {
        // Increment the HitCount variable 
        // stored in the application state
        Application["HitCount"] = 
          (int) Application["HitCount"] + 1;
      }
      else
      {
        Application["HitCount"] = 1;
      }
      // Unlock the application as 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!";
    }
  4. Set StepByStep3_12.aspx as the start page in the project.

  5. Run the project. You should see that the page shows the number of times it has been accessed. Refresh the page, and you should see that the page access counter increments by 1 as shown in Figure 3.11.

  6. Figure 3.11Figure 3.11 Application state allows you to store global information.

  7. 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.

Note that the technique used in Step by Step 3.12 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 Step by Step 3.12, I modified the contents of 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 will be able to 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.

No Locking Needed for Application_Start() and Application_End()

There is no need to use the Application.Lock() and Application.Unlock() methods in the Application_Start() and Application_End() event handlers because these event handlers are only called just once during the lifetime of an application.

Later in this book in Chapter 15, you'll learn about an alternative way of maintaining global state for an application using the application data cache. In fact, the application data cache provides everything 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 minimal code. In all other cases and for all new ASP.NET applications, 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.

  • View state is easily configurable. ASP.NET provides configuration schemes for disabling, tamper proofing, or protecting the contents of the view state.

  • 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 provide two ways to store the data that is globally used throughout the application. One is the 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 cache expiration policy.

  • + Share This
  • 🔖 Save To Your Account