ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


Personalization in ASP.NET

by Wei-Meng Lee 08/16/2004

Personalizing your web site is one of the tasks that you can do to enhance the experiences of users visiting your site. Personalization allows information about visitors to be persisted so that the information can be useful to the visitor when he visits your site again. For example, Amazon.com uses personalized recommendation to remember the books that I have purchased and make suitable recommendations based on my interests (see Figure 1).

Figure 1. Amazon.com’s personalized recommendation
Figure 1. Amazon.com's personalized recommendation

In ASP.NET 2.0, you can now use personalization providers to personalize your site. This article will discuss the personalization feature in ASP.NET 2.0 and how you can use it to personalize your web application.

Using the Profile Object

In ASP.NET 1.x, the conventional method for storing personalized information is through the Session object. However, using the Session object has its disadvantages, such as its volatility (it's persisted in memory by default, unless it's saved on disk), late-binding (all session objects are stored as objects), large memory requirements, and inefficient loading mechanism.

You may also store users' information in databases, but that requires you to write custom code to save and retrieve users' information.

In ASP.NET 2.0, there is a new Profile object that allows users' data to be persisted in a much more efficient manner.

To see how to use the Profile object, I will show you how to build a simple web application that uses the Profile object to save users' information. To do so, create a new web site using Visual Studio 2005 (Beta 1 at this moment).


In the default page, populate the page with the following controls -- all of the controls are located in a Panel control (see Figure 2).

Figure 2. Populating the default page with all of the controls
Figure 2. Populating the default page with all of the controls

This page will prompt the user to enter his name when he first visits the page. The next time the user visits the page, the application will be able to remember his name. I will use the Profile object to save the user's name. To use the Profile object, you first need to add a web configuration file to your project. (In Solution Explorer, right-click on the project name and select Add New Item. Select Web Configuration File.) Add the <profile> element into the web.config file:

<system.web>
  <profile>
  <properties>
     <add name="FirstName" type="System.String"/>
     <add name="LastName" type="System.String"/>
  </properties>
  </profile>
...

Here, I have defined two Profile properties -- FirstName and LastName, which will be used to store a user's first and last name, respectively. To use the two Profile properties, simply prefix the property name with the Profile keyword. That is, use Profile.FirstName and Profile.LastName.

In the Page_Load event, I first check to see if the FirstName property is empty. If it is empty, I assume that the user has never visited the page before, and show the Panel control to allow the user to enter his first and last name. If it is non-empty, then I will retrieve the first and last name of the user from the Profile properties.


Sub Page_Load(ByVal sender As Object,
              ByVal e As System.EventArgs) _
  Handles Me.Load
  If Profile.FirstName <> "" Then
    Panel1.Visible = False
    Response.Write("Welcome back, " & Profile.FirstName & ", " & _
            Profile.LastName)
  Else
    Panel1.Visible = True
  End If
End Sub

With the Save button, you save the first and last names by simply assigning them to the Profile properties:


Sub btnSave_Click(ByVal sender As Object,
                  ByVal e As System.EventArgs)
  ' save the profile 
  Profile.FirstName = txtFirstName.Text
  Profile.LastName = txtLastName.Text
End Sub

Figure 3 shows what happens when the user visits the page for the first time.

Figure 3. User visiting the page for the first time
Figure 3. A user visiting the page for the first time

Figure 4 shows what happens when the same user visits the page again:

Figure 4. The same user visiting the page again
Figure 4. The same user visiting the page again

Related Reading

Programming ASP.NET
By Jesse Liberty, Dan Hurwitz

As you can see, the user's first and last names have been saved in the Profile properties. So where are these values stored?

Note: ASP.NET 2.0 comes with two profile providers -- Access and SQL Server. By default, the Access provider is used. To change to the SQL Server provider (or your own provider), use the ASP.NET Web Application Administration tool. Under the Provider tab, click "Select a different provider for each feature (advanced)" and then select the relevant provider in the Profile Provider box.

If you refresh your project listing in Solution Explorer, you will notice that within the Data folder there is a database file called ASPNetDB.mdb (see Figure 5).

