Chapter 17. Maintaining Application State

Variables within a Web Form Page do not retain their values between requests. Requesting a Web Form Page is similar to starting and stopping an application. After the page is finished being processed, you must start all over again with a blank slate.

If you need to maintain the value of a variable across multiple page requests, you need to do something special. In this chapter, you learn about three methods of maintaining the state of variables. You will learn

  • How to use View State to retain the state of variables for a particular page

  • How to use Session State to retain the state of variables for a particular user

  • How to use Application State to retain the state of variables for a particular application

Using View State

View State enables you to preserve the state of a page when posting the page back to itself. It’s important to understand that View State does not work when posting from one page to another. You can only take advantage of View State when performing postbacks.

Let’s create a simple page that illustrates how View State works. We’ll preserve the state of a Label control.

  1. Create a Web Form Page named ShowViewState.aspx.

  2. Add Web Form TextBox, Button, and Label controls to the page. Clear the text in the Label control.

  3. Double-click the Button control to switch to the Code Editor and add a Button1_Click event handler.

  4. Enter the following code for the Button1_Click handler:

    C#

    private void Button1_Click(object sender, System.EventArgs e)
    {
      Label1.Text += "<li>" + TextBox1.Text;
    }
    

    VB.NET

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    VB.NET Handles Button1.Click
      Label1.Text &= "<li>" & TextBox1.Text
    End Sub
    
  5. Right-click ShowViewState.aspx in the Solution Explorer window and select Build and Browse.

After the page opens, enter some text in the text box and click the button. You should notice that every time you submit new text, the text is appended to the list of items displayed by the Label (see Figure 17.1). The previous text added to the label is preserved between page requests through View State.

Label contents preserved with View State.

Figure 17.1. Label contents preserved with View State.

Every Web Form control automatically preserves the values of all of its properties through View State. For example, if you select an item in a list box and post the page containing the ListBox control back to the server multiple times, the same list item will continue to be selected. The value of a List control’s SelectedItem property is automatically retained through View State.

View State also applies to the items displayed in a DataGrid. You only need to load data from a database into a DataGrid once. If you post the page containing the DataGrid back to itself, the DataGrid will not lose its data. A DataGrid automatically retains the values of all of its rows in View State.

How View State Really Works

View State works by taking advantage of a hidden form field that is automatically added to every Web Form Page. You can see this hidden form field if you select View Source when displaying a Web Form Page in a browser. For example, the View State hidden form field looks like the following when I click View Source for the ShowViewState.aspx page:

<input type="hidden" name="__VIEWSTATE"
value="dDwxNTg0NTEzNzMyO3Q8O2w8aTwxPjs+O2w8dDw7bDxpPDE+Oz47bDx0PHA
8cDxsPFRleHQ7PjtsPExhYmVsXDxsaVw+aGVsbG9cPGxpXD5taWxrOz4+Oz47Oz47P
j47Pj47PgIWH/qU4XKz/lwgBle3On0unW/h" />

Immediately before a page is rendered, the values of the properties of all controls in a page are converted into a string. When the page is rendered, this string is assigned to the hidden__VIEWSTATE form field. When the page is posted back to the server, the string is parsed and all the values are reassigned to the properties of the controls in the page.

Note

If you want to know the messy details, View State is saved right after the PreRender event and before the Render method is called. View State is loaded right after the Init event and before the Load event. You can modify the way in which View State is saved and loaded by overriding a control’s SaveViewState and LoadViewState methods.

Disabling View State

View State can be both a blessing and a curse. View State enables you to magically retain the state of all the controls on a page. However, the hidden VIEWSTATE form field can become very large, which can slow down the rendering of a page.

You don’t always need to take advantage of View State. If you don’t need to preserve the state of controls across post backs, you don’t need to use View State.

For example, suppose that you have a Web Form Page that displays all the products in the Products database table in a DataGrid. The information about all the products is automatically stuffed into View State. If you are simply viewing the data in the DataGrid, you don’t really need to do this. You only need to preserve the state of a DataGrid when performing such operations as sorting, editing, or paging a DataGrid. If you are only viewing the data, the View State consumed by the DataGrid is a waste of bandwidth.

