4. Grouping Profile Data and Persisting Custom Objects
Allow me to make a few additional comments on how profile data may be defined within a Web.config
file.The current profile simply defined four pieces of data which were directly exposed of the type of profile. When you establish more complex profiles, it can be useful to group the relative pieces of data under a single name. Consider the following update:
<profile>
<properties>
<group name ="Address">
<add name="StreetAddress" type="String" />
<add name="City" type="String" />
<add name="State" type="String" />
</group>
<add name="TotalPost" type="Integer" />
</properties>
</profile>
This time we have defined a custom group named Address
to expose the street address, city, and state of our user. To access
this data in our pages would now require us to update our code baseby
specifying Profile.Address to get each subitem. For example, here is the updated GetUserAddress() method (the Click event handler for the Button would need to be updated ina similar manner):
private void GetUserAddress()
{
// Database reads happening here!
lblUserData.Text = String.Format("You live here: {0}, {1}, {2}",
Profile.Address.StreetAddress,
Profile.Address.City, Profile.Address.State);
}
Before you run this example, you need to delete ASPNETDB.mdf
from your App_Data folder, to ensure the database schema is refreshed.
Once you have done so, you should be able to run your web site example
without error.
NOTE
A profile can contain as many groups as you feel are necessary. Simply define multiple <group> elements within your <properties> scope.
Finally, it is worth pointing out that a profile may also persist (and obtain) custom objects to and from ASPNETDB.mdf.
To illustrate, assume you wanted to build a custom class (or structure)
that will represent the user's address data. The only requirement
expected by the Profile API is that the type be marked with the [Serializable] attribute, for example:
[Serializable]
public class UserAddress
{
public string Street = string.Empty;
public string City = string.Empty;
public string State = string.Empty;
}
With this class in place, our profile definition can
now be updated as follows (notice I removed the custom group, although
this is not mandatory):
<profile>
<properties>
<add name="AddressInfo" type="UserAddress" serializeAs ="Binary"/>
<add name="TotalPost" type="Integer" />
</properties>
</profile>
Note that when you are adding [Serializable] types to a profile, the type
attribute is the fully qualified named of the type being persisted. As
you will see from the Visual Studio 2010 IntelliSense, your core
choices are binary, XML, or string data. Now that we are capturing
street address information as a custom class type, we (once again) need
to update our code base:
private void GetUserAddress()
{
// Database reads happening here!
lblUserData.Text = String.Format("You live here: {0}, {1}, {2}",
Profile.AddressInfo.Street, Profile.AddressInfo.City,
Profile.AddressInfo.State);
}
To be sure, there is much more to the Profile API than I've had space to cover here. For example, the Profile property actually encapsulates a type named ProfileCommon. Using this type, you are able to programmatically obtain all information for a given user, delete (or add) profiles to ASPNETDB.mdf, update aspects of a profile, and so forth.
Moreover, the Profile API has numerous
points of extensibility that can allow you to optimize how the profile
manager accesses the tables of the ASPNETDB.mdf database. As
you would expect, there are many ways to decrease the number of "hits"
this database takes. Interested readers are encouraged to consult the
.NET Framework 4.0 SDK documentation for further details.