8.4. State


State is the current value of all the controls and variables for the current user in the current session. The Web is inherently a stateless environment, which means that every time a page is posted to the server and then sent back to the browser, the page is recreated from scratch. Unless you explicitly preserve the state of all the controls before the page is posted, the state is lost and all the controls are created with default values. One of the great strengths of ASP.NET is that it automatically maintains state for server controls both HTML and ASP. This section will explore how that is done and how you can use the ASP.NET state management capabilities.

ASP.NET manages three types of state :

  • View state (which is saved in the state bag)

  • Application state

  • Session state

Table 8-2 compares the different kinds of state.

Table 8-2. State types

Variables

View state

Application state

Session state

Uses server resources

No

Yes

Yes

Uses bandwidth

Yes

No

Depends

Times out

No

No

Yes

Security exposure

Yes

No

Depends

Optimized for nonprimitive types

No

Yes

Yes

Available for arbitrary data

Yes

Yes

Yes

Programmatically accessible

Yes

Yes

Yes

Scope

Page

Application

Session

Survives restart

Yes

No

Depends


The following sections will examine each type of state.

8.4.1. View State

The view state is the state of the page and all its controls. The view state is automatically maintained across posts by the ASP.NET Framework. When a page is posted to the server, the view state is read. Just before the page is sent back to the browser the view state is restored.

The view state is saved in the state bag (described in the next section) via hidden fields on the page that contain the state encoded in a string variable. Since the view state is maintained in standard html form fields, it works with all browsers.

If you don't need to maintain the view state for a page, you can boost performance by disabling view state for that page. For example, if the page does not post back to itself, or if the only control that needs to have its state maintained is populated from a database with every trip to the server, there is no need to maintain the view state for that page. To disable view state for a page, add the EnableViewState attribute with a value of False to the Page directive:

     <%@ Page Language="VB"  EnableViewState="false" %> 

The default value for EnableViewState is true.

The view state can be disabled for an entire application by setting the EnableViewState property to False in the <pages> section of the machine.config or Web.config configuration file.


It is also possible to maintain or disable view state for specific controls . This is done with the Control.EnableViewState property, which is a Boolean value with a default of true. Disabling view state for a control, just as for the page, will improve performance slightly. This would be appropriate, for example, in the situation where a control is populated from a database every time the page is loaded. In this case, the contents of the control would simply be overridden by the database query, so there is no point in maintaining view state for that control, especially if a lot of data is involved.

There are some situations where view state is not the best place to store data. If there is a large amount of data to be stored, then view state is not an efficient mechanism, since the data is transferred back and forth to the server with every page post. If there are security concerns about the data and it is not otherwise being displayed on the page, then including the data in view state increases the security exposure. Finally, view state is optimized only for strings, integers, Booleans, arrays, lists, and dictionaries. Other .NET types may be serialized and persisted in view state, but will result in degraded performance and a larger view-state footprint.

In some of these instances, session state might be a better alternative; on the other hand, view state does not consume any server resources and does not time out like session state.

8.4.2. State Bag

If there are values that are not associated with any control and you wish to preserve these values across roundtrips, you can store these values in the page's state bag . The state bag is a data structure containing attribute/value pairs, stored as strings associated with objects. The valid objects are the primitive data types integers, bytes, strings, Booleans, and so on. The state bag is implemented using the StateBag class, which is a dictionary object. You add or remove items from the state bag as with any dictionary object assigning a value to a "key," as shown below.

The state bag is maintained using the same hidden fields as the view state. You can set and retrieve values of things in the state bag using the ViewState keyword . To experiment with this, add another page to your application (or create a new application with the new page) named StateBagDemo.aspx. In either case, set the new page as the start page.

Between the <div> tags, write the word Counter: and drag a label onto the form, setting its ID to lblCounter and removing any Text attribute (or setting the text to blank through the Properties window).

Drag a button onto the form, set its ID to btn and set its text to Increment Counter. When you are done, the HTML in the source window should look like that in Example 8-2.

Example 8-2. Counter source
 <div>    Counter:    <asp:Label  runat="server"></asp:Label>    <asp:Button  runat="server" Text="Increment Counter" /> </div> 

You'll track the Counter as a property by adding the code shown in Example 8-3 to the code-behind.

Example 8-3. Counter property
 Public Property Counter( ) As Integer     Get         If (ViewState("intCounter") IsNot Nothing) Then             Return CInt(ViewState("intCounter")) 'extract from view state         Else             Return 0         End If     End Get     Set(ByVal value As Integer)         ViewState("intCounter") = value 'Add to view state     End Set End Property 