You can disable View State for any control by assigning the value False to its EnableViewState property. You should always disable View State for controls such as the Repeater, DataList, and DataGrid controls when you are simply displaying data.

You also can disable View State for all the controls in a page by using the DOCUMENT EnableViewState property. To disable View State for a page, select DOCUMENT in the Properties window and assign the value False to the EnableViewState property.

Finally, you can disable View State for an entire application (or particular directory or file in an application) within the Web.Config file. Add the following tag to the System.Web section of the Web.Config file:

<pages enableViewState="false" />

Note

The enableViewState attribute in the Web.Config file overrides the enableViewState property for a page. So, disabling View State in the Web.Config file prevents any page from using View State in an application.

You can display the amount of View State that each control in a page is consuming by enabling tracing for a page. In the Properties window, select DOCUMENT and assign the value True to the Trace property. If you build and browse the page, you’ll see the amount of View State associated with each control in the Control Tree section appended at the bottom of the page (see Figure 17.2).

Viewing View State statistics.

Figure 17.2. Viewing View State statistics.

Note

You’ll notice that if you disable View State for a page, the Page control will still consume a little bit of View State. If you want to entirely disable View State, you need to remove the server-side <form> tag from the HTML source of the page.

Adding Custom Information to View State

You can add your own data to View State by taking advantage of the ViewState collection. Any data that you add to the ViewState collection will be stuffed into the __VIEWSTATE hidden form field and will be preserved across postbacks.

For example, the following statement adds the string “Hello World” to the ViewState collection:

C#

ViewState[ "myItem" ] = "Hello World";

VB.NET

ViewState("myItem") = "Hello World"

After an item has been added to the ViewState collection, you can retrieve the item by passing the name of the item to the collection:

C#

Response.Write( ViewState[ "myItem" ] );

VB.NET

Response.Write(ViewState("myItem"))

Warning

The ViewState collection is case sensitive, so adding an item named myItem is different from adding an item named MyItem.

You can add almost any object to the ViewState collection, including strings, integers, ArrayLists, Hashtables, and even DataSets. The only requirement is that the object must be serializable.

However, remember that anything you add to View State must be stuffed into the __VIEWSTATE hidden form field. Consequently, adding a DataSet to View State can significantly impact the rendering time for a page. In general, you should stick to objects that have optimized View State serializers—strings, integers, Booleans, arrays, ArrayLists, and Hashtables.

Protecting View State

By default, View State is not encrypted. In theory, anyone requesting a page can copy the page to their local hard drive, modify the value of the hidden __VIEWSTATE form field, and submit the modified page back to the server.

For example, if you are storing a shopping cart in View State, someone could modify the price of all the products in the shopping cart and submit the modified page. A great way for users to give themselves massive discounts!

You can protect the integrity of View State by adding a Message Authentication Code (MAC) to the hidden __VIEWSTATE form field. After the View State MAC is enabled, an exception is thrown if someone tampers with the View State.

You can enable the View State MAC for a particular Web Form Page by selecting DOCUMENT in the Properties window and assigning the value True to the EnableViewStateMAC property. You can enable the View State MAC for an application or directory by adding the following tag to the System.Web section of the Web.Config file:

<pages enableViewStateMac="true" />

The View State MAC is disabled by default. Enabling the View State MAC adds some extra work to the processing of the page, so it has an impact on performance. If you don’t need it, don’t enable it.

Enabling the View State MAC does not result in the View State being encrypted. If you want to encrypt the contents of View State, you need to enable the View State MAC and perform an additional step. You need to add the following tag to the System.Web section of the Web.Config file:

<machineKey validation="3DES" />

This tag causes all View State to be encrypted using the Triple Data Encryption Standard. Again, this has an impact on performance, so don’t enable it unless you need it.

Using Session State

Session State enables you to preserve the values of variables across page requests for a particular user. Session State is typically used for storing shopping carts, user preferences, or user security information, such as usernames and passwords.

Items added to Session State are preserved for the duration of a user’s visit to a Web site. The server detects that the user has left when the user does not request a page for more than 20 minutes. At that point, all of the user’s Session State information is automatically destroyed.

Note

You can change the default timeout period for Session State from 20 minutes to another value. You can modify the timeout period in code by setting the Timeout property of the Session object to a value in minutes. You can also modify the timeout period in the Web.Config file by modifying the value of the timeout attribute of the <sessionState> tag.

