The ProfileProvider


The ProfileProvider

The ProfileProvider is probably one of the most versatile providers in ASP.NET. It doesn't store user credentials or user role membership. Instead, this provider is responsible for storing arbitrary properties about the users themselves. As you have seen in previous chapters, when you define user profile properties in the Web.config file, you can use them in a strongly typed fashion at compile time in the Visual Studio environment using the Profile static class within a Web Form.

Introduction to the ProfileProvider Base Class

The ProfileProvider abstract base class provides methods that deal with locating user profiles, reading and writing properties on those profiles, and modifying, creating, and deleting those profiles. Table 29.5 contains the methods that you will be overriding in your custom implementation of the ProfileProvider class.

Table 29.5. ProfileProvider Methods

Method

Description

DeleteInactiveProfiles

Deletes all user profile data for profiles where the last activity date was older than the indicated date

DeleteProfiles

Deletes a list of user profiles as indicated by the user profiles in the supplied ProfileInfoCollection object

FindInactiveProfilesByUserName

Finds a list of inactive users where the supplied user name matches

FindProfilesByUserName

Finds a list of users where the supplied user name matches (regardless of whether the profile is inactive)

GetAllInactiveProfiles

Gets all profiles where the last activity date was older than the indicated date

GetAllProfiles

Gets all profiles in the data store

GetNumberOfInactiveProfiles

Gets the number of inactive profiles contained in the store


Implementing a Profile Schema

A quick examination of the ProfileProvider abstract base class reveals that a lot of the interface takes place with the ProfileInfo and ProfileInfoCollection classes. The ProfileInfo class has very few properties and only tracks basic information such as UserName, IsAnonymous, LastActivityDate, LastUpdatedDate, and Size. More important than storing the user name is the storage of profile properties. In most Profile providers, developers can create arbitrary properties.

If you are going to create a custom provider, you will need to be able to store arbitrary data associated with a given user. To do this, I used a parent-child table where the child table contained rows of name-value pairs associated with a specific user. Figure 29.3 shows the typed dataset ProfileDataSet. The only really important thing of note in the schema shown in Figure 29.3 is that the UniqueId column is a System.Guid and it is generated programmatically each time a new row is created.

Figure 29.3. The ProfileDataSet typed dataset.


Creating a Custom Profile Provider

As with the previous providers, I have split the Provider implementation and the private utility methods into two files so that the code is easy to read and follow. The utility methods that are not included in Listing 29.3 are: InitializeData, SaveData, AppendAuthOptionToQuery, GetProfileByUserName, CreateUserProfile, QueryProfiles, ProfileRowsToProfileInfoCollection, ProfilesRowToProfileInfo, GetProfileProperty, and TouchActivityDates.

Listing 29.3. The XML Profile Provider

