Programming Microsoft ASP.NET 4 - Dino Esposito [158]
// Display current settings through the edit panel as well.
chkEuroMetric.Checked = profile.UseEuroMetricSystem;
rdlTempSystem.SelectedIndex = (profile.TempSystem == "F" ? 0 : 1);
}
The output of the page can change depending on the settings entered by individual users. Figure 7-7 shows what the same page might look like for distinct users.
Figure 7-7. Different settings for different users.
If anonymous access is permitted, any unauthenticated user is treated as the same one—meaning that all anonymous users share the same settings and any can change in the settings of one user affects all the others. (Most of the time, though, sites where profiles are fundamental just don’t allow anonymous access.)
How do you change settings? Here’s the code you can associate with the Save button you see in Figure 7-7:
protected void Button1_Click(Object sender, EventArgs e)
{
// Retrieve and update the profile for the current user
var profile = YourApp.UserProfile.GetUserProfile();
profile.UseEuroMetricSystem = chkEuroMetric.Checked;
profile.TempSystem = rdlTempSystem.SelectedItem.Value;
// Persist settings for the current user
profile.Save();
// Refresh the page to ensure changes are immediately visible
Response.Redirect("/profile.aspx");
}
The Redirect call is not strictly required; however, if it’s omitted, it won’t give the user an immediate experience based on the changes entered. If you omit the redirect, the changes (which are stored in the repository, anyway) will be visible only upon the next request.
Personalization Events
As mentioned, the personalization data is added to the HTTP context of a request before the request begins its processing route. But which system component is in charge of loading personalization data? ASP.NET employs an HTTP module for this purpose named ProfileModule.
The module attaches itself to a couple of HTTP events and gets involved after a request has been authorized and when the request is about to end. If the personalization feature is off, the module returns immediately. Otherwise, it fires the Personalize event to the application and then loads personalization data from the current user profile. When the Personalize event fires, the personalization data hasn’t been loaded yet. Handlers for events fired by an HTTP module must be written to the global.asax file.
void Profile_Personalize(object sender, ProfileEventArgs e)
{
ProfileCommon profile = null;
// Exit if it is the anonymous user
if (User == null) return;
// Determine the profile based on the role. The profile database
// contains a specific entry for a given role.
if (User.IsInRole("Administrators"))
profile = (ProfileCommon) ProfileBase.Create("Administrator");
else if (User.IsInRole("Users"))
profile = (ProfileCommon) ProfileBase.Create("User");
else if (User.IsInRole("Guests"))
profile = (ProfileCommon) ProfileBase.Create("Guest");
// Make the HTTP profile module use THIS profile object
if (profile != null)
e.Profile = profile;
}
}
The personalization layer is not necessarily there for the end user’s amusement. You should look at it as a general-purpose tool to carry user-specific information. User-specific information, though, indicates information that applies to the user, not necessarily information entered by the user.
The personalization layer employs the identity of the current user as an index to retrieve the proper set of data, but what about roles? What if you have hundreds of users with different names but who share the same set of profile data (such as menu items, links, and UI settings)? Maintaining hundreds of nearly identical database entries is out of the question. But the standard profile engine doesn’t know how to handle roles. That’s why you sometimes need to handle the Personalize event or perhaps roll your own profile provider.
The code shown previously overrides the process that creates the user profile object and ensures that the returned object is filled with user-specific information accessed