Figure 5. The ASPNetDB.mdb file in the Data folder
Figure 5. The ASPNetDB.mdb file in the Data folder

Within this database, you will see a table called aspnet_Profile. Figure 6 shows the content of the table and the values that have been saved via the Profile properties. Also note the user name associated with the row. By default, ASP.NET uses Windows authentication, and so when I access my application, ASP.NET associates me with my Windows user name.


Figure 6. Examining the aspnet_Profile table
Figure 6. Examining the aspnet_Profile table

It is interesting to note how ASP.NET stores the Profile properties. In my case, I have two properties -- FirstName and LastName. The following table shows the value of each field in the table.

Field NameValues
PropertyNames FirstName:S:0:8:LastName:S:8:3:
PropertyValuesStringWei MengLee

It is not difficult to interpret the relationship between the PropertyNames and PropertyValuesString fields.

Using Forms Authentication

In the last example, I used Windows authentication for my ASP.NET web application. While this is useful for intranet applications, a better way to authenticate external users would be to use forms authentication. In this section, I will show you how to use personalization together with forms authentication.

Add a new folder to your project (right-click your project name in Solution Explorer and select New Folder) and name it "Members." Move the default.aspx page created in the previous section into the Members folder. Add a new web configuration file to the Members folder. Finally, add a new web form to your project and name it login.aspx (see Figure 7). Populate the form with the Login control.

Figure 7. The login.aspx page with the Login control
Figure 7. The login.aspx page with the Login control

Your Solution Explorer should look like Figure 8.

Figure 8. Files and folders in Solution Explorer
Figure 8. Files and folders in Solution Explorer

Change the authentication mode from Windows to Forms in web.config (1) and specify the login page for the site as login.aspx:


<authentication mode="Forms">
  <forms name=".ASPXAUTH"
         loginUrl="login.aspx"
         protection="Validation"
         timeout="999999" />
</authentication>

In web.config (2), add in the following:


<system.web>
  <authorization>
    <deny users="?" />
  </authorization>
...

Essentially, this means that all anonymous users will be denied access to the Members folder.

Let's add a new user to the web site. To do so, go to Website -> ASP.NET Configuration in Visual Studio 2005, and under the Users section, click on Create user. In Figure 9, I have entered a user name.

Figure 9. Adding a new user to the site
Figure 9. Adding a new user to the site

You are now ready to test the application.

Load the default.aspx page located in the Members folder using a web browser. Since all unauthenticated users are denied access, you will be redirected to the login.aspx page. Log in using the user name that you have just created, and you will see the default.aspx page. As usual, enter your first and last names and click on the Save button.

Let's now examine the aspnet_Profile table again (see Figure 10). This time around, you will see a second row in the table. This row belongs to the "WeiMengLee" user, which is the user name you used to log in. Contrast this to the Windows user name "WINXP\Wei-Meng Lee" used in the earlier example (using Windows authentication).

Figure 10. Examining the aspnet_Profile table
Figure 10. Examining the aspnet_Profile table

You might wonder what happens if the file default.aspx is located outside of the Members folder and a user accesses it directly without logging in. Figure 11 shows the location of default.aspx.
Figure 11. Moving Default.aspx out of the Members folder
Figure 11. Moving default.aspx out of the Members folder

If default.aspx is accessed directly when the user has not yet been authenticated, trying to set the Profile properties will result in a run time error. This is because ASP.NET requires an ID to identify the user. Personalization for a user that has not yet been authenticated is known as anonymous personalization. The next section will discuss this in more detail.

Anonymous Personalization

Anonymous personalization is useful for several reasons. One good scenario is the shopping cart example. A user might add items to the cart (via the Profile properties) and log in only when he is ready to check out.

ASP.NET supports anonymous personalization and assigns a Globally Unique Identifier (GUID) to identify an anonymous user. To do so, you need to add the <anonymousIdentification> element to your web.config file:

<system.web>
  <anonymousIdentification enabled="true" />
...

To illustrate anonymous personalization, I will add a new web form called products.aspx to the project (see Figure 12).

Figure 12. Adding a new form to the project
Figure 12. Adding a new form to the project

