Recipe 7.3. 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 accessing 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 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 7-8, 7-9, 7-10, 7-11 through 7-12. The example uses the class shown in Examples 7-8 (CH07PersonalDataVB for VB) and 7-9 (CH07PersonalDataCS for C#) to provide a container for some simple personalized data. This class contains properties for each of the data items and a default constructor.

Figure 7-2 shows a form that we've created for viewing the current contents of the personalized data stored in the Session object and for entering new session state data values. Example 7-10 shows the .aspx file that produces the form. Examples 7-11 and 7-12 show the companion VB and C# code-behind files.

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


Discussion

An approach we like for maintaining personalized data about a user for the duration of a sessionan approach often referred to as personalizationis to create a class to hold the data, instantiate and populate the object, store the object in the Session object, and access the data from the Session object.

This recipe takes a slightly different approach to personalization from that found in the recipes in Chapter 10, which leverage ASP.NET 2.0's built-in profile features. Here the emphasis is on relatively short-lived datathat is, data that must remain available while the user is active. What's more, your code must undertake all the necessary steps to instantiate and populate an object to hold personalized settings, store it in session state, and access it from session state when needed. By contrast, when using ASP.NET 2.0's built-in profile features, much of the mechanics of persisting information is handled for you automatically and transparently using the profile framework. More important, ASP.NET 2.0's profile features are geared more toward long-lived data, such as a user's name, address, and other user-specific information. These customizations can be persisted and made available to the user on subsequent visits to the site. This forms the basis of ASP.NET 2.0's new profile features and is the focus of the recipes in Chapter 10.


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 Examples 7-11 (VB) and 7-12 (C#) to check if the Session object contains the personalization data. If not, we create a new CH07PersonalDataVB (VB) or CH07PersonalDataCS (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.

In Examples 7-11 (VB) and 7-12 (C#), 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 another class containing global constants as described in Recipe 7.1.


For this example, the personalized 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 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 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 impact the application's performance 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 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 will be destroyed.

To support applications that do not use cookies, ASP.NET provides the ability to modify the URL automatically 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 12.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 12.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 12.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

Recipes 7.1, 12.4, and Chapter 10 for ASP.NET 2.0's built-in personalization features

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

 Option Explicit On Option Strict On Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class provides the container to store personalization data ''' for a user ''' </summary> Public Class CH07PersonalDataVB 'private attributes with default values Private mUsername As String = "" Private mResultsPerPage As Integer = 25 Private mSortBy As String = "Title" '''********************************************************************** ''' <summary> ''' This property provides the ability to get/set the username data ''' </summary> Public Property username() As String Get Return (mUsername) End Get Set(ByVal Value As String) mUsername = Value End Set End Property 'username '''********************************************************************** ''' <summary> ''' This property provides the ability to get/set the resultsPerPage data ''' </summary> Public Property resultsPerPage() As Integer Get Return (mResultsPerPage) End Get Set(ByVal Value As Integer) mResultsPerPage = Value End Set End Property 'resultsPerPage '''********************************************************************** ''' <summary> ''' This property provides the ability to get/set the sortBy data ''' </summary> Public Property sortBy() As String Get Return (mSortBy) End Get Set(ByVal Value As String) mSortBy = Value End Set End Property 'sortBy End Class 'CH07PersonalDataVB End Namespace 

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

 using System; namespace ASPNetCookbook.CSExamples { /// <summary> /// This class provides the container to store personalization data /// for a user /// </summary> public class CH07PersonalDataCS { // private attributes with default values private String mUsername = ""; private int mResultsPerPage = 25; private String mSortBy = "Title"; ///********************************************************************** /// <summary> /// This property provides the ability to get/set the username data /// </summary> public String username { get { return (mUsername); } set { mUsername = value; } } // username ///********************************************************************** /// <summary> /// This property provides the ability to get/set the resultsPerPage data /// </summary> public int resultsPerPage { get { return (mResultsPerPage); } set { mResultsPerPage = value; } } // resultsPerPage ///********************************************************************** /// <summary> /// This property provides the ability to get/set the sortBy data /// </summary> public String sortBy { get { return (mSortBy); } set { mSortBy = value; } } // mSortBy } // CH07PersonalDataCS } 

Example 7-10. Maintaining user state (.aspx)

 <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master" AutoEventWireup="false" CodeFile="CH07SessionStateVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH07SessionStateVB" Title="State Session" %> <asp:Content  runat="server" ContentPlaceHolder> <div align="center" > Maintaining Session State (VB) </div> <table width="60%" align="center"> <tr> <td colspan="2" align="center" > Current Session Data Values</td> </tr> <tr > <td>User Name: </td> <td><asp:Label  Runat="server" /></td> </tr> <tr > <td>Results Per Page: </td> <td><asp:Label  Runat="server" /></td> </tr> <tr > <td>Sort By: </td> <td><asp:Label  Runat="server" /></td> </tr> </table> <br /> <table width="60%" align="center"> <tr> <td colspan="2" align="center" > Enter New Session Data Values</td> </tr> <tr > <td>User Name: </td> <td><asp:TextBox  Runat="server" /></td> </tr> <tr > <td>Results Per Page: </td> <td><asp:TextBox  Runat="server" /></td> </tr> <tr > <td>Sort By: </td> <td><asp:TextBox  Runat="server" /></td> </tr> <tr> <td colspan="2" align="center"> <br /> <asp:Button  runat="server"    Text="Update"    OnClick="btnUpdate_Click" /> </td> </tr> </table> </asp:Content> 

Example 7-11. Maintaining user state code-behind (.vb)

 Option Explicit On Option Strict On Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class provides the code behind for ''' CH07SessionStateVB.aspx ''' </summary> Partial Class CH07SessionStateVB Inherits System.Web.UI.Page 'The following constant defines the name of the session variable used 'to store the user personalization data Public Const SES_PERSONALIZATION_DATA As String = "PersonalizationData" '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the page load event. It ''' is responsible for initializing the controls on the page. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Private Sub Page_Load(ByVal sender As Object, _   ByVal e As System.EventArgs) Handles Me.Load Dim personalData As CH07PersonalDataVB 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 CH07PersonalDataVB Session.Add(SES_PERSONALIZATION_DATA, _ personalData) Else 'data exists in session so get a reference to the data personalData = CType(Session(SES_PERSONALIZATION_DATA), _  CH07PersonalDataVB) End If 'update contents on the form updateFormData(personalData) End If End Sub 'Page_Load '''*********************************************************************** ''' <summary> ''' 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. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub btnUpdate_Click(ByVal sender As Object, _   ByVal e As System.EventArgs) Dim personalData As CH07PersonalDataVB '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 CH07PersonalDataVB Else 'data exists in session so get a reference to the data personalData = CType(Session(SES_PERSONALIZATION_DATA), _  CH07PersonalDataVB) 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 '''*********************************************************************** ''' <summary> ''' This routine updates the contents of the form from the passed data. ''' </summary> ''' ''' <param name="personalData">Set the the personalization data used ''' to update the data on the form ''' </param> Private Sub updateFormData(ByVal personalData As CH07PersonalDataVB) labUserName.Text = personalData.username labResultsPerPage.Text = personalData.resultsPerPage.ToString() labSortBy.Text = personalData.sortBy End Sub 'update   End Class 'CH07SessionStateVB End Namespace 

Example 7-12. Maintaining user state code-behind (.cs)

 using System; namespace ASPNetCookbook.CSExamples { /// <summary> /// This class provides the code behind for /// CH07SessionStateCS.aspx /// </summary> public partial class CH07SessionStateCS : System.Web.UI.Page { // The following constant defines the name of the session variable used // to store the user personalization data public const String SES_PERSONALIZATION_DATA = "PersonalizationData"; ///*********************************************************************** /// <summary> /// This routine provides the event handler for the page load event. /// It is responsible for initializing the controls on the page. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void Page_Load(object sender, EventArgs e) { CH07PersonalDataCS personalData = null; 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 CH07PersonalDataCS(); Session.Add(SES_PERSONALIZATION_DATA, personalData); } else { // data exists in session so get a reference to the data personalData = (CH07PersonalDataCS)    (Session[SES_PERSONALIZATION_DATA]); } // update contents on the form updateFormData(personalData); } } // Page_Load ///*********************************************************************** /// <summary> /// 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. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void btnUpdate_Click(object sender, EventArgs e) { CH07PersonalDataCS 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 CH07PersonalDataCS(); } else { //data exists in session so get a reference to the data personalData = (CH07PersonalDataCS)(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 ///*********************************************************************** /// <summary> /// This routine updates the contents of the form from the passed data. /// </summary> private void updateFormData(CH07PersonalDataCS personalData) { labUserName.Text = personalData.username; labResultsPerPage.Text = personalData.resultsPerPage.ToString(); labSortBy.Text = personalData.sortBy; } // updateFormData } // CH07SessionStateCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2003
Pages: 202

Similar book on Amazon

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