Writing a custom ASP.NET Profile class

We made heavy use of the ASP.NET membership and profile system for Video.Show (a Silverlight 1.0 video community website system, available on CodePlex). In addition to storing basic profile information, we created a custom profile with some additional fields. It's a really easy way to add add some additional personalization to your site without having to add a bunch of tables to your database.

This is really simple if you're using a Website Project - you can just add additional properties to the profile section of your web.config, and a custom profile class is generated on the fly when you rebuild your application. That makes things ridiculously easy. First, we'd define the property in web.config:

<!-- In web.config -->
<profile >
  <properties>
    <add name="FavoritePasta" />
  </properties>
</profile>
Then you can refer to the Profile.FavoritePasta profile setting anywhere in your web application, and it's automatically mapped to the current user:
Profile.FavoritePasta = "Pumpkin Ravioli";
And you can access the data just as you would a session property:
<span id="user-favorite-pasta"><%= Profile.FavoritePasta %></span>

Not so fast, I'm using a Web Application Project

Yeah, here's the catch. If you're using the Web Application Project model, the custom build handling for the profile doesn't kick in, so those custom properties you've lovingly crafted in your web.config aren't going to be compiled into a custom profile class.

There's a Visual Studio 2005 add-in called WebProfile that reads your custom profile and creates a custom class for you. That's handy, but I passed on it. For one thing, I haven't heard that there's a VS 2008 version of this. Additionally, I don't like to require a custom add-in in order to get my code to work in case I want to add a new profile property - especially when I'm working on a project that's going to be distributed on CodePlex.

Fortunately, it's not very hard to implement a custom profile. First, we'll write a class that inherits from System.Web.Profile.ProfileBase. I added a few static accessors, too:

using System.Web.Profile;
using System.Web.Security;

namespace VideoShow
{
    public class UserProfile : ProfileBase
    {
        public static UserProfile GetUserProfile(string username)
        {
            return Create(username) as UserProfile;
        }

public static UserProfile GetUserProfile() { return Create(Membership.GetUser().UserName) as UserProfile; } [SettingsAllowAnonymous(false)] public string Description { get { return base["Description"] as string; } set { base["Description"] = value; } } [SettingsAllowAnonymous(false)] public string Location { get { return base["Location"] as string; } set { base["Location"] = value; } } [SettingsAllowAnonymous(false)] public string FavoriteMovie { get { return base["FavoriteMovie"] as string; } set { base["FavoriteMovie"] = value; } } } }

 
Now we need to  hook that up in the profile section of web.config - notice that I've included inherits="VideoShow.UserProfile" in the profile declaration:
 
<profile inherits="VideoShow.UserProfile">
  <providers>
    <clear />
    <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="VideoShowConnectionString"/>
  </providers>
</profile>
 
With that done, I can grab an instance of the custom profile class and set a property:
 
//Write to a user profile from a textbox value
UserProfile profile = UserProfile.GetUserProfile(currentUser.UserName);
profile.FavoriteMovie = FavoriteMovie.Text;
profile.Save();

Part of the reason for the accessor is to allow display of profile information for users other than the current user - for instance, a public profile page which displays information about other users in the system.

//Write to a user profile from a textbox value
UserProfile profile = UserProfile.GetUserProfile(displayUser.UserName);
Response.Write(profile.FavoriteMovie)

And of course, I can still databind to it as well:

<span id="user-favorite-movie"><%= VideoShow.UserProfile.GetUserProfile().FavoriteMovie %></span>

A few disclaimers:

  • This isn't news, it's been out since ASP.NET 2.0 shipped. Still, it's pretty handy to know about, and if you're like me you may have forgotten or never really dug into some of the ASP.NET 2.0 goodies.
  • This isn't the ultimate solution in terms of entity modeling. Custom profile information is stored in two columns in the aspnet_Profile table (delimited strings in one column, another column for binary serialized objects). That means that the only real way to read or write custom property values is via the profile API. That's not a real problem unless you need to query or join on information stored in a custom profile setting.

Further information:

Profiles in ASP.NET (K. Scott Allen)

Essential ASP.NET 2.0, Chapter 5 (Fritz Onion)

Published Saturday, January 19, 2008 11:46 PM by Jon Galloway
Filed under:

Comments

# re: Writing a custom ASP.NET Profile class

Cool article.

If you did want the profile fields to be stored in a standard way in SQL Server, you have option of using:_

SqlTableProfileProvider - www.asp.net/.../table-profile-provider-samples

There is also StoredProcedure provider as well.

They are both very handy if you want your data to be easily accessible at database level.

You can also mix and match profile providers at field level, in case you still wanted the flexibility of adding fields without touching the schema.

www.outofmemory.co.uk/.../ASPNET-Registration-with-multiple-profile-providers.aspx

Sunday, January 20, 2008 7:07 AM by Andrew Rimmer

# Movies and Film Blog &raquo; Writing a custom ASP.NET Profile class

Pingback from  Movies and Film Blog &raquo; Writing a custom ASP.NET Profile class

# links for 2008-01-22

links for 2008-01-22

Tuesday, January 22, 2008 4:27 AM by Javier-Romero

# re: Writing a custom ASP.NET Profile class

Thanks for posting this, Jon!  I'm creating my first real enterprise ASP.NET application, and I was struggling with the Membership API trying to get it to pass my provider custom data.  This is obviously the way to get that done.

Wednesday, January 30, 2008 11:20 AM by Brian Sullivan

# problemas caseritos en Web Application Projects... hoy Profiles

