Home   |   QuickStart Welcome   |   ASP.NET   |   Web Services   |   How Do I...?   
  |   I want my samples in...      

ASP.NET 2.0 Quickstart Tutorials

Storing User Profiles

What's New in 2.0

  • User Profiles - The profile feature in ASP.NET 2.0 allows you to define and store per-user settings to be used throughout your application. Settings can also be stored in an anonymous profile while users are not logged in, and then migrated to a logged-in user profile at a later time.
This section discusses the new profile feature in ASP.NET 2.0.

Web sites frequently need a convenient method to store user-specific data that is applicable site-wide. The Profile feature delivers an easy-to-use approach for defining user-specific data as well storing and retrieving this user data.

A user's profile is a collection of properties that define information you want to store for your web site's users. The user's profile is defined using a simple XML syntax in a configuration file (machine.config and/or web.config). Within your page, you reference a user's profile information with the Profile property. ASP.NET reads the schema defined in configuration, and automatically generates a class that is accessible from the Profile property on a page. You access properties on the Profile just as you would access properties on any other class.

Although the most common use of the Profile feature is storing data for authenticated users, the Profile feature also supports storing information for anonymous users. Storing profile information for anonymous users depends on the Anonymous Identification feature. The Profile and Anonymous Identification features work together to enable the use of the Profile property for anonymous users. The samples included in the QuickStart demonstrate using the Profile feature with both authenticated and unauthenticated users.

Prior to the start of the page lifecycle, ASP.NET ensures that the Profile is available for use by the page. Similarly, at the end of the ASP.NET page lifecycle, ASP.NET automatically saves the Profile to the underlying data store(s). As with other features such as Membership and Role Manager, the Profile feature has been designed with a provider-based model. Providers abstract the physical data storage for a feature from the classes and business logic exposed by a feature. The Profile feature ships with a provider for Microsoft™ SQL Server. You can create your own custom providers and configure them to work either the Profile feature. Pages that use the Profile feature will continue to work unchanged with your custom providers.

In addition to the Profile property, the Profile feature provides support for administration of profiles (both for authenticated users and anonymous users) with the ProfileManager. Common tasks that you perform with the ProfileManager include:

  • Searching for statistical information about all profiles, profiles for authenticated users, and profiles for anonymous users
  • Determine the number of profiles that have not been modified in a given period of time
  • Deleting individual profiles as well as deleting multiple profiles based on a profile's last modification date

Defining the Profile Schema

The configuration file in the following sample defines a Profile using properties, as well as a property group. Properties are defined using <add> elements within a <properties> element. A property group is a convenient way of logically grouping multiple properties. You define a property group with a <group> element. In the sample schema, a property group called "AutomobilePreferences" groups together two additional properties. Note that <group> elements cannot be nested (that is: there is only one level of group nesting supported beneath the <properties> element).

The sample schema demonstrates the flexibility you have in terms of defining data types for your profile properties. By default, properties are assumed to be of type System.String. However, you can define a profile property using any type that is resolvable by the ASP.NET application at runtime. The sample schema includes definitions for System.Collections.ArrayList as well as System.Drawing.Color.

Note that the <add> element supports a variety of optional attributes beyond those shown in this sample. Normally, the Profile feature serializes properties using either type conversion to a string, or Xml serialization. However, not all types are serializable as strings or as Xml fragments. This is why the "PreferredBackgroundColor" property has a serializeAs attribute that explicitly indicates binary serialization. The "PricePoint" property has a defaultValue attribute that defines the default value for this property if one has not already been set.

The "PreferredBackgroundColor" property also has an allowAnonymous attribute that is set to true. By default, profile properties are restricted to authenticated users. When the allowAnonymous attribute is set to true this indicates that the property can also be used to load and store information for anonymous users.

Profile schema in web.config
View Source

Anonymous Profiles

The profile schema shown in the last sample allows both authenticated and anonymous users to store their preferred background color. On the sample page an anonymous user can choose from a selection of colors. When the page refreshes it will render using the selected color. Notice that if you shut down the browser, and then re-run the sample, the color selection is remembered. The reason for this is that the Anonymous Identification feature is enabled for all of the samples (by default, Anonymous Identification is disabled). The Anonymous Identification feature automatically generates a random identifier for an anonymous user and stores it in a cookie. On subsequent visits to a site, the identifier in the cookie is used as a surrogate "id" when retrieving profile information for an anonymous user.