As the products.aspx page is in the root of the project, anonymous users can access the page. Figure 13 shows the content of the page. It contains two ImageButton controls.

Figure 13. Content of Products.aspx
Figure 13. The content of products.aspx

When the user clicks on the image, the product's ISBN will be added to the Profile properties (which I will add shortly):

Sub imgBook1_Click(ByVal sender As Object, ByVal e As _
           System.Web.UI.ImageClickEventArgs)
  Profile.Cart += "0-596-00768-X;"
  Response.Write("'Just a Geek' added!")
End Sub

Sub imgBook2_Click(ByVal sender As Object, ByVal e As _
  System.Web.UI.ImageClickEventArgs)
  Profile.Cart += "0-596-00733-7;"
  Response.Write("'We the media' added!")
End Sub

For simplicity, I will implement the shopping cart as simply a string containing a list of ISBNs separated by semicolons. In reality, you can map your profile property to a class that you define in your project (such as a shopping cart class).

The following shows the addition to the web.config file:

<anonymousIdentification enabled="true" />
<profile>
  <properties>
    <add name="FirstName" type="System.String"/>
    <add name="LastName" type="System.String"/>
    <add name="Cart" allowAnonymous="true"
                     type="System.String"/>
  </properties>
</profile>

Do note that you need to add the allowAnonymous attribute to each property of the Profile object that you want to allow for anonymous access. In this example, only the Cart property is allowed anonymous access.

Load the products.aspx page (make sure you are not logged in) using Internet Explorer, and click once on each image. Now, examine the aspnet_Profile table again (see Figure 14). You should see a third row containing the shopping cart values. It is associated with a UserName that contains some random characters (this is the GUID used to identify the anonymous user).

Figure 14. Anonymous Personalization
Figure 14. Anonymous personalization

Migrating from Anonymous Personalization to Authenticated Personalization

In the last section, you saw how anonymous users can also use the Profile object to add items to their shopping carts. When the user is ready to check out and proceed to payment, he would need to log in. When he logs in (through login.aspx), all of the profile properties saved when he was an anonymous user would be lost. Therefore, you would need to manually migrate his anonymous profile to his authenticated profile.

Let's now add a new web form to our project and name it checkout.aspx (located within the Members folder). This page will list all of the items added to the shopping cart by the user.

Also, add a hyperlink to the products.aspx page that links to the checkout.aspx page.

When an anonymous user logs in, an event called Profile_MigrateAnonymous would be fired. This event should be serviced in a Global Application Class called global.asax. To add a Global Application Class to your project, right-click the project name and select Add New Item..., and then select Global Application Class.

To transfer the anonymous profile to an authenticated profile, do the following:


Sub Profile_MigrateAnonymous(ByVal sender As Object, _
               ByVal e As ProfileMigrateEventArgs)
  Dim anonymousProfile As ASP.HttpProfile = _
    Profile.GetProfile(e.AnonymousId)
  If anonymousProfile.Cart IsNot Nothing Then
    Profile.Cart = anonymousProfile.Cart
  End If
End Sub

Figure 15 shows the new additions.

Figure 15.  The new files in the project
Figure 15. The new files in the project

In the checkout.aspx page, list out the content of the shopping cart to ensure that the cart content has been migrated successfully:

Sub Page_Load(ByVal sender As Object,
              ByVal e As System.EventArgs)

  Response.Write("Shopping cart content: " " Profile.Cart)
End Sub

You can now test out the process. Figure 16 shows the steps involved:

Figure 16. Testing the migration of a user’s profile
Figure 16. Testing the migration of a user's profile

Summary

Personalization is a very useful feature in ASP.NET 2.0. It is also the foundation for other new features in ASP.NET 2.0, such as web parts and themes. In the next article, I will talk more about applying skins and themes to your ASP.NET 2.0 web application.

Wei-Meng Lee (Microsoft MVP) http://weimenglee.blogspot.com is a technologist and founder of Developer Learning Solutions http://www.developerlearningsolutions.com, a technology company specializing in hands-on training on the latest Microsoft technologies.


Return to ONDotnet.com

Copyright © 2009 O'Reilly Media, Inc.