Cuando se liberaron los Web Application Projects (para saber m&#225;s de WSP y WAP, revise esta entrada

Friday, February 29, 2008 1:45 AM by SergioTarrillo's RichWeblog

# re: Writing a custom ASP.NET Profile class

Great article, however it blows an exception for me..

System.Configuration.ConfigurationErrorsException: This profile property has already been defined. (C:\Documents and Settings\Guy\My Documents\Visual Studio 2008\Projects\cal\cal\web.config line 105) at System.Web.Profile.ProfileBase.InitializeStatic() at System.Web.Profile.ProfileBase.Create(String username, Boolean isAuthenticated) at System.Web.Profile.ProfileBase.Create(String username) at cal.UserProfile.GetUserProfile(String username) in C:\Documents and Settings\Guy\My Documents\Visual Studio 2008\Projects\cal\cal\code\UserProfile.vb:line 7

The properties are not duplicated anywhere in the config file.

If i remove my properties and add a completely random one (such as ksdjekxkek) it works!>?!?>!

Do you have any idea what could be wrong as even a google search gives no clues

Saturday, March 08, 2008 10:39 AM by Guy Harwood

# re: Writing a custom ASP.NET Profile class

problem solved - by removing the property declarations from web.config.

because they are already defined in the new class that inherits profile base there is no need to delcare them in web.config.

that isnt so clear in the post!

but thanks - this is a great solution

Sunday, March 09, 2008 2:50 PM by Mr Baldman

# re: Writing a custom ASP.NET Profile class

Thanks for this. Saved me a lot of pain trying to figure out why it wouldn't work in my Web Application Project. Hopefully I'll get it going in a web service I'm putting together too.

Tuesday, March 11, 2008 6:01 AM by Matt

# re: Writing a custom ASP.NET Profile class

And here's a tip that may save you another hour  of pain ;)

Make sure that the name of the property you create matches the base property you try to return i.e. don't do this:

[SettingsAllowAnonymous(false)]

public string UserAge

{

 get { return base["Age"] as string; }

 set { base["Age"] = value; }

}

Otherwise it will complain with

"The settings property 'Age' was not found."

Change 'Age' to 'UserAge' and it will work.

Tuesday, March 11, 2008 8:22 AM by Matt

# re: Writing a custom ASP.NET Profile class

Can someone tell me how to translate the first two functions to VB.NET ? would be great.

Thanks!

Tuesday, March 11, 2008 10:55 AM by uquandux

# re: Writing a custom ASP.NET Profile class

Thanks!!  This really helped, plus helps reduce the opacity of the profile provider for future re-factoring.  I second Mr Baldman's posts - be sure to remove any <properties/> elements from the web.config file.

Tuesday, March 11, 2008 3:48 PM by Liatris

# php code and scripts &raquo; Blog Archive &raquo; Writing a custom ASP.NET Profile class

Pingback from  php code and scripts  &raquo; Blog Archive   &raquo; Writing a custom ASP.NET Profile class

# re: Writing a custom ASP.NET Profile class

Thanks for this code Jon.

I've implemented it easily in my site and it works great, but have you been able to unit test it?  On my first attempt, the inherited "Create" method returned a DefaultProfile object, which caused a casting failure.  I figured out that the Unit Tests were not using the web.config file to see the custom Profile Provider I configured, then I figured out you need to copy the web.config to the unit test project, and rename it to app.config.  However now I get the error.  

"Test method TestMyProject.UserControllerTest.CreateNewUserTest threw exception:  System.TypeLoadException: Could not load type 'MyRootNamespace.Profile.UserProfile' from assembly 'System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.."

I don't know why it is not looking the DLL that contains my custom "UserProfile" class.  Any ideas?  It works in my website, but not in the Unit Test.  The UnitTest project references the project containing the Profile class.  I'm using VS2008 built-in Unit Testing.

Thanks in advance.

Tuesday, March 25, 2008 3:58 PM by Scott Davis

# re: Writing a custom ASP.NET Profile class

Here it is in VB.Net

blog.steeleprice.net/.../1378.aspx

This methodology is MUCH better than any other add-in style scenarios!

Thanks a bunch Jon, I tore my hair out for days over this and this is BY FAR the best (and simplest) solution.

There ae a couple caveats with VB, first you have to use the Get/SetPropertyValue since we can't use MyBase("Location") etc... next, the Trycast in the Static methods were failing, but this may have been a compiler funkiness until I got it all sorted out. It still occassionally gives me "ProfileCommon" errors in the designer, but it does compile and work perfectly fine.

Monday, March 31, 2008 2:19 AM by Steele Price [MVP]

# re: Writing a custom ASP.NET Profile class

Anyone have any ideas about Scott's post above?

I am also trying to unit test the custom profile class. Any ideas?

Thanks,

Tim

Thursday, April 10, 2008 4:29 PM by Tim

# re: Writing a custom ASP.NET Profile class

hei .... can anyone please help me ?

I am trying to implement the custom profile class... so far so good... it just doesn't retrieve any info at all :(

i have added this in my web.config

<profile inherits="UserProfile">

     <providers>

       <clear />

       <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="LocalSqlServer"/>

     </providers>

   </profile>

and my UserProfile class is very much like the one above....

did anyone else experience this problem ?

thanks in advance ...

andu

Tuesday, April 15, 2008 9:45 PM by andu

# what is aspnet membership table

Pingback from  what is aspnet membership table

Wednesday, April 30, 2008 3:45 PM by what is aspnet membership table

Leave a Comment

(required) 
(required) 
(optional)
(required)