6.2. Maintaining Information about a User Throughout a Session

Problem

You want to make personalized information available to the users of your application for as long as each remains active, without having to access a database each time the information is needed and regardless of the number of pages traversed.

Solution

Create a class in which to store the personalized data, instantiate the class and load the data, store the data object in the Session object, and then access the data from the Session object as required.

In the code-behind class for your ASP.NET pages that need access to the data, use the .NET language of your choice to:

  1. Check to see if the object used to store the personalized data exists in the Session object.

  2. If the object exists, retrieve the object from Session. If the object does not exist, instantiate the class used for the personalized data and store it in the Session object.

  3. Use the data as required in your application.

A simple example that illustrates this solution is shown in Examples Example 6-6 through Example 6-10. The example uses the class shown in Example 6-6 (CH06PersonalDataVB for VB) and Example 6-7 (CH06PersonalDataCS for C#) to provide a container for some simple personalization data. This class contains properties for each of the data items and a default constructor.

Figure 6-2 shows a simple form that we’ve created for viewing the current contents of the personalization data stored in the Session object and for entering new session state data values. Example 6-8 shows the .aspx file that produces the form. Example 6-9 and Example 6-10 show the companion VB and C# code-behind files.

Form for viewing and entering session state data values

Figure 6-2. Form for viewing and entering session state data values

Discussion

The approach we favor for maintaining personal information about a user for the duration of a session—an approach that is often referred to as personalization—is to create a class to hold the data, instantiate and populate the object, store the object in the Session object, and then access the data from the Session object.

As its name implies, you can use the Session object in ASP.NET to store information needed for a particular user session. Variables stored in the Session object are not discarded when the user navigates between the pages of an application. Rather, they are persisted for the entire session.

To illustrate this approach, the code-behind in our example contains the logic needed to access the data in the Session object. We make use of the Page_Load method in Example 6-9 (VB) and Example 6-10 (C#) to first check whether the Session object contains the personalization data. If not, we create a new CH06PersonalDataVB (VB) or CH06PersonalDataCS (C#) object using default values, and store this new data object in the Session object associated with the current session. Otherwise, we retrieve a reference to the object containing the personalized data. Finally, we update the contents of the form by passing the personalization object to a method that uses the data to update the contents of the form.

Tip

In Example 6-9 and Example 6-10, a constant, SES_PERSONALIZATION_DATA, is used to define the name of the variable placed in the Session object. This is done to avoid having to hardcode the name of the variable in multiple locations in the code. In an application where the data is accessed in multiple pages, the constant should be stored in global.asax.vb (or global.asax.cs) or in another class containing global constants.

For this example, the personalization data is updated when the user enters new personalization data values and clicks the Update button. In the button click event handler, we check whether the data has been stored in the Session object, using the same code we used in the Page_Load method. You should always check this condition to avoid the error that will be thrown if the data is no longer in the Session object. Loss of data can occur if the session times out and ASP.NET deletes all variables for the user session.

Next, we update the contents of the personalization object with data from the form. In a production setting, your code will need to perform validation on the data to ensure that it is of the correct type, in the correct form, within the correct range, and so on. Finally, we store the personalization data in the Session object and update the form contents.

This example is rather simple, but it shows the mechanics associated with storing and retrieving data in the Session object. In a full application, the personalization data could be read from a database when the user logs in. If your application uses cookies to identify a user, the Session_Start event handler of global.asax provides an ideal place to retrieve the cookie that identifies the user, get the user’s personalization data from a database, and then place the data in the Session object.

You can place any object in the Session object, but take care not to overuse the Session object. Large objects can significantly impact the performance of the application by tying up system resources.

To provide the ability to associate session data with a specific user, ASP.NET assigns a session ID to each user session. The session ID is then used by ASP.NET to retrieve the Session object associated with the user requesting a page.

The HTTP protocol is stateless, so some method of associating the incoming requests with a specific user is required. By default, ASP.NET sends a cookie containing the session ID to the client browser as part of its response to the first page request by a user. Subsequent page requests return the cookie data. ASP.NET retrieves the cookie data from the request, extracts the session ID, retrieves the Session object for the specific user, and then processes the requested page.

The cookie sent to the client browser is an in-memory cookie and is not persisted on the client machine. If the user closes the browser, the cookie containing the session ID is destroyed.

To support applications that do not use cookies, ASP.NET provides the ability to automatically modify the URL to contain the session ID (called URL munging). This method of tracking the session ID is configured in the web.config file and is discussed in Recipe 9.4.

ASP.NET supports three methods of storing the session information. By default, the session data is stored in memory within the ASP.NET process. The session data can also be stored in memory in an out-of-process state server or SQL Server. The storage methods are configured in the web.config file and are discussed in Recipe 9.4.

When using the Session object in your application, consider the following points:

  • By default, a session times out after 20 minutes of inactivity. When a session times out, the ASP.NET process destroys all session data, and the resources used by the session variables are recovered. The session timeout is configured in the web.config file and is discussed in Recipe 9.4.

  • If any special operations are required when a user session ends, they can be performed in the Session_End event handler of global.asax. This event is raised whenever a session ends, whether it is done programmatically or because the session times out. However, the Session_End event may not be raised if ASP.NET is terminated abruptly.

See Also

Recipe 9.4

Example 6-6. Class used to store data in session object (.vb)

Option Explicit On 
Option Strict On
'-----------------------------------------------------------------------------
'
'   Module Name: CH06PersonalDataVB.vb
'
'   Description: This module provides the container to store personalization 
'                data for a user
'
'*****************************************************************************
Namespace ASPNetCookbook.VBExamples
  Public Class CH06PersonalDataVB

    'private attributes with default values
    Private mUsername As String = ""
    Private mResultsPerPage As Integer = 25
    Private mSortBy As String = "Title"

    Public Property username( ) As String
      Get
        Return (mUsername)
      End Get
      Set(ByVal Value As String)
        mUsername = Value
      End Set
    End Property  'username

    Public Property resultsPerPage( ) As Integer
      Get
        Return (mResultsPerPage)
      End Get
      Set(ByVal Value As Integer)
        mResultsPerPage = Value
      End Set
    End Property  'resultsPerPage

    Public Property sortBy( ) As String
      Get
        Return (mSortBy)
      End Get
      Set(ByVal Value As String)
        mSortBy = Value
      End Set
    End Property  'sortBy
  End Class  'CH06PersonalDataVB
End Namespace

Example 6-7. Class used to store data in session object (.cs)

//----------------------------------------------------------------------------
//
//   Module Name: CH06PersonalDataCS
//
//   Description: This module provides the container to store personalization 
//                data for a user
//
//****************************************************************************
using System;

namespace ASPNetCookbook.CSExamples
{
  public class CH06PersonalDataCS
  {
    // private attributes with default values
    private String mUsername = "";
    private int mResultsPerPage = 25;
    private String mSortBy = "Title";

    public String username
    {
      get
      {
        return(mUsername);
      }
      set
      {
        mUsername = value;
      }
    }  // username

    public int resultsPerPage
    {
      get
      {
        return(mResultsPerPage);
      }
      set
      {
        mResultsPerPage = value;
      }
    }  // resultsPerPage

    public String sortBy
    {
      get
      {
        return(mSortBy);
      }
      set
      {
        mSortBy = value;
      }
    }  // mSortBy
  }  // CH06PersonalDataCS
}

Example 6-8. Maintaining user state (.aspx)

<%@ Page Language="vb" AutoEventWireup="false" 
         Codebehind="CH06SessionStateVB.aspx.vb" 
         Inherits="ASPNetCookbook.VBExamples.CH06SessionStateVB" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>State Session</title>
    <link rel="stylesheet" href="css/ASPNetCookbook.css">
  </head>
  <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">
    <form id="frmSessionState" method="post" runat="server">
      <table width="100%" cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td align="center">
            <img src="images/ASPNETCookbookHeading_blue.gif">
          </td>
        </tr>
        <tr>
          <td class="dividerLine">
            <img src="images/spacer.gif" height="6" border="0"></td>
        </tr>
      </table>
      <table width="90%" align="center" border="0">
        <tr>
          <td><img src="images/spacer.gif" height="10" border="0"></td>
        </tr>
        <tr>
          <td align="center" class="PageHeading">
            Maintaining Session State (VB)
          </td>
        </tr>
        <tr>
          <td><img src="images/spacer.gif" height="10" border="0"></td>
        </tr>
        <tr>
          <td align="center">
            <table width="60%" align="center">
              <tr>
                <td colspan="2" align="center" class="PageHeading">
                  Current Session Data Values</td>
              </tr>
              <tr class="MenuItem">
                <td>User Name: </td>
                <td><asp:Label ID="labUserName" Runat="server" /></td>
              </tr>
              <tr class="MenuItem">
                <td>Results Per Page: </td>
                <td><asp:Label ID="labResultsPerPage" Runat="server" /></td>
              </tr>
              <tr class="MenuItem">
                <td>Sort By: </td>
                <td><asp:Label ID="labSortBy" Runat="server" /></td>
              </tr>
            </table>
            <br />
            <table width="60%" align="center">
              <tr>
                <td colspan="2" align="center" class="PageHeading">
                  Enter New Session Data Values</td>
              </tr>
              <tr class="MenuItem">
                <td>User Name: </td>
                <td><asp:TextBox ID="txtUserName" Runat="server" /></td>
              </tr>
              <tr class="MenuItem">
                <td>Results Per Page: </td>
                <td><asp:TextBox ID="txtResultsPerPage" Runat="server" /></td>
              </tr>
              <tr class="MenuItem">
                <td>Sort By: </td>
                <td><asp:TextBox ID="txtSortBy" Runat="server" /></td>
              </tr>
              <tr>
                <td colspan="2" align="center">
                  <br />
                  <asp:ImageButton ID="btnUpdate" Runat="server" 
                       ImageUrl="images/buttons/button_update.gif" />
                </td>
              </tr>
            </table>
          </td>
        </tr>
      </table>
    </form>
  </body>
</html>

Example 6-9. Maintaining user state (.vb)

Option Explicit On 
Option Strict On
'-----------------------------------------------------------------------------
'
'   Module Name: CH06SessionStateVB.aspx.vb
'
'   Description: This module provides the code behind for
'                CH06SessionStateVB.aspx
'
'*****************************************************************************
Imports Microsoft.VisualBasic

Namespace ASPNetCookbook.VBExamples
  Public Class CH06SessionStateVB
    Inherits System.Web.UI.Page

    'controls on the form
    Protected labUserName As System.Web.UI.WebControls.Label
    Protected labResultsPerPage As System.Web.UI.WebControls.Label
    Protected labSortBy As System.Web.UI.WebControls.Label

    Protected txtUserName As System.Web.UI.WebControls.TextBox
    Protected txtResultsPerPage As System.Web.UI.WebControls.TextBox
    Protected txtSortBy As System.Web.UI.WebControls.TextBox

    Protected WithEvents btnUpdate As System.Web.UI.WebControls.ImageButton

    'The following constant defines the name of the session variable used
                      'to store the user personalization data
                      Public SES_PERSONALIZATION_DATA As String = "PersonalizationData"

    '*************************************************************************
    '
    '   ROUTINE: Page_Load
    '
    '   DESCRIPTION: This routine provides the event handler for the page load
    '                event.  It is responsible for initializing the controls 
    '                on the page.
    '-------------------------------------------------------------------------
    Private Sub Page_Load(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) Handles MyBase.Load

      Dim personalData As CH06PersonalDataVB

                        If (Not Page.IsPostBack( )) Then
                          'check to see if the session data exists
                          If (IsNothing(Session(SES_PERSONALIZATION_DATA))) Then
                            'data does not exist in session so create a new personalization
                            'object and place it in session scope
                            personalData = New CH06PersonalDataVB
                            Session.Add(SES_PERSONALIZATION_DATA, _
                                        personalData)

                          Else
                            'data exists in session so get a reference to the data
                            personalData = CType(Session(SES_PERSONALIZATION_DATA), _
                                                 CH06PersonalDataVB)
                          End If

                          'update contents on the form
                          updateFormData(personalData)
                        End If
    End Sub  'Page_Load

    '*************************************************************************
    '
    '   ROUTINE: btnUpdate_Click
    '
    '   DESCRIPTION: This routine provides the event handler for the update
    '                button click event.  It is responsible for updating the
    '                contents of the session variable used to store the 
    '                personalization data and updating the form.
    '-------------------------------------------------------------------------
    Private Sub btnUpdate_Click(ByVal sender As Object, _
                                                  ByVal e As System.Web.UI.ImageClickEventArgs) _
                              Handles btnUpdate.Click

                        Dim personalData As CH06PersonalDataVB

                        'check to see if the session data exists
                        If (IsNothing(Session(SES_PERSONALIZATION_DATA))) Then
                          'data does not exist in session so create a new personalization object
                          personalData = New CH06PersonalDataVB
                        Else
                          'data exists in session so get a reference to the data
                          personalData = CType(Session(SES_PERSONALIZATION_DATA), _
                                               CH06PersonalDataVB)
                        End If

                        'update contents of session object from form
                        personalData.username = txtUserName.Text
                        personalData.resultsPerPage = CInt(txtResultsPerPage.Text)
                        personalData.sortBy = txtSortBy.Text

                        'update contents of session object
                        Session(SES_PERSONALIZATION_DATA) = personalData

                        'update contents on the form
                        updateFormData(personalData)
                      End Sub  'btnUpdate_Click

    '*************************************************************************
    '
    '   ROUTINE: updateFormData
    '
    '   DESCRIPTION: This routine updates the contents of the form from the
    '                passed data.
    '-------------------------------------------------------------------------
    Private Sub updateFormData(ByVal personalData As CH06PersonalDataVB)
      labUserName.Text = personalData.username
      labResultsPerPage.Text = personalData.resultsPerPage.ToString( )
      labSortBy.Text = personalData.sortBy
    End Sub  'updateFormData
  End Class  'CH06SessionStateVB
End Namespace

Example 6-10. Maintaining user state (.cs)

//----------------------------------------------------------------------------
//
//   Module Name: CH06SessionStateCS.ascx.cs
//
//   Description: This module provides the code behind for
//                CH06SessionStateCS.ascx
//
//****************************************************************************
using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ASPNetCookbook.CSExamples
{
  public class CH06SessionStateCS : System.Web.UI.Page
  {
    // controls on the form
    protected System.Web.UI.WebControls.Label labUserName;
    protected System.Web.UI.WebControls.Label labResultsPerPage;
    protected System.Web.UI.WebControls.Label labSortBy;

    protected System.Web.UI.WebControls.TextBox txtUserName;
    protected System.Web.UI.WebControls.TextBox txtResultsPerPage;
    protected System.Web.UI.WebControls.TextBox txtSortBy;

    protected System.Web.UI.WebControls.ImageButton btnUpdate;
                                                                                                                                                                                                                               
    // The following constant defines the name of the session variable used
                      // to store the user personalization data
                      public String SES_PERSONALIZATION_DATA = "PersonalizationData";

    //************************************************************************
    //
    //   ROUTINE: Page_Load
    //
    //   DESCRIPTION: This routine provides the event handler for the page 
    //                load event.  It is responsible for initializing the 
    //                controls on the page.
    //------------------------------------------------------------------------
    private void Page_Load(object sender, System.EventArgs e)
    {
      CH06PersonalDataCS personalData = null;

                        // wire the update button click event
                        this.btnUpdate.Click += 
                          new ImageClickEventHandler(this.btnUpdate_Click);

                        if (!Page.IsPostBack)
                        {
                          // check to see if the session data exists
                          if (Session[SES_PERSONALIZATION_DATA] == null)
                          {
                            // data does not exist in session so create a new personalization
                            // object and place it in session scope
                            personalData = new CH06PersonalDataCS( );
                            Session.Add(SES_PERSONALIZATION_DATA, 
                                        personalData);
                          }
                          else
                          {
                            // data exists in session so get a reference to the data
                            personalData = (CH06PersonalDataCS)
                                           (Session[SES_PERSONALIZATION_DATA]);
                          }

                          // update contents on the form
                          updateFormData(personalData);
                        }
    }  // Page_Load

    //************************************************************************
    //
    //   ROUTINE: btnUpdate_Click
    //
    //   DESCRIPTION: This routine provides the event handler for the update
    //                button click event.  It is responsible for updating the
    //                contents of the session variable used to store the 
    //                personalization data and updating the form.
    //------------------------------------------------------------------------
    private void btnUpdate_Click(Object sender,
                                                   System.Web.UI.ImageClickEventArgs e)
                      {
                        CH06PersonalDataCS personalData = null;
                      

                        //check to see if the session data exists
                        if (Session[SES_PERSONALIZATION_DATA] == null)
                        {
                          // data does not exist in session so create a new 
                          // personalization object
                          personalData = new CH06PersonalDataCS( );
                        }
                        else
                        {
                          //data exists in session so get a reference to the data
                          personalData = (CH06PersonalDataCS)(Session[SES_PERSONALIZATION_DATA]);
                        }

                        // update contents of session object from form
                        personalData.username = txtUserName.Text;
                        personalData.resultsPerPage = Convert.ToInt32(txtResultsPerPage.Text);
                        personalData.sortBy = txtSortBy.Text;

                        //update contents of session object
                        Session[SES_PERSONALIZATION_DATA] = personalData;

                        // update contents on the form
                        updateFormData(personalData);
                      }  // btnUpdate_Click

    //************************************************************************
    //
    //   ROUTINE: updateFormData
    //
    //   DESCRIPTION: This routine updates the contents of the form from the
    //                passed data.
    //------------------------------------------------------------------------
    private void updateFormData(CH06PersonalDataCS personalData)
    {
      labUserName.Text = personalData.username;
      labResultsPerPage.Text = personalData.resultsPerPage.ToString( );
      labSortBy.Text = personalData.sortBy;
    }  // updateFormData
  }  // CH06SessionStateCS
}
..................Content has been hidden....................

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