ViewState is the dictionary, "int Counter" is the key, and value is the value associated with that key. Override the OnLoad( ) method (as discussed above), adding the lines shown in bold in Example 8-4.

Example 8-4. Overriding the StateBagDemo form OnLoad event handler
 Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)     MyBase.OnLoad(e)     lblCounter.Text = Counter.ToString( )     Counter += 1 End 

StateBagDemo.aspx sets up a Counter that is maintained as long as the session is active. Every time the Increment Counter button is clicked, the page is reloaded, which causes the Counter to increment.

To make this work, you need to maintain state between postbacks. One way to do so is to store the value of the counter in a state bag. ASP.NET provides that state bag in its ViewState collection, which you access by indexing into it by name. In this example, you access the ViewState collection through the Counter Property. The property's get accessor casts the value stored in the ViewState to an integer, because ViewState stores objects.

Each time the page is loaded, you display the value of the Counter property and then increment it by 1:

     Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)         MyBase.OnLoad(e)         lblCounter.Text = Counter.ToString( )         Counter += 1     End Sub 

In the Get block of the Counter property, the contents of the statebag named intCounter are tested to see if anything is there:

     If (ViewState("intCounter") IsNot Nothing) Then 

If the intCounter state bag is not empty, the value stored is returned; otherwise, the value 0 is returned. To retrieve the value, you access it by name, but you must cast the object back to an integer to use it in your program.

     If (ViewState("intCounter") IsNot Nothing) Then         Return CInt(ViewState("intCounter"))     Else         Return 0     End If 

In this and in all programs in this book Option Strict is always set to TRue. Unfortunately, the default is False, but good object-oriented, type-safe programming requires that you set this to true to enlist the compiler in helping you find type-cast errors.


8.4.3. Session State

While an application is running, there will be many sessions. A session is a series of requests coming from a single browser client in a more or less continuous manner. If there are no requests from that client within a specified period of time (the timeout period), then the session ends. The default timeout period is 20 minutes.

As noted above, the Web is an inherently stateless environment. The HTTP protocol has no means of identifying which requests should be grouped together in the same session. A session must be imposed on top of HTTP. ASP.NET provides session state with the following features:

  • Works with browsers that have had cookies disabled.

  • Identifies if a request is part of an existing session.

  • Stores session-scoped data for use across multiple requests. This data persists across server restarts and works in multiprocessor (web garden) and multimachine (web farm) environments, as well as in single-processor, single-server situations.

  • Automatically releases session resources if the session ends or times out.

Session state is stored in server memory separately from the ASP.NET process. This means that if the ASP.NET process crashes or is restarted, the session state is not lost. Session state can also be stored on a dedicated and shared machine or even within a database.

Sessions are identified and tracked with a 120-bit SessionID that is passed from client to server and back using either an HTTP cookie or a modified URL, depending on how the application is configured. The SessionID is handled automatically by the .NET Framework; there is no need to manipulate it programmatically. The SessionID consists of URL-legal ASCII characters that have two important characteristics:

  • They are unique, so there is no chance of two different sessions having the same SessionID.

  • They are random, so it is difficult to guess the value of another session's SessionID after learning the value of an existing session's SessionID.

Session state is implemented using the Contents collection of the HttpSessionState class. This collection is a (key-value) dictionary containing all the session state dictionary objects that have been directly added using code.

To see session state at work, create a new page SessionState.aspx (either in this application or in a new application) and set it to be the start page.

Drag a RadioButtonList onto your page, set its ID to rbl and use the smart tag to edit the items. Add three items. The first has the text .NET and the value n, the second has the text Databases and the value d, and the third has the text Hardware and the value h, as shown in Figure 8-31.

Figure 8-31. Adding three items to RadioButtonList


Also add a button, and set its ID to btn and its Text to Submit. Add a label control (id=lblMsg), and a drop-down list with the ID ddl. Set its Visible property to False.

You're all set. Now just change to Code view and implement a handler for the button's Click event, and one for the SelectedIndexChanged event in the RadioButtonList control. The complete source for these methods is shown in Example 8-5.