In the sample page, you get and set the background color using the syntax Profile.PreferredBackgroundColor. The coding style for using a Profile property is the same as accessing properties on any other class. In this sample, the page uses some common conversions available on the System.Drawing.Color structure to get and set Profile.PreferredBackgroundColor.

VB Storing Profile data for anonymous users
Run Sample View Source

Authenticated Profiles

In this sample, you log in as an authenticated user and set values for all of the profile properties. When you first run the sample you will be on a home page that is accessible to both anonymous and authenticated users. Note that the background color is set to the value you selected as an anonymous user in the previous sample. Click on the link that allows you to create a new user (this link is at the bottom of the login control). Enter a username and a password and then click the button to create a new user. After the new user is created, click on the button to continue to the page that displays the profile properties for the logged in user.

When you first view the page with all of your profile properties, you will notice that the background color is set to the selection you made earlier as an anonymous user. The reason for this is covered in more detail in the next sample. For now, notice that you can set values for all of the profile properties. Also, notice that initially the automobile price point is set to the default value defined in the profile schema.

After entering new values in the HTML form, press the "Update Preferences" button. When the page refreshes the property changes take immediate effect. Click on the logout link to remove the Forms Authentication cookie from your machine. Then close the browser. Now, if you re-run the sample you will be prompted to log in again. After entering your credentials and logging in, notice that the profile properties page correctly displays the information you entered earlier. If you click on the link that takes you back to the home page, you will see that the home page uses both the name and the background color that you selected for the logged in user. This demonstrates how profile properties can be used across secured and non-secure pages on a site. On the home page the background color and name are displayed using either the anonymous user's Profile (if you are not logged in yet), or the logged in user's Profile (once you choose to log in).

As with the anonymous example, this sample demonstrates how the Profile syntax follows the property accessor syntax for VB.NET and C#. Notice that the syntax for accessing a property within a property group uses two levels of property accessors: Profile.AutomobilePreferences.PricePoint. The property group simply acts as an intermediate property. The code for manipulating Profile.AutomobilePreferences.CarModels demonstrates using an System.Collections.Arraylist as a Profile property. The string that is typed into the HTML form should be a comma-delimited set of names. The page code parses this into an System.Array of strings prior to adding the array values to the Profile.AutomobilePreferences.CarModels property. When retrieving the car models, Profile.AutomobilePreferences.CarModels is enumerated using standard for-each syntax.

VB Storing Profile data for authenticated users
Run Sample View Source

Migrating Anonymous Profiles to Authenticated Profiles

In earlier samples it was demonstrated that the background color for an anonymous user was carried over to the authenticated user. You can verify this by running the sample below. If you are already logged in, click the logout link at the bottom of the page. On the home page, select a different color from the dropdown in the upper left corner of the page. The home page will refresh itself and display using the selected background color. Also, the page will have text stating "Hello Anonymous User" because the name property on the Profile is only supported for authenticated users. Log in to the site using the login control on the home page. Notice that once you log in, the background color on the profile properties page reflects the selection that was made earlier as an anonymous user.

On the profile properties page, click the link that takes you back to the home page. Notice that on the home page the name that is displayed is based on the value set for the Profile.Name property. Now that you are back on the home page as an authenticated user, select a different color from the dropdown and click the update button. The page refreshes and uses the updated background color. If you then click on the link that leads back to the profile properties page, you will see that the background color is retained.

Once you are back on the profile properties page, click on the logout link. This will redirect you back to the home page. Notice that when you are redirected to the home page, your previous selections for background color are no longer in effect. The reason for this is twofold. First, once you are logged out, the site considers you to be an anonymous user - as a result any background color that was set on the authenticated user's Profile is not available. Secondly, any color selection that was previously made when you were an anonymous user is no longer available. The reason for this is that once an anonymous users logs in, the cookie containing the autogenerated anonymous identifier was removed from the browser. As a result, when you log in, and then log out, the site considers you to be a completely new anonymous user. This interaction between anonymous users and logged in users leads to the need for migrating data from anonymous profiles to authenticated profiles.

