My musings about .NET and what not

ASP.NET Profiles in Web Application Projects

Accessing ASP.NET profiles from a web application project is remarkably easy once you know how. Here’s how it’s done, along with a fully working implementation that you can download.


Earlier this year, I blogged about how to create a strongly-typed Profile that could be accessed from a class library. In response to popular demand, today I’m presenting a similar (but more substantial) example geared specifically toward accessing profiles in web application projects.

There are plenty of blog posts that talk about this, but unfortunately very few that show how to do it. Most of them instead refer to this relatively obscure add-in for Visual Studio 2005 (apparently. you’re out of luck if you’re using Visual Studio 2008). However, the good news is you don’t need a third party add-in or build task for this, as implementing this functionality yourself is not difficult at all.

If you’re reading this, I’ll assume you’re aware of the differences between an ASP.NET web site and a web application, so I won’t go into the various differences in great detail (feel free to consult the MSDN for more information). For our purposes, it’s just important to understand that in a web application project, there is no ProfileCommon class or Page.Profile property to work with, as we’re accustomed to seeing in web site projects – hence the problem.

Web site projects accomplish this bit of magic through dynamic compilation – essentially creating the needed objects at runtime, “on the fly” as it were. In effect we will be doing the exact same thing, but the old-fashioned way – with a simple hand-written proxy class.

Writing a Profile Proxy Class

Let’s assume for the sake of discussion that we have several bits of user information we want to store in profile.

  • first name
  • last name
  • date of birth
  • gender
  • the user’s time zone
  • the user’s preferred culture

Now, we could store these as separate value types, but in practice I find it easier to group related properties together in a class. So let’s create a class Personal to store the first four properties, and a class Preferences to store the time zone and culture. Make sure to decorate these classes with the [Serializable] attribute.

namespace LD.Sample.BLL
{
   using System;

   [Serializable]
   public class Personal
   {
      public string FirstName { get; set; }

      public string LastName { get; set; }

      public DateTime DateOfBirth { get; set; }

      public Gender Gender { get; set; }
   }
}
namespace LD.Sample.BLL
{
   using System;

   [Serializable]
   public class Preferences
   {
      public string TimeZone { get; set; }
      
      public string Culture { get; set; }
   }
}

Next, we’ll write a class that will define the profile we want, incorporating the two custom types shown above as properties. This class will inherit ProfileBase . Let’s call it CustomProfile.

namespace LD.Sample.BLL
{
   using System.Web;
   using System.Web.Profile;

   public class CustomProfile : ProfileBase
   {
      public Personal Personal
      {
         get { return (Personal) GetPropertyValue("Personal"); }
      }

      public Preferences Preferences
      {
         get { return (Preferences) GetPropertyValue("Preferences"); }
      }

      /// <summary>
      /// Get the profile of the currently logged-on user.
      /// </summary>      
      public static CustomProfile GetProfile()
      {
         return (CustomProfile) HttpContext.Current.Profile;
      }

      /// <summary>
      /// Gets the profile of a specific user.
      /// </summary>
      /// <param name="userName">The user name of the user whose profile you want to retrieve.</param>
      public static CustomProfile GetProfile(string userName)
      {
         return (CustomProfile) Create(userName);
      }
   }
}

Note that I’ve also included two overloaded static GetProfile methods. GetProfile()  lets us obtain the profile of the current user, while GetProfile(string userName) lets us get the profile of a specific user (for administrative purposes, or when creating a new member, for example).

One more thing – and this is very important – we need to define the provider in web.config.

<profile defaultProvider="LD.SampleWAP.ProfileProvider" inherits="LD.Sample.BLL.CustomProfile">
<providers>
   <add name="LD.SampleWAP.ProfileProvider"
   type="System.Web.Profile.SqlProfileProvider"
   applicationName="/"
   connectionStringName="LocalSqlServer"/>
</providers>

You’ll see that our provider is of type System.Web.Profile.SqlProfileProvider. Of course, this assumes that the database to which this is pointing has been configured with the schema required to support SqlProfileProvider.

Also note the inherits attribute in <profile>. This is what tells the provider where to obtain the profile properties – in our case, from the CustomProfile class. When you do this, you do not want to define the properties declaratively in web.config, as you would in a website project. If you do, you’ll get a System.Configuration.ConfigurationException, informing you that the profile property has already been defined.

Usage

And that, believe it or not, is all there is to setting up a strongly-typed profile for use in a web application project. Now, let’s take a look at how you can use this newly-implemented goodness.

Here is some code that shows setting profile values for the currently logged-on user.

CustomProfile profile = CustomProfile.GetProfile();

profile.Personal.FirstName = "Tami";
profile.Personal.LastName = "Gharst";
profile.Personal.DateOfBirth = new DateTime(1972, 7, 10);
profile.Personal.Gender = Gender.Female;
profile.Preferences.TimeZone = "W. Europe Standard Time";
profile.Preferences.Culture = "de-DE";

profile.Save();

Here is some code that shows setting profile values for a specific user with the user name “Lee”.

CustomProfile profile = CustomProfile.GetProfile("Lee");

profile.Personal.FirstName = "Lee";
profile.Personal.LastName = "Dumond";
profile.Personal.DateOfBirth = new DateTime(1961, 10, 9);
profile.Personal.Gender = Gender.Male;
profile.Preferences.TimeZone = "Central Standard Time";
profile.Preferences.Culture = "en-US";