Example 8-5. SessionState.aspx.vb
 Partial Class SessionState_aspx     Inherits System.Web.UI.Page     Protected Sub btn_Click( _     ByVal sender As Object, _     ByVal e As System.EventArgs) Handles btn.Click         If (rbl.SelectedIndex = -1) Then             lblMsg.Text = "You must select a book category."         Else             Dim sb As StringBuilder = New StringBuilder( )             sb.Append("You have selected the category ")             sb.Append(CStr(Session("cattext")))             sb.Append(" with code """)             sb.Append(CStr(Session("catcode")))             sb.Append(""".")             lblMsg.Text = sb.ToString( )             ddl.Visible = True             Dim CatBooks() As String = CType(Session("books"), String( ))             '  Populate the DropDownList.             Dim i As Integer             ddl.Items.Clear( )             For i = 0 To CatBooks.GetLength(0) - 1                 ddl.Items.Add(New ListItem(CatBooks(i)))             Next         End If     End Sub     Protected Sub rbl_SelectedIndexChanged( _     ByVal sender As Object, _     ByVal e As System.EventArgs) Handles rbl.SelectedIndexChanged         If (rbl.SelectedIndex <> -1) Then             Dim Books(3) As String             Session("cattext") = rbl.SelectedItem.Text             Session("catcode") = rbl.SelectedItem.Value             Select Case (rbl.SelectedItem.Value)                 Case "n"                     Books(0) = "Programming Visual Basic 2005"                     Books(1) = "Programming ASP.NET"                     Books(2) = "C#: A Developer's Notebook"                 Case "d"                     Books(0) = "Oracle & Open Source"                     Books(1) = "SQL in a Nutshell"                     Books(2) = "Transact-SQL Programming"                 Case "h"                     Books(0) = "PC Hardware in a Nutshell"                     Books(1) = "Dictionary of PC Hardware and " + _                        "Data Communications Terms"                     Books(2) = "Linux Device Drivers"             End Select             Session("books") = Books         End If     End Sub End Class 

Look first at rbl_SelectedIndexChanged, the RadioButtonList event handler. After testing to ensure that something is selected, rbl_SelectedIndexChanged defines a string array to hold the lists of books in each category. Then it assigns the selected item Text and Value properties to two Session dictionary objects.

     Session("cattext") = rbl.SelectedItem.Text     Session("catcode") = rbl.SelectedItem.Value 

The first line stores the text of the selected item in session state using the key "cattext."

rblSelectedIndexChanged next uses a Select Case statement to fill the previously declared string array (Books) with a list of books, depending on the book category selected. Finally, the method assigns the string array to a Session dictionary object.

     Session("books") = Books 

This example stores only strings and an array in the Session dictionary objects. However, you can store any object that inherits from ISerializable. These include all the primitive data types and arrays comprising of primitive data types, as well as the DataSet, DataTable, HashTable, and Image objects. This allows you to store query results, for example, or a collection of items in session state to implement a user's shopping cart.

The other event-handler method, btn_Click, is called whenever the user clicks on the Submit button. It first tests to verify that a radio button has been selected. If not, then the Label is filled with a warning message.

     If (rbl.SelectedIndex = -1) Then        lblMsg.Text = "You must select a book category." 

The Else clause of the If statement is the meat of this page. It retrieves the Session dictionary objects and uses the StringBuilder class to concatenate the strings into a single string for display in the Label control.

     dim sb as StringBuilder = new StringBuilder( )     sb.Append("You have selected the category ")     sb.Append(Cstr(Session("cattext")))     sb.Append(" with code """)     sb.Append(Cstr(Session("catcode")))     sb.Append(""".")     lblMsg.Text = sb.ToString( ) 

The btn_Click method also unhides the DropDownList that was created and made invisible in the HTML portion of the page. The method then retrieves the string array from the Session dictionary object and populates the DropDownList.

     ddl.Visible = true     dim CatBooks( ) as string= CType(Session("books"), string( ))     '  Populate the DropDownList.     dim i as integer     ddl.Items.Clear( )     for i = 0 to CatBooks.GetLength(0) - 1        ddl.Items.Add(new ListItem(CatBooks(i)))     next 

Because the Page directive in the VB.NET example sets Strict="true", it is necessary to explicitly cast the Session dictionary object containing the string array from object to type string array using the CType function. The results are shown in Figure 8-32.

Figure 8-32. Session state demonstration


As you look at this example, you might wonder what advantage is gained here by using session state, rather than just using the programmatically accessible control values. The answer is that since this example is fairly trivial, no advantage is gained. However, in a real-life application with many different pages, session state provides an easy method for values and objects to be passed from one page to the next, with all the advantages listed at the beginning of this section.

8.4.4. Session-State Configuration

The configuration of session state is controlled on a page-by-page basis by entries in the Page directive at the top of the page. On an application-wide basis, it is controlled by a file called Web.config, typically located in the virtual root directory of the application.

Session state is enabled by default. You can enable session state for a specific page by adding the EnableSessionState attribute to the Page directive, as in the following VB Page directive:

     <%@ Page Language="VB" Strict="true" EnableSessionState="true"%> 

To disable session state for the page you would use:

     <%@ Page Language="VB" Strict="true" EnableSessionState="false"%> 

To enable session state in a read-only mode that is, values can be read but not changed use the ReadOnly value of EnableSessionState, as in:

     <%@ Page Language="VB" Strict="true" EnableSessionState="ReadOnly"%> 

(All of the values for EnableSessionState are case-insensitive.) The reason for either disabling session state or making it read-only is performance. If you know that you will not be using session state on a page, you can gain a performance boost by disabling it.

If the ASP.NET process crashes or is restarted, the session state is not lost. In addition to unplanned outages, ASP.NET can be configured to periodically perform a preventive restart of each process after a specified number of requests or after a specified length of time, improving availability and stability (this is configurable in machine.config and/or Web.config).

Web.config is an XML file and as such it must be well-formed . The values are case-sensitive, and the file consists of sections delimited by tags. The session-state configuration information is contained within the <system.web> section, which is contained within the <configuration> section. Thus, a typical session-state configuration snippet will look something like Example 8-6.

Example 8-6. Code excerpt from Web.config
 <?xml version="1.0" encoding="utf-8" ?> <configuration>   <system.web> . . .    <sessionState            mode="InProc"            cookieless="false"            timeout="20"            stateConnectionString="tcpip=127.0.0.1:42424"            sqlConnectionString="data source=127.0.0.1;userid=sa;password="    /> 

There are five possible attributes for the sessionState section:


mode

Specifies whether the session state is disabled for all the pages controlled by this copy of Web.config, and, if enabled, where the session state is stored. Table 8-3 lists the permissible values.

Table 8-3. Possible values for the mode attribute

Values

Description

Off

Session state is disabled.

Inproc

Session state is stored in-process on the local server. This is the default value.

StateServer

Session state is stored on a remote server. If this attribute is used, then there must also be an entry for stateConnectionString, specifying which server to use to store the Session state.

SqlServer

Session state is stored on a SQL Server. If this attribute is used, then there must also be an entry for sqlConnectionString, which specifies how to connect to the SQL Server. The SQL Server used can either be on a local or remote machine.


Storing the session state Inproc is the fastest and is well-suited to small amounts of volatile data. However, it is vulnerable to machine crashes and is not suitable for web farms (multiple servers) or web gardens (multiple processors on a single machine). For these cases, you should use either StateServer or SqlServer. SqlServer is the most robust for surviving crashes and restarts.


cookieless

Cookies are used with session state to store the SessionID so that the server knows which session it is connected to. The permissible values of cookieless are true and False, with False being the default. In other words, the default behavior is to use cookies. However, if the client browser either does not support cookies or has had cookie support turned off by the user, then any attempt at saving and retrieving session state will be lost. To prevent this, set cookieless to true.

If cookieless is set to TRue, then the SessionID is persisted by adding a value to the URL.


timeout

Specifies the number of minutes of inactivity before a session times out and is abandoned by the server. The default value is 20.


stateConnectionString

Specifies the server and port used to save the session state. It is required if mode is set to StateServer. Use of a specific server for saving state enables easy and effective session-state management in web-farm or web-garden scenarios. An example of a stateConnectionString is:

     stateConnectionString="tcpip=127.0.0.1:42424" 

In this example, a server with an IP address of 127.0.0.1 would be used. This happens to be localhost, or the local machine. The port is 42424. For this to work, the server being specified must have the ASP.NET State service started (accessible via Control Panel/Administrative Tools/Services) and must have the specified port available for communications (that is, not disabled or blocked by a firewall or other security measure).


sqlConnectionString

Specifies a connection string to a running instance of SQL Server. It must be set if mode is set to SqlServer. Similar to stateConnectionString in that it lends itself to use with web farms and gardens, it also will persist despite crashes and shutdowns. The session state is saved in SQL tables indexed by SessionID.

8.4.5. Session-Scoped Application Objects

One additional way of providing information across the session is through the use of static objects, which are declared in the global.asax file. Once declared with the Scope attribute set to Session, the objects are accessible to the session by name anywhere within the application code.



Programming Visual Basic 2005
Programming Visual Basic 2005
ISBN: 0596009496
EAN: 2147483647
Year: 2006
Pages: 162
Authors: Jesse Liberty

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net