I have a friend with whom I have a never-ending IM conversation. You know what I mean: We never say “Hello” or “TTYL”. Conversations just gradually flow in and out, as in some extended stream of consciousness. Ever since I left Los Angeles, this friend and I can’t meet for lunch, take a hike up the hill, or a morning bike ride around Pasadena. We both miss these benefits of proximity and self-employment. So, we make do with IM.

The little IM popup window appears regularly with comments on a recent TV show (“I already miss West Wing”), the state of the dog (“Taking Max out for a walk”) or his owner (“Feeling kinda cruddy this morning”), and the important questions of life (“Should I have toast or a bagel this morning for breakfast?”), without introduction, greeting, or context. One morning, this one pops up (and, as you might imagine, acted as the germination of the idea for this article): “How can I retrieve Profile information from a class library called from a Web page?”

Amazingly, I had just completed a courseware chapter on the Profile features in ASP.NET, and so I figured I had to have something in there that would help. For those unclear on the concept, you can define a schema for user-oriented profile information by adding a section to your site’s Web.config file, like this:

<profile>
  <properties>
    <add name="LastVisitedDate"
      type="System.DateTime"
      allowAnonymous="true"/>
    <add name="FullName"
      type="System.String"
      allowAnonymous="true"/>
    <add name="PrivateInfo"
      type="UserInfo"/>
    <group name="LocationInfo">
      <add name="State"
        type="System.String"
        allowAnonymous="true"/>
      <add name="PostalCode"
        type="System.String"
        allowAnonymous="true"/>
    </group>
  </properties>
</profile>

At design time, the language compiler takes this information and generates an object of type ProfileCommon named Profile, with properties that match the properties defined in the configuration file (LastVisitedDate, FullName, PrivateInfo; of the type UserInfo, a class defined in my sample project, containing Birthdate and SSN properties; and LocationInfo, a “structure” of properties defined in web.config, containing State and PostalCode properties). In your site’s code, you can include code like this to retrieve and set properties of the current user’s profile:

[Visual Basic]
If Profile.LastVisitedDate <> _
 DateTime.MinValue Then
' Only display the date if you've
' already been through here.
  lblLastDate.Text = _
   "You last visited on " & _
   Profile.LastVisitedDate.
   ToShortDateString()
End If
    
Profile.LastVisitedDate = DateTime.Today
    
[C#]
if (Profile.LastVisitedDate !=
  DateTime.MinValue)
{
  // Only display the date if you've
  // already been through here.
    lblLastDate.Text =
      "You last visited on " +
      Profile.LastVisitedDate.
      ToShortDateString();
}
Profile.LastVisitedDate =
DateTime.Today;

You can work with the auto-generated Profile object, loading a profile for any user (the ASP.NET profile management code stores each user’s profile information in a database-a SQL Express database named ASPNETDB.MDF, by default), using code like this:

' Call the DisplayData procedure like
' this:
' DisplayData(Profile.GetProfile
' ("Russ"))
    
Private Sub DisplayData( _
 ByVal currentProfile As ProfileCommon)
  ' Retrieve data from the selected
  ' profile, and display in
  ' controls on the page.
  txtName.Text =
  currentProfile.FullName
  ' Display the rest of the data here…
End Sub

The real problem comes when you attempt to retrieve profile data in a project outside the current site. You define all the schema for the Profile object in web.config, but a class library project doesn’t have the web.config available to it, nor will Visual Studio automatically create the Profile object for you unless you’re in a Web project, and you’ve set up the schema in the configuration file.

What can you do to solve this problem? I first looked into the ProfileManager class, which almost seems to provide the information you might need. You could write code like this, in order to find a particular profile:

' Set a reference to System.Web, and add
' the following to the top of the file:
Imports System.Web.Profile
' or in C#:
' using System.Web.Profile;
    
For Each info As ProfileInfo In _
 ProfileManager. _
 FindProfilesByUserName( _
  ProfileAuthenticationOption. _
  Authenticated, "Ken")
  System.Diagnostics. _
   Debug.Print(info.UserName)
Next

The problem is that the ProfileInfo class provides only the minimum values for each profile, including the UserName, LastActivityDate, and a few other properties-it doesn’t include any of the properties added through the schema you define in Web.config.

The answer, which my friend finally found on his own, is to use the System.Web.Profile.ProfileBase class to do the work. You can use this class’ Create method to retrieve the specified user’s profile information from the current data store, even though the currently running code (in a class library) doesn’t have direct access to the web.config schema. For example, you could write code like this to create a ProfileBase object and retrieve a profile property:

[Visual Basic]
Public Function GetState( _
  ByVal userName As String) As String
  Dim profile As ProfileBase = _
   ProfileBase.Create(userName)
  Return profile("LocationInfo.State")
End Function
    
[C#]
public string GetState(string userName)
{
  ProfileBase profile =
    ProfileBase.Create(userName);
  Return profile["LocationInfo.State"];
}

As you can tell, you’re on your own when retrieving information from the ProfileBase instance you create-the class exposes the profile values in a dictionary, so you supply the string index, and the class provides the corresponding value.

Is this a tip of earth-shattering importance? Probably not. On the other hand, it’s nearly impossible to retrieve the profile information from outside a running Web site by any other means, so it’s nice to know that this technique exists. (You’ll also find it useful to investigate the System.Profile.ProfileManager class, which provides lots of useful methods for managing profiles, including the important DeleteInactiveProfiles-otherwise, there’s no way to remove the myriad anonymous profiles you’ll find clogging your site’s ASPNETDB database.) And in the same IM conversation, I learned all sorts of other interesting, if not quite so useful, factoids. If only every IM thread was so fruitful.

Ken Getz