using System; using System.Xml; using System.Configuration; using System.Web; using System.Web.Profile; using System.Web.Security; using System.Collections.Generic; using System.Text; using System.Collections; namespace SAMS.CustomProviders.XML { public partial class ProfileProvider : System.Web.Profile.ProfileProvider {   private string profileFile = string.Empty;   private string name = string.Empty;   private ProfileDataSet profileData = null;   private string applicationName = string.Empty; public override void Initialize(string name,     System.Collections.Specialized.NameValueCollection config) {   this.name = name;   if (config["connectionStringName"] != null)     profileFile =     ConfigurationManager.ConnectionStrings[       config["connectionStringName"]].ConnectionString;     else       profileFile = @"D:\SAMS\C# Unleashed 2005\Chapters\29\Code\Data\Profiles.XML";     if (config["applicationName"] != null)       applicationName = config["applicationName"];     else       applicationName = HttpContext.Current.Request.ApplicationPath;     InitializeData(); } public override string Description {   get { return "XML Profile Provider"; } } public override string Name {   get { return name; } } public override int DeleteInactiveProfiles(ProfileAuthenticationOption     authenticationOption, DateTime userInactiveSinceDate) {   string query = string.Format(     "ApplicationName ='{0}' AND LastActivityDate <= '{1}'",     applicationName, userInactiveSinceDate);   int totalRecords;   ProfileDataSet.ProfilesRow[] profiles = QueryProfiles(query,     authenticationOption, 0, Int32.MaxValue, out totalRecords);   foreach (ProfileDataSet.ProfilesRow profile in profiles)   {     profile.Delete();   }   SaveData();   return totalRecords; } public override int DeleteProfiles(string[] usernames) {   int x = 0;   foreach (string user in usernames)   {     ProfileDataSet.ProfilesRow profile = GetProfileByUserName(user);     profile.Delete();     x++;   }   SaveData();   return x; } public override int DeleteProfiles(ProfileInfoCollection profiles) {   int x = 0;   foreach (ProfileInfo pi in profiles)   {     ProfileDataSet.ProfilesRow profile = GetProfileByUserName(pi.UserName);     profile.Delete();     x++;   }   SaveData();   return x; } public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption,   string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize,   out int totalRecords) {   string query = string.Format(    "UserName='{0}' AND ApplicationName='{1}' AND LastActivityDate <= '{1}'",    usernameToMatch, applicationName, userInactiveSinceDate);  ProfileDataSet.ProfilesRow[] profiles = QueryProfiles(    query, authenticationOption, pageIndex, pageSize, out totalRecords);  return ProfileRowsToProfileInfoCollection(profiles); } public override ProfileInfoCollection FindProfilesByUserName( ProfileAuthenticationOption   authenticationOption, string usernameToMatch, int pageIndex,   int pageSize, out int totalRecords) {   string query = string.Format(     "UserName='{0}' AND ApplicationName='{1}'",     usernameToMatch, applicationName);   ProfileDataSet.ProfilesRow[] profiles = QueryProfiles(     query, authenticationOption, pageIndex, pageSize, out totalRecords);   return ProfileRowsToProfileInfoCollection(profiles); } public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption   authenticationOption, DateTime userInactiveSinceDate,   int pageIndex, int pageSize, out int totalRecords) {   string query = string.Format(     "LastActivityDate <= '{0}' AND ApplicationName='{1}'", userInactiveSinceDate,     applicationName);   ProfileDataSet.ProfilesRow[] profiles = QueryProfiles(     query, authenticationOption, pageIndex, pageSize, out totalRecords);   return ProfileRowsToProfileInfoCollection(profiles); } public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption     authenticationOption, int pageIndex, int pageSize, out int totalRecords) {   string query = string.Format(     "ApplicationName='{0}'", applicationName);   ProfileDataSet.ProfilesRow[] profiles = QueryProfiles(     query, authenticationOption, pageIndex, pageSize, out totalRecords);   return ProfileRowsToProfileInfoCollection(profiles); } public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption   authenticationOption, DateTime userInactiveSinceDate) {   int totalRecords;   ProfileInfoCollection pic = GetAllInactiveProfiles(authenticationOption,     userInactiveSinceDate, 0, Int32.MaxValue, out totalRecords);   return totalRecords; } public override string ApplicationName { get {   return applicationName; } set {   applicationName = value; } } public override System.Configuration.SettingsPropertyValueCollection GetPropertyValues(     System.Configuration.SettingsContext context,     System.Configuration.SettingsPropertyCollection collection) {   string userName = (string)context["UserName"];   bool isAuthenticated = (bool)context["IsAuthenticated"];   ProfileDataSet.ProfilesRow user = GetProfileByUserName(userName);   if (user == null)     user = CreateUserProfile(userName, isAuthenticated);   SettingsPropertyValueCollection svc = new SettingsPropertyValueCollection();   foreach (SettingsProperty prop in collection)   {     SettingsPropertyValue propValue = new SettingsPropertyValue(prop);     ProfileDataSet.ProfilePropertiesRow propRow = GetProfileProperty(       user, prop.Name);     if (propRow != null)     {       propValue.PropertyValue = propRow["PropertyValue"];     }     svc.Add(propValue);   }   TouchActivityDates(user, true);   return svc; } public override void SetPropertyValues( System.Configuration.SettingsContext context,     System.Configuration.SettingsPropertyValueCollection collection) {   string userName = (string)context["UserName"];   bool isAuthenticated = (bool)context["IsAuthenticated"];     ProfileDataSet.ProfilesRow user = GetProfileByUserName(userName);     if (user == null)       user = CreateUserProfile(userName, isAuthenticated);     foreach (SettingsPropertyValue propValue in collection)     {       ProfileDataSet.ProfilePropertiesRow propRow =         GetProfileProperty(user, propValue.Name);       if (propRow != null)         propRow["PropertyValue"] = propValue.PropertyValue;       else       {         propRow = profileData.ProfileProperties.NewProfilePropertiesRow();         propRow["UniqueId"] = user.UniqueId;         propRow["PropertyValue"] = propValue.PropertyValue;         propRow["PropertyName"] = propValue.Name;         profileData.ProfileProperties.AddProfilePropertiesRow(propRow);     }     }     SaveData();     TouchActivityDates(user, false); } } } 

Configuring and Installing the Profile Provider

The Profile provider also has its own Web.config entry. As with the other providers, if you plan on sharing the provider among multiple applications on the same server, you should install the provider into the Global Assembly Cache. Otherwise, you are fine just ensuring that the provider's Assembly is in your web application's bin directory.

The first thing you need is a connection string in the <connectionStrings> Web.config element:

<add name="profileProvider"     connectionString= "D:\SAMS\C# Unleashed 2005\Chapters\29\Code\Data\Profiles.XML"/> 


Next you can add the <profile> element to the Web.config file:

<profile defaultProvider="xmlProfile" enabled="true"> <providers> <add name="xmlProfile" type="SAMS.CustomProviders.XML.ProfileProvider" applicationName="CustomProviderDemo" connectionStringName="profileProvider" /> </providers> <properties><add name="ShoeSize" type="System.Int32" allowAnonymous="false" /> <add name="FavoriteColor" type="System.String" allowAnonymous="false" /> </properties> </profile> 




Microsoft Visual C# 2005 Unleashed
Microsoft Visual C# 2005 Unleashed
ISBN: 0672327767
EAN: 2147483647
Year: 2004
Pages: 298

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