profile.Save();

If you like, you can make this even simpler by adding a Profile property to the page you’re working with – or even better, inherit your pages from a base type and add it there, so it’s available to all of your pages. This lets you set and retrieve profile properties with the familiar ASP.NET web site syntax.

// set profile properties

Profile.Personal.FirstName = "Lee";
Profile.Personal.LastName = "Dumond";
Profile.Personal.DateOfBirth = new DateTime(1961, 10, 9);
Profile.Personal.Gender = Gender.Male;
Profile.Preferences.TimeZone = "Central Standard Time";
Profile.Preferences.Culture = "en-US";

Profile.Save();
// display profile properties

lblDisplay.Text =
   string.Format(
      "User {0} had a real name of {1} {2}, was born on {3}, lives in the {4} time zone, and has a preferred culture of {5}.",
      Profile.UserName, 
      Profile.Personal.FirstName, 
      Profile.Personal.LastName,
      Profile.Personal.DateOfBirth.ToShortDateString(),
      Profile.Preferences.TimeZone,
      Profile.Preferences.Culture);

Sample Application

As I mentioned, I’ve included a downloadable web application solution that demonstrates web application profiles in action. When you run it, you’ll be greeted by the following screen:

image

There are screens that let you display a profile, edit a profile, and create a new one.

image

image

Examining the source code, along with the preceding explanation, should make understanding these concepts a snap.

I hope this helps the next time you find yourself needing access to profile properties from a web application!

Download sample code: WebApplicationProfileSample.zip

Subscribe to this blog for more cool content like this!

Tweet this blog post

kick it on DotNetKicks.com

shout it on DotNetShoutOut.com

vote it on WebDevVote.com

Bookmark / Share

    » Similar Posts

    1. Getting Strongly Typed Profile Properties From a Class Library
    2. Building a TweetThis Extension with Automatic Bit.ly for Graffiti CMS
    3. Singletons vs. Static Classes

    » Trackbacks & Pingbacks

    1. Pingback from Getting Strongly Typed Profile Properties From a Class Library : LeeDumond.com

    2. Pingback from Twitter Trackbacks for ASP.NET Profiles in Web Application Projects : LeeDumond.com [leedumond.com] on Topsy.com

    3. You've been kicked (a good thing) - Trackback from DotNetKicks.com

      ASP.NET Profiles in Web Application Projects — October 8, 2009 10:19 AM
    4. DotNetBurner - burning hot .net content

      ASP.NET Profiles in Web Application Projects — October 8, 2009 6:42 PM
    5. Pingback from ASP.NET Profiles in Web Application Projects : LeeDumond.com | Webmaster Tools

    6. Pingback from Dew Drop – October 9, 2009 | Alvin Ashcraft's Morning Dew

    7. Daily tech links for .net and related technologies - October 9-11, 2009 Web Development Using MvcContrib

    8. Thank you for submitting this cool story - Trackback from DotNetShoutout

      ASP.NET Profiles in Web Application Projects — October 15, 2009 6:32 AM
    9. You are voted (great) - Trackback from WebDevVote.com

      ASP.NET Profiles in Web Application Projects — October 15, 2009 6:34 AM
    Trackback link for this post:
    http://leedumond.com/trackback.ashx?id=78

    » Comments

    1. Anthony avatar

      Cool explanation! Joel Wrobel has taken the project you mention on CodePlex and updated it to work as a build task that is supposed to work for VS 2008 - I haven't tried it. But it does allow use of the config file for the declarations:

      weblogs.asp.net/.../web-profile-bui

      I still prefer your way because it is self-documenting! :-)

      Anthony — October 8, 2009 10:01 AM
    2. Steve Walker avatar

      Yup; I've found when migrating from web to app it was always a bind to re-do all the profile stuff but after a good dig about I found two ways:

      a get:

      decimal delivery = (decimal)Context.Profile.GetPropertyValue("delivery");

      a set:

      Context.Profile.SetPropertyValue("delivery", delivery);

      Work perfectly well, you have to cast the profile object but that is not a major headache if you're only using it here and there - and sometimes quicker than a class, but less portable.

      The other option is the custom build provider for WebProfile which works very well. Add that to VS2008 or earlier and then just let it run once and a class is created for your profile from the details in the web.config, drop that in your code folder and you're good to go!

      It's up on codeplex and even has a config file for making changes to the classname, filename and location of the generated code. http://webprofile.codeplex.com - In fact once you've made the class and you're not changing it then you can <!-- --> out the build task and only re enable it when you need to update the profile class if you've changed it.

      Regards,

      Steve

      Steve Walker — October 23, 2009 5:30 AM
    3. Maxi avatar

      However, the good news is you don’t need a third party add-in or build task for this

      Agree X 100

      Maxi — December 23, 2009 8:14 PM
    4. Maxi avatar

      Have you try to put that profile.cs in App_Code.

      It will give you casting error, how is that?

      Maxi — December 23, 2009 9:22 PM
    5. Lee Dumond avatar

      @Maxi - This applies to Web Application Projects only. There is no App_Code, as you can see from the sample download.

      Lee Dumond — December 23, 2009 9:32 PM

    » Leave a Comment