WindowsDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


AddThis Social Bookmark Button Liberty on Whidbey

Personalization in ASP.NET 2.0

by Jesse Liberty
10/25/2004

In previous articles, I discussed security and managing users' roles. This article will pick up from where those articles left off, and show you how to provide personalized web pages for your users. Personalization allows your web site to welcome the user ("Welcome back Jesse") and to persist the user's state ("You have three items in your shopping cart").

Getting Started

There have been some small changes since the previous articles were published, and so I suggest downloading the updated starter code. Unzip the starter project to any directory you like. It will create a subdirectory called personalization. Open IIS Manager and create a virtual directory named Personalization that points to your (physical) personalization sub-directory. Right-click on the virtual directory, and choose Properties. Click on the ASP.NET tab, and then click on Edit Configuration. Click on the Authentication tab, set the Authentication Mode drop-down menu to Forms, and make sure the Role Management Enabled checkbox is checked, as shown in Figure 1.

 

Figure 1

Figure 1. Setting up personalization

Start Visual Studio 2005 Beta 1 and choose File -> Open -> Open Web site. Navigate to the Personalization directory and click Open. Click Debug (and save the sln file) and you should be brought to the default page. Log in with the username Jesse (the starter kit includes this user) with the password Jesse. Click on Manage Roles and then within the ManageRoles.aspx page, click on Administrator. You should see something very much like Figure 2.

Figure 2

Figure 2. User and role management

Assuming this all worked as expected, you're ready to add personalization. (If it did not work, make sure you are using Beta Refresh 1 of Visual Studio 2005 and that IIS is properly installed. If all else fails, start over. If that fails, give up; it is beta, after all!)

Related Reading

Programming .NET Windows Applications
By Jesse Liberty, Dan Hurwitz

Personalization

The simplest form of personalization is to record information about the user, and then to make that information available whenever the user logs on. This requires a kind of persistence that goes beyond session state; to create true personalization, you'll want to create a database that associates the saved information with a particular user, and that persists indefinitely.

To do this, you need to store the data in a database. ASP.NET 2.0 provides all of the plumbing required. You do not have to design, edit, or manage the tables; all of that is done for you.

In fact, ASP.NET 2.0 has decoupled the Profile API (how you programmatically interact with profile data) from the underlying data provider (how you store the data). This allows you to use the default provider (Access), or one of the other providers supplied (SQL server) or even write your own provider (e.g., for an existing customer relationship management system) without changing the way you interact with the profile in the rest of your code.

To add data to the user's profile, you must first alert the system about the data you wish to store. You do so in Web.config, by adding a profile section to the system.web element:


<profile>
  <properties>

    <add name="lastName" />
    <add name="firstName" />
    <add name="phoneNumber" />
    <add name="birthDate" type="System.DateTime"/>
  </properties>
</profile>    

This causes the Profile API to create storage for (in this case) four pieces of information (first and last name, phone number, and birthdate). The default storage type is string, but here we are storing the birthdate as a datetime object. You can gather this information any way you like. To keep the example simple, we'll remove the role groups section from Default.aspx, and add a hyperlink to the LoggedInTemplate:


<LoggedInTemplate>
    Welcome
     <asp:LoginName ID="LoginName1" Runat="server" />
  <asp:HyperLink ID="linkProfile" Runat="server" 
   NavigateUrl="~/ProfileInfo.aspx">Add Profile Info</asp:HyperLink>
</LoggedInTemplate>

This link brings you to the ProfileInfo.aspx page, where you are asked to fill in your profile information, as shown in Figure 3.

Figure 3

Figure 3. Profile info page

When you click Save, the event handler is fired and you may store the data to the Profile object. The Profile object was automatically instantiated for the current user, and so the data you assign here is properly associated with the current user ID.


void save_Click(object sender, EventArgs e)
{
	Profile.lastName = this.lastName.Text;
	Profile.firstName = this.firstName.Text;
	Profile.phoneNumber = this.phone.Text;
	Profile.birthDate = Convert.ToDateTime(this.birthDate.Text);
	Response.Redirect("Default.aspx");
}

The Profile object has properties that correspond to the properties you added in Web.config.

To test that the Profile object has in fact stored this date, you'll add a panel to the default page:

 
<asp:Panel ID="pnlInfo" Runat="server" Visible="False" Width="422px" Height="63px">
  <br />
  <table width="100%">
    <tr>
      <td>
        <asp:Label ID="lblFullName" Runat="server"  Text="Full name unknown">
        </asp:Label></td>
      </tr>
    <tr>
      <td>
        <asp:Label ID="lblPhone" Runat="server" Text="Phone number unknown">
        </asp:Label>
      </td>
    </tr>
    <tr>
      <td>
        <asp:Label ID="lblBirthDate" Runat="server"  Text="Birthdate  unknown">
        </asp:Label>
      </td>
    </tr>
  </table>
 </asp:Panel>
 
 

The panel has a table with three rows, and each row has a label that is initialized to say that the value is unknown (this is not normally needed, but is included here to ensure that the data you see was in fact retrieved from the Profile object). When the page is loaded, you check to see if you have Profile data for this user and, if so, you assign that data to the appropriate controls.


if (Profile.UserName != null && Profile.IsAnonymous == false )
{
  this.lblFullName.Text = "Full name: " + Profile.firstName + " " + Profile.lastName;
  this.lblPhone.Text = "Phone: " + Profile.PhoneNumber;
  this.lblBirthDate.Text = "Born: " + Profile.birthDate.ToShortDateString();
  this.pnlInfo.Visible = true;
}
else
{
  this.pnlInfo.Visible = false;
}

Notice that you convert the datetime to a string for easy display in the label. The result is shown in Figure 4.

Figure 4

Figure 4. Using personalization

Before going on, let's look at how that data is stored. In your Project, you'll find a Data folder, and within that Data folder, you'll find an .mdb file (assuming you are using the default Access profile database). Open that database and examine two tables: aspnet_Users (which lists all of the users your security system knows about) and aspnet_Profile, as shown in Figure 5.

Figure 5

Figure 5. The database

The profile table is tied to the users table by the UserID (red arrows), much as you might see in any relational database. Because the property types and values cannot be predicted, they are encoded. Each property is listed in a string in the PropertyNames field, and the values are aggregated in a second string in the PropertyValuesString column.

You can decode this fairly easily, at least for simple types. The lastName is a string (S) that begins at offset 0 and is seven characters long. The first name is a string that begins at offset 7 and is five characters long (highlighted in Figure 5). Notice that birthDate is listed as a string, that begins at offset 24 and is 95 characters long, but if you look at the propertyValuesString column, you'll find that the birthdate is encoded as XML.

Pages: 1, 2

Next Pagearrow