Items that you add to Session State are stored in the Web Server’s memory. You can add almost any type of object to Session State, including strings, integers, ArrayLists, Hashtables, DataSets, and DataTables. The only requirement is that the object be serializable.

To illustrate how Session State works, we’ll create two Web Form Pages. In the first page we’ll add an item to Session State, and on the next page we’ll retrieve and display the value of that item. These pages will illustrate how Session State preserves information when a user navigates from page to page.

To create the first page, do the following:

  1. Create a new Web Form Page named Session1.aspx.

  2. Add a HyperLink control to the page and set the following properties:

    Property

    Value

    Text

    Click Here

    NavigateUrl

    Session2.aspx

  3. Switch to the Code Editor by selecting Code from the View menu.

  4. Enter the following code for the Page_Load handler:

    C#

    private void Page_Load(object sender, System.EventArgs e)
    {
      Session[ "myItem" ] = "Hello!";
    }
    

    VB.NET

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
    VB.NET MyBase.Load
      Session("myItem") = "Hello!"
    End Sub
    

The Session1.aspx page adds a single item named myItem to Session State.

Now, let’s create a second page that retrieves that item and displays it:

  1. Create a Web Form Page named Session2.aspx.

  2. Add a Label control to the page.

  3. Switch to the Code Editor by selecting Code from the View menu.

  4. Enter the following code for the Page_Load handler:

    C#

    private void Page_Load(object sender, System.EventArgs e)
    {
      Label1.Text = (string)Session[ "myItem" ];
    }
    

    VB.NET

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
    VB.NET MyBase.Load
      Label1.Text = Session("myItem")
    End Sub
    
  5. Right-click the Session1.aspx page in the Solution Explorer window and select Build and Browse.

When the Session1.aspx page opens, you’ll see a link to the Session2.aspx page (see Figure 17.3). If you click the link, the Session2.aspx page will display the value of the Session State item named myItem (see Figure 17.4). After an item has been added to Session State, the item is available on any other Web Form Page that the user visits.

The Session1.aspx page.

Figure 17.3. The Session1.aspx page.

The Session2.aspx page.

Figure 17.4. The Session2.aspx page.

Configuring Out-of-Process Session State

By default, Session State is stored in the same process as the Web server. In other words, when you add an item to Session State, it’s added to the same memory being used by the Web server process. This has several bad consequences.

If the Web server process is stopped or becomes corrupted, all Session State information is lost. For example, if you are storing shopping carts in Session State and your Web server crashes, all the shopping carts will disappear.

Furthermore, because in-process Session State is stored on a particular Web server, you can’t load balance requests across multiple servers. In other words, if you use inprocess Session State, you can’t create a Web farm. This restriction limits the scalability of your Web application.

ASP.NET supports two out-of-process forms of Session State that get around these two problems. You can store Session State in either an external Windows Service or an external database table. Enabling out-of-process Session State makes Session State more reliable and more scalable.

Note

You might be wondering why Session State is not configured to be out-of-process by default. The reason is performance. Storing Session State in an external Windows Service or database table is slower than in-process Session State.

Storing Session State in a Windows Service

You can store Session State in an external Windows Service running on the same machine as the Web server or on a different machine on your network. There are two configuration steps that you must complete to store Session State in a Windows NT Service:

  1. Start the ASP.NET State Service

  2. Modify the Web.Config file

The ASP.NET State Service is automatically installed on your machine when you install Visual Studio .NET. By default, it is not running. Do the following to start the State Service:

  1. Go to Start, open the Control Panel, select Administrative Tools, and launch the Services applet.

  2. Find the ASP.NET State Service applet and click Start. On a production Web site, you’ll need to modify the service to startup automatically.

Next, you need to modify the Web.Config file to configure Session State to use the ASP.NET State Service. In the application root Web.Config file, find the <sessionState> tag and modify it as follows:

<sessionState
  mode="StateServer"
  stateConnectionString="tcpip=127.0.0.1:42424"
  stateNetworkTimeout="10" />

This setting causes Session State to use the ASP.NET State Service instead of in-process Session State. Furthermore, it specifies that the State Service can be found on the local machine at port 42424. You can specify an IP address or hostname of another server on your network here. Finally, a connection timeout value of 10 seconds is supplied.

