Last week I needed to add some personalization features to our ActiveFocus application, and it seemed like the built in logic around the Profile class in ASP.Net 2.0 Personalization would do the trick. It's actually pretty neat. First, you "declare" your profile data in web.config, something like this:
<profile enabled="true">
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ActiveFocus" applicationName="/ActiveFocus"/>
</providers>
<properties>
<group name="Grids">
<add name="MainGridRows" type="System.Int16" />
<add name="DetailGridRows" type="System.Int16" />
</group>
<add name="LastProject" type="System.Int32" />
</properties>
</profile>
The Properties portion defines the profile data structure. You can use simple data types like System.Int16, nested types (like the Grids property), and your own data types. You can also declare how these types are to be serialized.
When you add a declaration like this to your project, Visual Studio 2005 generates a class for you that implements this data structure (more on how this actually needs a little help for it to work later!). The class basically wraps the HttpContext.Current.Profile object, which is of type ProfileBase. It adds accessors for the members you declared in the web.config file, and sub objects for nested types.
In runtime, the ProfileBase reads and writes it values to a column in the table aspnet_Profile. Here is what it looks like when an instance of the profile class above is written to that table:
UserId PropertyNames PropertyValuesString
7B07AE10-61A7-4DEE-AFF1-172BB42A5E95 Grids.DetailGridRows:S:0:1:Grids.MainGridRows:S:1:2:LastProject:S:3:1: 8202
The profile is tied to user using the UserID column, and the PropertyNames column determines what offset and length in PropertyValuesString each data item occupies. For instance, MainGridRows starts at offset 1 and is 2 characters (so the value is 20). You can use attributes in web.config to control how the properties are serialized.
In code, to access the profile, you just need to declare a property in your form that casts the Profile object of the current Page (or HttpContext.Current.Profile) to a WebProfile (this is the type name of the auto generated ProfileBase wrapper) :
protected WebProfile Profile
{
get
{
return (WebProfile) this.Profile;
}
}
Now you can read and write the Profile using this property:
tbRowsPerMainGrid.Text = Profile.Grids.MainGridRows.ToString();
tbRowsPerDetailGrid.Text = Profile.Grids.DetailGridRows.ToString();
Here is how you can save it back:
Profile.Grids.MainGridRows = Int16.Parse( tbRowsPerMainGrid.Text );
Profile.Grids.DetailGridRows = Int16.Parse( tbRowsPerDetailGrid.Text );
Profile.Save();
Pretty cool, huh?
Profile data can be stored for authenticated users, but it can also be stored for anonymous users and "upgraded" to an authenticated user if the anonymous user becomes an authenticated user.
So what is the catch with all this magic?
Well, it turns out that this handy dandy auto generating of wrapper classes is only done for Web Site Projects, not Web Application Projects (WAPs)! This is true even of the latest Visual Studio 2005 SP1. I tried doing this in the ActiveFocus WAP, and the compile failed miserably, there was no WebProfile class to be found. I figured this would be easy to Google, and indeed it was, and it turns out that there is a Visual Studio add in on gotdotnet that adds this capability to WAPs, but to my dismay I saw that the gotdotnet site is "being phased out", and the download is gone!
So I turned to my old colleague and friend Charlie Calvert at Microsoft, and he did some digging. He found this post at andornot.com, which references the original post by Scott Guthrie on scottgu.com, and helpfully provides the vanished download!
I downloaded the software and installed it, and now when I right clicked on the web.config node in the Solution Explorer, there was a menu option saying Generate WebProfile:

And what's more, it actually worked! ActiveFocus is now equipped with a user profile capability! Thanks for the help, all of you guys with helpful blogs above! Hopefully this blog will help you too.