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

# re: Writing a custom ASP.NET Profile class

Thanks for saving me a ton of time!

Great article!

Best,

Brett

Monday, May 26, 2008 12:21 AM by Brett Nieland

# re: Writing a custom ASP.NET Profile class

How would you handle groupings using this method?

Thanks!

Brett

Monday, May 26, 2008 1:14 AM by Brett Nieland

# ASP.NET: Web Site versus Web Application Project

ASP.NET: Web Site versus Web Application Project

Sunday, June 01, 2008 9:04 PM by CodersBarn.com

# re: Writing a custom ASP.NET Profile class

I am facing the same issue as Scott and Tim above. I've posted about it on the forums:

forums.asp.net/.../2397754.aspx

Tuesday, June 03, 2008 10:44 AM by PMichaud

# re: Writing a custom ASP.NET Profile class

I echo Brett's question.  How in the heck do you handle grouping properties?  I've tried Googling to no avail.

Wednesday, June 18, 2008 9:41 AM by Jamie Cross

# re: Writing a custom ASP.NET Profile class

So will it automatically grab the related value from the profile table or a class is needed to do that job? I am little confused

Monday, June 23, 2008 2:11 PM by MH

# re: Writing a custom ASP.NET Profile class

So will it automatically grab the related value from the profile table or a class is needed to do that job? I am little confused.

Thursday, June 26, 2008 1:10 PM by MH

# re: Writing a custom ASP.NET Profile class

To use this approach with the SqlTableProfileProvider(www.asp.net/.../table-profile-provider-samples), you need to define the table properties in your custom profile class too, or you get the "This profile property has already been defined" error.

e.g.

[SettingsAllowAnonymous(true), CustomProviderData("FirstName;nvarchar")]

public string FirstName

{

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

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

}

Tuesday, July 22, 2008 8:39 PM by Martin Bayly

# re: Writing a custom ASP.NET Profile class

UserProfile profile = UserProfile.GetUserProfile(displayUser.UserName);

Giving null object.

how to resove it?

Wednesday, August 13, 2008 5:48 AM by Savvy

# re: Writing a custom ASP.NET Profile class

I'm Getting this problem on a Web Application. It's running on the website. Any Ideas?

Thursday, August 28, 2008 2:25 PM by ofern01

# re: Writing a custom ASP.NET Profile class

Thanks Martin Bayly for CustomProviderData howto use mention!

Saturday, August 30, 2008 8:53 PM by Roman

# re: Writing a custom ASP.NET Profile class

Thx for your explanation. It helped me a lot.

Wednesday, September 03, 2008 8:54 AM by Xavier

# re: Writing a custom ASP.NET Profile class

Awesome! Thanks for this code Jon.

I've implemented it easily in my site and it works great. Thanks for saving me a ton of time. It helped me a lot.

Wednesday, October 22, 2008 3:50 PM by Thomas Drago

# web应用程序中页面无法直接访问Profile,但是网站中可以。

web应用程序中页面无法直接访问Profile,但是网站中可以。

Profile只能应用于WebSiteProject中才能使用这个特性,在WebApplication项目无法使用,那么在...

Monday, November 03, 2008 11:09 PM by min10

# re: Writing a custom ASP.NET Profile class

I had the same problem with running custom providers in unit tests and I have found the answer so I thought you might want to know if you are still dealing with this problem.

Check your app.config in your unit test.

Your membership section should be in this format. The change you have to make is in the TYPE attribute. You have to add the namespace or it will look in system.web for the provider and mess up the references.

<membership defaultProvider="MeanWormMembershipProvider">

     <providers>

       <remove name="AspNetSqlMembershipProvider"/>

         <add applicationName="MeanWorm" requiresQuestionAndAnswer="false"

           requiresUniqueEmail="true" minRequiredNonalphanumericCharacters="0"

           enablePasswordReset="true" passwordFormat="Hashed" connectionStringName="MeanWormConnectionString"

           name="MeanWormMembershipProvider" type="MeanWorm.Domain.Providers.MeanWormMembershipProvider,MeanWorm.Domain" /><!-- RIGHT HERE ADD YOUR PARTIAL ASSEMBLY NAME -->

     </providers>

   </membership>