You can test whether the State Service is running by opening the Session1.aspx page that we created in the first part of this section. After the page opens in your browser, open a command prompt and execute the following command:

iisreset

This command will stop and start the Web service. Next, click the link to go to the Session2.aspx page. You should notice that the item added to Session State is not lost. The text Hello! appears in the Label control, even though you stopped and started the Web service.

Storing Session State in a SQL Server Database

The most reliable, and slowest, method of storing Session State is to use a SQL Server database. When you store Session State in an external database, the state information is kept in a temporary database table.

Note

You can store Session State information only with a Microsoft SQL Server database (version 7.0 or later). It doesn’t work with Oracle or Microsoft Access.

Configuring SQL Server Session State requires completing the following two steps:

  1. Run the SQL State Installation script to create the necessary database objects.

  2. Modify the Web.Config file.

The SQL State Installation script is automatically installed on your computer when you install Visual Studio .NET. You can execute this script by doing the following:

  1. Launch Query Analyzer by going to Start, Programs, Microsoft SQL Server.

  2. Select Open from the File menu and browse to the following file:

    WinntMicrosoft.NETFrameworkVersionInstallSqlState.sql
    
  3. Execute the SQL script by clicking Execute Query (the green VCR run button).

The SQL State Installation script adds a new database to SQL Server named ASPState. The script adds several stored procedures for managing Session State to this database.

The actual Session State information is stored in two database tables in the TempDB database named AspStateTempApplications and AspStateTempSessions. The AspStateTempApplications table contains a list of all the ASP.NET Web Applications that are using the database to store Session State. The AspStateTempSessions includes a row that corresponds to each user’s Session State information.

Before you can use SQL State, you need to modify the application root Web.Config file. Find the <sessionState> tag and modify it as follows:

<sessionState
  mode="SQLServer"
  sqlConnectionString="data source=127.0.0.1;user id=sa;password=secret" />

The important attribute here is the sqlConnectionString attribute. You’ll need to enter the correct password for your database.

You can test SQL Server Session State by opening the Session1.aspx page that we created at the beginning of this section. After you open the page, a new row will be added to the AspStateTempSessions table. You can view the row by executing the following command from Query Analyzer:

SELECT * FROM tempDB..AspStateTempSessions

There is one row per user in the AspStateTempSessions table. When you add objects to Session State, the objects are serialized and stored in either the SessionItemShort or SessionItemLong column. For example, after opening the Session1.aspx page, the text Hello! is stored in the SessionItemShort column. If a user’s Session State information becomes too long, the state information is stored in the SessionItemLong column instead of the SessionItemShort column.

Enabling Cookieless Sessions

By default, Session State relies on browser cookies. When you first request a Web Form Page from an ASP.NET Web Application, the server automatically adds a cookie to your browser called the ASP.NET_SessionID cookie. The server uses that cookie to identify you when you request a new page.

Session State depends on this cookie to associate the right Session State information with the right user. If cookies are disabled on a browser, Session State will fail. The Web server will assume that you are a new user each and every time that you request a new page.

When you are creating a public Web application, it’s dangerous to rely on cookies. For a variety of reasons, cookies don’t always work. This means that Session State will not always work.

Fortunately, there is a way around this problem. Session State supports something called Cookieless Sessions. As the name implies, you can use Cookieless Sessions to maintain Session State without relying on browser cookies.

You can enable Cookieless Sessions by modifying a single attribute in the Web.Config file. Find the <sessionState> tag in the application root Web.Config file and modify it as follows:

<sessionState
  cookieless="true" />

Cookieless Sessions are compatible with both in-process and out-of-process Session State, so you can use Cookieless Sessions regardless of whether you are storing state information in process or in a database table.

You can test Cookieless Sessions by opening the Session1.aspx page that we created at the beginning of this section. When the page opens, you should notice that the contents of the address bar look a little strange. The address bar should look something like the following:

http://localhost/myApp/(rtobxqzq5cjkswbtmpgj0×45)/Session1.aspx

The string of characters between the parentheses is the current Session ID. When you click the link in the Session1.aspx page, this Session ID is passed to the Session2.aspx page in the URL. The Web server can identify you without using cookies as you move from page to page by extracting this Session ID.