The Profile feature exposes an event called the MigrateAnonymous event. You can subscribe to this event by placing an event handler in global.asax called Profile_MigrateAnonymous. This event fires whenever an anonymous identifier is available (either as a cookie or in the URL as a cookieless ticket), and the current user is authenticated. Within the event handler, you can load the Profile for the anonymous user by calling Profile.GetProfile and passing in the anonymous ID (the anonymous ID is one of the properties available off of the event arguments). Once you have a reference to the anonymous Profile, you can transfer property settings from the anonymous Profile to the authenticated Profile. The sample global.asax file demonstrates transferring the background color from the anonymous Profile to the authenticated Profile. The code also deletes the anonymous Profile data from the database. Lastly, the code calls a method in Anonymous Identification to clear the cookie that contains the anonymous identifier. Note that developers must explicitly choose to clear the anonymous identifier from the request - otherwise ASP.NET will not automatically clear the identifier. By the time the MigrateAnonymous event completes, ASP.NET will have issued an Http header to clear the anonymous identifier from the browser, and on subsequent page requests the event will no longer fire.

VB Migrating Profile data from an anonymous user to an authenticated user
Run Sample View Source

Defining Profile Properties with a Custom Base Class

The web.config shown earlier included an attribute called inherits on the <profile> element. This attribute instructs ASP.NET to autogenerate a class for the Profile property by inheriting from a custom base class. In this sample, the classname is UserDefinedProfileClass, and this class is located in the App_Code directory. The custom class inherits from ProfileBase because the autogenerated class for the Profile property must always have ProfileBase in the inheritance hierarchy. Any public properties defined on a custom base class are visible and useable from the Profile property.

Run the sample and log in again. On the properties page, the data from the listbox containing junk food preferences is stored using the property defined on the custom base class. As with other properties on the Profile, the food preferences are accessed using standard property syntax: Profile.JunkFood.

The advantage of defining a custom base class is that developers can "intercept" property sets and gets, and implement complex business logic in the property getters and setters. In the sample code, the custom base class defines a property using Generics. The property definition demonstrates the minimal requirements: the property implementations must call into the base class since it is the base class (ProfileBase) that contains the logic for serializing data as well as communicating to the underlying provider(s).

Profile schema in web.config
View Source
VB Using a Custom Base Class
Run Sample View Source

Controlling the Automatic Save Behavior of the Profile

The Profile feature will automatically determine whether or not a Profile is dirty. If the Profile appears to be dirty, the ProfileModule that runs at the end of each page request will call the Save method on the Profile, thus saving data using the configured provider(s). However, the Profile feature can only reliably detect changes to data when the data is typed as either a System.String, or as a primitive type like System.Int16 , System.Int32, etc... If a Profile contains more complex data-types, the default behavior of the Profile feature assumes the Profile is dirty, and will always attempt to save the data. To optimize performance, a developer can implement logic in their pages to determine if the Profile really is dirty. If a developer determines the Profile has not changed, they can hook the ProfileAutoSaving event by writing an event handler in global.asax. The event argument includes a property called ContinueWithProfileAutoSave. If a developer sets this property to false, then ProfileModule will not attempt to save the Profile.

Run the sample and log in again if necessary. This page is the same as the profile properties page used earlier, with the minor addition of a second button. If you edit any of the profile data, and then click on the button that cancels the automatic save behavior, when the page refreshes, the old property values will be displayed. The code sample demonstrates subscribing to the ProfileAutoSaving event in global.asax and cancelling the save if a property was set in the HttpContext.Items collection. The button click event handler on the page sets this item to indicate that the automatic save behavior should be cancelled.

Note that if a developer never wants the ProfileModule to attempt saves, the automatic save behavior for the feature can be turned off by setting the automaticSaveEnabled attribute on the <profile> element to false.

VB Controlling Automatic Profile Saves
Run Sample View Source

Deleting a Profile

Over time, the amount of profile data for a site will grow, especially for sites that use anonymous profiles. The ProfileManager class provides a number of methods for deleting profile data. This sample demonstrates using ProfileManager.DeleteProfile to delete the profile of the currently logged in user. When you run the sample you will first need to log in. Once you are logged in, you can click on the delete button to clear the profile data for the current user. You will then be redirected to the profile properties page. Notice that at this point all of your previous profile data has been deleted and you need to re-enter new profile data on the HTML form.

In production environments you would normally use ProfileManager in a scheduled maintenance task. For example, you could create a daily batch job that runs a console application using ProfileManager to delete profiles that have been inactive for more than thirty days. Since the Profile feature is supported in non-ASP.NET environments (for example: console applications or NT service applications) you can create operations oriented applications using the ProfileManager class.

VB Deleting a Profile
Run Sample View Source