I found this answer from this post: forums.asp.net/.../2397754.aspx

Thanks for everyone's posts.

Thursday, November 13, 2008 12:41 PM by kevin

# re: Writing a custom ASP.NET Profile class

Is it possible to set a property as "[SettingsAllowAnonymous(true)]" and get the profile for an anonymous user?

I have been trying to do this but I am not able.

Could someone, please, help me out?

Friday, November 14, 2008 3:17 PM by shapper

# re: Writing a custom ASP.NET Profile class

I think there is a bug on this code. Did someone tried to get and change the profile of an anonymous user?

I made the following change to my code:

   public static ProfileHelper GetProfile() {

     return Create(System.Web.Security.Membership.GetUser().UserName)

as ProfileHelper;

   } // GetProfile

By:

   public static ProfileHelper GetProfile() {

     return Create(HttpContext.Profile.UserName) as ProfileHelper;

   } // GetProfile

Now it is working with anonymous users.

Could someone give me a second opinion on this?

Thank You

Friday, November 14, 2008 6:42 PM by shapper

# re: Writing a custom ASP.NET Profile class

How in the heck do you handle grouping properties in the class? Was anyone able to find the answer, if so could you please post it.

Thursday, November 20, 2008 9:44 AM by drs

# re: Writing a custom ASP.NET Profile class

I was able to answer my own question. What I did was i used a demo website project and setup my profile properties and groups in the webconfig so that it would autogenerate the class into Asp.Net Temporary files and then looked at how the code got generated for the groups.

Thursday, November 20, 2008 3:09 PM by drs

# re: Writing a custom ASP.NET Profile class

Did anyone figure out how to get a custom profile class with groups to work with the SqlStoredProcedureProfileProvider? I can't get it to pick up my groups

Sunday, November 23, 2008 1:47 PM by dsteinle

# re: Writing a custom ASP.NET Profile class

DRS, can you post an example of the group code?

Monday, November 24, 2008 7:23 PM by Andrew

# re: Writing a custom ASP.NET Profile class

I'm also unable to get profile groups to work with the custom profile class. Has anyone played around with attributes of the <profile> tag to see if there's some "secret" setting that causes a  ProfileGroup to get recognized by ASP.NET and included in the custom object that it generates?

Saturday, December 13, 2008 5:34 PM by Jim Black

# re: Writing a custom ASP.NET Profile class

Can this profile type be accessed for a winform, is so how?

Monday, January 12, 2009 2:30 AM by Mike

# re: Writing a custom ASP.NET Profile class

Thanks, Jon. You just saved my sanity.

Friday, January 16, 2009 9:32 AM by Michael Earls

# Get anonymous profile | keyongtech

Pingback from  Get anonymous profile | keyongtech

Sunday, January 18, 2009 12:08 PM by Get anonymous profile | keyongtech

# re: Writing a custom ASP.NET Profile class

As Jim Black said over there, we're stuck on that same issue over at Omar's:

msmvps.com/.../how-to-use-asp-net-2-0-profile-object-from-web-service-code.aspx

I thought I had an answer in just going back to web.config for the groups, but while my property call at least runs without "the profile group ... has not been defined" error now, it just returns the default value...!

Sunday, February 01, 2009 12:41 PM by David Ross

# re: Writing a custom ASP.NET Profile class

UserProfile profile = UserProfile.GetUserProfile(displayUser.UserName);

Giving null object. because Unable to cast object of type 'ProfileCommon' to type 'UserProfile'.

how to resove it?

thanks

Saturday, February 21, 2009 1:24 AM by Amir

# Inheritance and Interfaces | keyongtech

Pingback from  Inheritance and Interfaces | keyongtech

Saturday, April 11, 2009 9:07 PM by Inheritance and Interfaces | keyongtech

# re: Writing a custom ASP.NET Profile class

Has anyone developed a solutin to the null object problem that several people asked about? I implemented this custome profile provider exactly as shown but keep getting a null profile back. The UserProfile.Save() does not appear to be saving at all. Any help?

Friday, June 12, 2009 12:29 PM by James

Leave a Comment

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