You should be aware that Cookieless Sessions do not work in exactly the same way as normal Session State. Normally, when you open multiple instances of a browser when visiting a Web site, all browser instances share the same Session State. On the other hand, if you open multiple browser instances when using Cookieless Sessions, the Session State information will not be shared.

Cookieless Sessions also force you to design your pages in a particular way. If you want to take advantage of Cookieless Sessions, you need to make all the links in your pages use relative URLs. If you add an absolute URL, the Session ID information will be lost.

Tip

You can use the Response.AppPathModifier() method to automatically build a URL that contains the Session ID. For example, this method is useful when you need to build an absolute URL to link to a secure Web Form Page (using https://).

Using Application State

There’s one last form of state that’s left to be discussed in this chapter—Application State. Whereas View State is scoped to a particular page and Session State is scoped to a particular user, Application State is scoped to an entire application. In other words, any items that you add to Application State are available within any page and by any user within an application.

In the ASP.NET world, an application is defined by a virtual directory. All the Web Form Pages located under the same virtual directory live in the same application. That means that if you add an item to Application State, that item is available within any other page beneath the virtual directory.

Application State is similar to the Cache object (for more information on the Cache object, see Chapter 14, “Improving Application Performance with Caching”). You can use either object to store data in memory. In most situations, you should use the Cache object instead of Application State for the following reasons:

  • Items are automatically dumped from the Cache when memory resources become low. Items are never automatically removed from Application State. If you add too much data to Application State, the entire application is restarted.

  • The Cache object automatically handles synchronizing access to items stored in the Cache. When using Application State, you must manually lock and unlock items to prevent conflicts.

  • The Cache object supports advanced functionality, such as expiration policies and file dependencies that are not supported by Application State.

Again, whenever you are tempted to use Application State, consider using the Cache object instead. Application State is mainly a holdover from ASP Classic.

With these warnings in mind, let’s look at a simple example of using Application State. We’ll create a page that automatically keeps track of the number of times that it has been requested.

  1. Create a Web Form Page named TrackAccess.aspx.

  2. Add a Label control to the page.

  3. Switch to the Code Editor by selecting Code from the View menu.

  4. Enter the following code for the Page_Load handler:

    C#

    private void Page_Load(object sender, System.EventArgs e)
    {
      Application.Lock();
      if (Application[ "AccessCount" ] == null)
        Application[ "AccessCount" ] = 1;
      else
        Application[ "AccessCount" ] = (int)Application[ "AccessCount" ] + 1;
      Application.UnLock();
      Label1.Text = Application[ "AccessCount" ].ToString();
    }
    

    VB.NET

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
    VB.NET MyBase.Load
      Application.Lock()
      Application("AccessCount") += 1
      Application.UnLock()
      Label1.Text = Application("AccessCount")
    End Sub
    
  5. Right-click the TrackAccess.aspx page in the Solution Explorer window and select Build and Browse.

When the page opens, click the browser Refresh button a couple times. Each time the page is requested, the value of the AccessCount variable is incremented by one (see Figure 17.5). The value of this variable is stored in Application State between page requests.

The TrackAccess.aspx page.

Figure 17.5. The TrackAccess.aspx page.

Unlike View State or Session State, items in Application State can be accessed by multiple users at a time. Consequently, you must take special precautions when accessing items from Application State.

Notice the use of the Lock() method in the TrackAccess.aspx page. The Lock() method prevents read and write access by other sessions while AccessCount is being updated. You can’t lock an item in Application State selectively. You must lock all items in Application State to lock a single item.

After Lock() is called, every other session must wait until UnLock() is called to access any item from Application State. For this reason, you should call UnLock() as quickly as possible in your code. If you forget to call UnLock(), this method is automatically called after the page has been processed.

Summary

In this chapter, you learned three methods of maintaining state in your application. In the first section, you learned how to use View State to preserve the state of controls and variables when posting back to the same page.

Next, you learned how to use Session State to maintain state during the lifetime of a user session. You learned how to store Session State in the Web server process, in a Windows NT Service, and in an external database.

Finally, we briefly examined the topic of Application State. You learned how to use Application State to store information that can be accessed within any page and by any user of an application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset