Whither Profile?

Onion Blog

Syndication

As developers begin shifting to ASP.NET 2.0, one of the biggest hurdles they will face is understanding the multitude of choices they now have and the implications of those choices on their design. Case and point, Profile. The Profile feature in ASP.NET gives you a simple way of defining database-backed user profile information. It is similar to Session in many ways since it is data stored per client, but it has the advantage of always being written to and read from a database, thus avoiding many of the issues with session state (like its lack of durability or its inability to scale to a web farm deployment).
 
Here's a small example of using profile to give you an idea. First, declare the properties you would like to store on behalf of each user in your web.config file under the <profile> element:
 
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <system.web>
    <profile>
      <properties>
        <add name="firstname" type="System.String" />
        <add name="lastname" type="System.String" />
        <add name="age" type="System.Int32" />
      </properties>
    </profile>
  </system.web>
</configuration>
 
When ASP.NET compiles your site, it creates a new class that derives from HttpProfileBase with typesafe accessors to the properties you declared. These accessors use the profile provider to save and retrieve these properties to and from whatever database the provider is configured to interact with. Here's what the generated class looks like for the properties declared above:
 
namespace ASP
{
  public class HttpProfile : HttpProfileBase
  {
    public virtual string lastname
    {
      get
      {
        return ((string)(this.GetPropertyValue("lastname")));
      }
      set
      {
        this.SetPropertyValue("lastname", value);
      }
    }
    public virtual string firstname
    {
      get
      {
        return ((string)(this.GetPropertyValue("firstname")));
      }
      set
      {
        this.SetPropertyValue("firstname", value);
      }
    }
    public virtual int age
    {
      get
      {
        return ((int)(this.GetPropertyValue("age")));
      }
      set
      {
        this.SetPropertyValue("age", value);
      }
    }
    public virtual ASP.HttpProfile GetProfile(string username)
    {
      return ((ASP.HttpProfile)(System.Web.Profile.HttpProfileBase.Create(username)));
    }
  }
}
 
The second thing that happens, is ASP.NET adds a property declaration to each generated Page class in your site named 'Profile' which is a typesafe accessor to the current profile class (which is part of the HttpContext):
 
public partial class Default_aspx : Page
{
  protected ASP.HttpProfile Profile
  {
    get { return ((ASP.HttpProfile)(this.Context.Profile)); }
  }
  //...
}
 
This lets you interact with your profile properties in a very convenient way, for example, here's an example of setting the profile properties based on fields in a form:
 
void enterButton_Click(object sender, EventArgs e)
{
  Profile.firstname = firstNameTextBox.Text     ;
  Profile.lastname  = lastNameTextBox.Text      ;
  Profile.age       = int.Parse(ageTextBox.Text);
}
 
If you look in the database used by the profile provider (currently an Access .mdb file by default), you will see a table called aspnet_Profile with 4 columns:
 
UserId
PropertyNames
PropertyValuesString
LastUpdatedDate
 
In our example above, these columns were populated with the following values:
1
firstname:S:0:3:lastname:S:3:5:age:S:8:2:
JoeSmith22
9/28/2004 8:27:12 AM
 
So you can see that the Profile provider uses a string serialization with property names and string lengths carefully stored as well on a per-user basis.
 
What concerns me about this model, is that it is extremely convenient to use, but it produces a very chatty interface with the database with data that is basically an opaque blob to anyone but the profile provider itself (meaning no stored procs can interact with the data, nor can you do join queries across tables using profile information). Every time you use the Profile object to access/set a property, you incur a round trip the database.
 
You can ameliorate the inefficiency somewhat this somewhat by defining your own classes (like Person) and storing instances of classes in profile instead of individual values, but at that point it feels like you are designing a data access layer and you may as well go all the way and forego Profile altogether.
 
In the end, I'd have to recommend that people use this feature for quick prototyping and/or sites where scalability and carefully designed database schema are not a concern (like for your local tennis tournament :) If people feel otherwise, I'd be interested in hearing why.
 
[One last note - there is a nice feature of profile that lets you store data on behalf of anonymous users and then migrate that data to a known user once then log in or create an account, but that's still not enough for me to recommend using it for large scale sites.]

Posted Sep 28 2004, 06:55 AM by fritz-onion
Filed under:

Comments

Adam Creeger wrote re: Whither Profile?
on 09-28-2004 6:13 AM
Hey Fritz,

I was nodding my head in agreement with your post, until I remembered the provider pattern in ASP.NET 2.0.

The provider pattern allows you to override how the innards of the system work, whilst keeping the API the same. I haven't used it in practice, but I'm hoping you'll be able to create more efficient and scalable solutions whilst being able to take advantage of the "anonymous / authenticated profiles" functionality...

Cheers,

Adam
Fritz Onion wrote re: Whither Profile?
on 09-28-2004 6:24 AM
Yes - I should have mentioned that you can absolutely replace the default Profile provider with your own implementation. However, keep in mind that you must support the same functionality - which means that you still need to support arbitrary name/object pairs that must be persisted on demand. My issue is with the chatty, opaque database interaction this model mandates, not the fact that it is not pluggable.
-Fritz
David Hayden wrote re: Whither Profile?
on 09-28-2004 6:50 AM
After reading your post I began thumbing through one of the ASP.NET v2.0 books I purchased awhile back.

The authors considered the architecture of only fetching properties upon request as a positive performance impact. The profile only grabs what it needs each time as opposed to data it may not need.

However, as you pointed out, that is a very one-sided look. Realistically, you will probably need several properties at a time and thus cause several roundtrips to the database if using the default functionality.

Excellent point.
Anonymous wrote Re: Whither Profile?
on 09-28-2004 8:59 AM
Since its provider driven, and if you implement your own (doing the SettingsProvider work), wouldn't that give you a shot at caching such stuff anyway? Of course, It means you endup with some amount of intelligent behavior built into these providers and at that point it starts looking like a regular old DAL.

But, I think it is probably useful when you are building web based themes as a product for other applications without the knowledge a lot of internals. Right?
Girish wrote re: Whither Profile?
on 09-28-2004 9:00 AM
The last comment was made by me. SauceReader lost some of my information. :(
Fritz Onion wrote re: Whither Profile?
on 09-28-2004 10:06 AM
Response to Girish: yes, there are certainly opportunities for caching, and as I mentioned you can make things less granular and more round-trip friendly by using classes to represent profile data, but as you rightly point out it then begins to look like a regular old DAL wedged into an interface it was not designed for.
My main point in this post was that developers need to be aware of the implicit choices they are making as they elect to use features. Many features in this next release are designed to entice new developers to the platform (php, classic ASP, etc.) and while convenient for small-scale sites may not be ideal for enterprise-scale applications.
-Fritz
Girish wrote re: Whither Profile?
on 09-28-2004 10:13 AM
<me Nodding vigorously/> I agree with you 100%. I think if one were to implement a personization feature that needs something similar for a enterprise-scale app, they have to do that implementing their own, instead of using the <profile/>.
GuyIncognito wrote re: Whither Profile?
on 09-28-2004 10:15 AM
Just to verify what you're saying...

Profile.firstname = firstNameTextBox.Text ;
Profile.lastname = lastNameTextBox.Text ;
Profile.age = int.Parse(ageTextBox.Text);

...would equal three database writes?

I'm curious what a serialized Person object looks like? The primitive serialization technique they are using doesn't appear to support object serialization.

Also what does the 'S' in 'firstname:S:0:3:lastname:S:3:5:age:S:8:2:' stand for? My guess would be string, but you clearly defined age as string value. I understand the start and length positions for each serialized value, but the character prefix doesn't make any sense.
GuyIncognito wrote re: Whither Profile?
on 09-28-2004 10:23 AM
btw, I loved your first book on ASP.NET it was very helpful.

One of the things about ASP.NET 2.0 that is sort of turning me off is the *DataSource controls used for databinding at design time. I'm definitely not a huge fan of SQL statements embedded in ASP.NET pages. For the most part, I believe the ASPX pages should have the user interface markup (view) and the code-behind/beside files should have the controller code that hooks up the model (your [my?] data) with the view. Embedding a SQL statement in the presentation layer isn't a very tiered approach in my opinion. I had no problem calling DataBind() in the past, and I guess I will still continue to do so in ASP.NET. The ObjectDataSource looks interesting, but I haven't had much time to examine it.

What is your opinion on the declarative datasource binding of ASP.NET?
Fritz Onion wrote re: Whither Profile?
on 09-28-2004 10:45 AM
Response to Guy:
Yes - those three property accesses will be three database updates.

I just tried a serialized Person class, and it looks like they user the XmlSerializer:

<Person xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<FirstName>Joe</FirstName>
<LastName>Smith</LastName>
<Age>22</Age>
</Person>

...and you're right, it doesn't seem that they are using the type tag for anything but strings (the same thing happened for the class). It could be the serialization is in flux during the beta - we'll have to see.

Glad you liked the book - and I will have a post on the declarative data sources in the future, I promise :)
-Fritz
David Hayden - Sarasota Web Design Development - F wrote ASP.NET 2.0 Profile Feature - Persisting Personal Data in ASP.NET Web Applications
on 09-28-2004 11:37 AM
Brendon Schwartz wrote re: Whither Profile?
on 09-30-2004 5:24 AM
I agree with what you are saying. With ASP.NET 2.0 you can write an entire website with 3 lines of code in 20 minutes, but if you want a real site that solves real problems you will still need to have an architect on the team that knows what they are doing and can make the right decisions. With black box programming there is always a greater chance for having a bad underlying architecture because the general programmer does not read IL and does not look into what classes are used on a component they just use the component.
Sergio Pereira wrote re: Whither Profile?
on 10-01-2004 12:29 PM
It would be great if we could tell the runtime (via page properties, custom attributes, or whatever) what are the properties this page will eventually need so that whenever the first property is attempted, then all the other ones are also retrieved. If one of the properties is very expensive to retrieve but might not be used always, then it would be retrieved as needed.
For the write operatoions, the profile object could store the changes in memory until the page terminates (Unload event?) and then commit all the changes at once to the database (similar to what we can do with the DataSet object).
OK, time to stop designing other people's work :)
christophe fouquet wrote re: Whither Profile?
on 10-02-2004 10:07 AM
I am sometimes amazed at the quick and dirty approach that people take. Any sane developper would not code this way. Maybe there are some Marketing folks at M$ that specify something like this: "I want to make amazon.com in 5 minutes". This type of shortcut is really nice if you want to demo something or provide a working subsystem quickly for other developers. This is fine as long as you have the intention to make a true object/DAL to replace the 'nasty' one.

It is not the first time we see this kind of approach. The <credentials> element in the web.config is another example of a nice/quick/impractical approach.

I am wondering if this paves the path to bad programming. Showing this kind of approach to programmers is dangerous (I won't say criminal).

Only the wise guys like Fritz can tell the difference!

CF

Girish Bharadwaj wrote Client Settings in Whidbey
on 10-04-2004 6:08 PM
StefanG wrote re: Whither Profile?
on 10-04-2004 11:59 PM
Are you really sure that each read and write to a profile property causes a database read/write ?

From what I have been reading about ASP 2.0 Profile, it seems that they will fetch all the profile information (for a specific provider) the first time you access any profile on a specific page, and they will write all the information back at the end of the page, but only if you have actually modified anything.

See http://www.asp.net/whidbey/downloads/WSV321_rhoward_slides.zip

and

http://msdn.microsoft.com/msdnmag/issues/04/03/CuttingEdge/

for example.

If my understanding of how it works is correct, I think that the profile functionality of ASP 2.0 is really useful. It would be quite hard to do implement anything substantially better yourself.

Fritz Onion wrote re: Whither Profile?
on 10-05-2004 3:58 AM
Ah - that's much better. You're absolutely right, Stefan, it makes at most 2 round trips per page access and flushes only those fields that were changed. I'll post a follow-up post making sure this is clear and pointing out how nice a replacement for Session this is.
Onion Blog wrote Thither Profile!
on 10-05-2004 4:10 AM
Gunady wrote re: Whither Profile?
on 10-10-2004 5:53 AM
Yeah I think it's great to replace the use of Session, or better way to mantain state for each user. So far, i have developed web application, i use some classes specifically to manage user information. But it's not uniform, when i go to other project, i see there's different way to manage session. I can't judge it's better or not.
Vincent wrote re: Whither Profile?
on 10-10-2004 5:54 AM
Yeah I think it's great to replace the use of Session, or better way to mantain state for each user. So far, i have developed web application, i use some classes specifically to manage user information. But it's not uniform, when i go to other project, i see there's different way to manage session. I can't judge it's better or not.
virgild wrote re: Whither Profile?
on 11-02-2004 7:48 AM
It seems like I couldn't use the Profile to store important user information. The reason is when you remove a Profile property from the web.config file or your HttpProfileBase inherited class (accidentally or not), the implementation removes that particular proprerty data from the blob when the profile is accessed.
Michael Earls wrote re: Whither Profile?
on 07-08-2005 9:03 AM
I must say that the Profile fills in a nice gray area in Enterprise development for semi-volatile data that doesn't necessarily belong in a first-class relational store. When a user is removed from the Membership system, their profile is deleted. There are also convenience methods on it that allow you to easily clean up old profiles (that haven't been accessed since a particular date).

Also, there is a property that you can use on the property named "serializeAs", with values "Xml", "Binary", "ProviderSpecific", and "String".

For the classes that I store in Profile, I implement ISerializable and perform some reduction tricks in the Serialization constructor/GetObjectData if space/performance needs to be adjusted.

The Profile is a PERFECT place to store a Custom Type of ShoppingCart. My implementation has a public property of type List<CartItem> that I use to store the actual items. I added a Total and Shipping property that enumerates the Items list and calculates the values.

Anyway, I don't think it's going to be productive to dismiss the Profile as some sort of "marketing trick" to convert people over. I believe it has a specific value and a specific cost. If the cost is too great for your application, then don't use it. However, spreading the word that it's "dangerous" or "useless" is going to cause some unnecessary coding out there as people end up implementing a simimlar scheme (which is scarier to me than the mistakes they could make using the built-in Profile).
Fritz Onion wrote re: Whither Profile?
on 07-14-2005 10:45 PM
I have since come around to a similar opinion to yours, Michael - please read my followup post at http://pluralsight.com/blogs/fritz/archive/2004/10/05/2659.aspx. That's one of the hazards of blog entries being indexed on google I suppose...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?