Recipe 10.4. Using and Migrating Anonymous Profiles


Problem

You want to store profile information for users who are not logged into your application.

Solution

Implement the solution described in Recipe 10.1, add an <anonymousIdentification> element to the web.config file to enable anonymous identification, and set the allow-Anonymous attributes of the profile property elements to true in web.config for each of the profile properties that should be stored for anonymous users.

Modify web.config as follows:

  1. Add an <anonymousIdentification> element to enable the anonymous identification features and to define the cookie used to identify the user.

  2. Set the allowAnonymous attribute of each profile property that is to be persisted for anonymous users to true.

Example 10-8 shows the modifications made to web.config for this solution. The example page that uses the user profile information is identical to the example in Recipe 10.1 and is shown in Examples 10-2, 10-3 through 10-4.

Discussion

Storing anonymous user profile data was possible in ASP.NET 1.x, but, since there was no inherent support in 1.x, you had to implement it yourself. As part of the profile features, ASP.NET 2.0 provides full support for storing data for anonymous users. Like storing profile data for authenticated users, it can be configured with little code.

When anonymous identification is enabled, ASP.NET 2.0 generates a GUID to use as the identity for all visitors to your application on their first visit. This GUID is stored in a cookie that is persisted on the user's computer. For all subsequent page requests and visits to your application, the cookie is retrieved and the GUID is used to access his or her profile information. Other than relying on a cookie to identify the user (instead of logging into your application), the mechanism for managing the user profile data is the same whether the user is anonymous or authenticated.

ASP.NET supports using the URL for the anonymous identification data; however, unless the user bookmarks the URL with the encoded data, the user cannot be identified on subsequent visits to your application.


Since cookies are not shared between browsers, users who use multiple browsers may have unexpected results when accessing an application with one browser and then another. If your application uses anonymous profiles and a user first accesses it with Internet Explorer, for example, and then accesses with Firefox, two separate profiles will be created and stored for the user. If the user changes the profile information using one browser, those changes will not be reflected when using the other browser.


To enable anonymous identification, you need to add an <anonymousIdentification> element to web.config. Multiple attributes are provided to configure anonymous identification, as shown in Table 10-3.

Table 10-3. anonymousIdentification element attributes

Attribute

Description

enabled

Specifies if the HttpAnonymousIdentificationModule is enabled. Valid values are true and false. The default value is false.

cookieName

Defines the name of the cookie used to store the anonymous ID of the user. The default value is .ASPXANONYMOUS.

cookiePath

Defines the path to the directory where the cookie is stored. Most browsers treat the path as case-sensitive and will not return the cookie for a request that does not match the value provided for the path attribute. Unless your application requires specifying the path, leave the path as "/".

cookieRequireSSL

Defines whether an SSL connection is required to transmit the cookie to the client. Valid values are true and false. The default value is false.

cookieTimeout

Specifies the cookie expiration time in minutes.

cookieSlidingExpiration

Defines if sliding expiration of the cookie is enabled. If set to TRue, the cookie time to expire will be refreshed on every page request. If set to false, the cookie will expire at the time set when the cookie was created. The default value is TRue.

cookieProtection

Defines the protection method used for the cookie. Possible values are All, None, Encryption, and Validation. Validation specifies that the cookie data will be validated to ensure it was not altered in transit. Encryption specifies that the cookie is encrypted. All specifies that data validation and encryption will be used. None specifies that no protection will be provided for the cookie information. The default is All and is recommended because it offers the highest level of protection for the cookie.


In some applications, supporting conversion of an anonymous user to an authenticated user is necessary. For example, when a user fills his shopping cart and then logs in to make a purchase, you want to transfer the data from the shopping cart in the anonymous profile to the one in the authenticated profile.

ASP.NET 2.0 provides the ability for you to perform the conversion by firing an event when an anonymous user logs into your application. The event is the OnMigrateAnonymous and must be handled in Global.asax, as shown in Example 10-9 (VB) and Example 10-10 (C#).

The first step to migrate an anonymous profile to an authenticated user profile is to get the user's anonymous profile data. You can do this by calling the GetProfile method of the Profile class passing the ID of the anonymous user. The anonymous user ID is passed to the Profile_OnMigrateAnonymous method in the args parameter.

 

anonymousProfile = Profile.GetProfile(args.AnonymousID)

anonymousProfile = Profile.GetProfile(args.AnonymousID);

Next, you need to verify that the authenticated user profile does not exist. Since the profile for a user, whether anonymous or authenticated, will never be null (Nothing in VB), you can check the LastActivityDate property to determine if it has a valid date. If the date is equal to the minimum date value, the authenticated profile does not exist. Any other value indicates an authenticated profile exists.

 

If (Profile.LastActivityDate = DateTime.MinValue) Then … End If

if (Profile.LastActivityDate == DateTime.MinValue) { … }

If you do not check the authenticated user profile in the OnMigrateAnonymous event handler before migrating the anonymous user profile, the authenticated user profile will be overwritten every time the user logs in, since the OnMigrateAnonymous event is fired every time the user logs in to your application.


After determining that the authenticated profile does not exist, you need to copy the desired data from the anonymous profile to the authenticated profile and save the profile.

 

If (Profile.LastActivityDate = DateTime.MinValue) Then 'logged in user's profile does not exist so copy the anonymous 'profile data to the logged in user's profile Profile.FirstName = anonymousProfile.FirstName Profile.LastName = anonymousProfile.LastName Profile.MailingAddress.Address1 = anonymousProfile.MailingAddress.Address1 Profile.MailingAddress.Address2 = anonymousProfile.MailingAddress.Address2 Profile.MailingAddress.City = anonymousProfile.MailingAddress.City Profile.MailingAddress.State = anonymousProfile.MailingAddress.State Profile.MailingAddress.ZipCode = anonymousProfile.MailingAddress.ZipCode Profile.EmailAddresses = anonymousProfile.EmailAddresses 'save the logged in user's profile Profile.Save() End If

if (Profile.LastActivityDate == DateTime.MinValue) { // logged in user's profile does not exist so copy the anonymous // profile data to the logged in user's profile Profile.FirstName = anonymousProfile.FirstName; Profile.LastName = anonymousProfile.LastName; Profile.MailingAddress.Address1 = anonymousProfile.MailingAddress.Address1; Profile.MailingAddress.Address2 = anonymousProfile.MailingAddress.Address2; Profile.MailingAddress.City = anonymousProfile.MailingAddress.City; Profile.MailingAddress.State = anonymousProfile.MailingAddress.State; Profile.MailingAddress.ZipCode = anonymousProfile.MailingAddress.ZipCode; Profile.EmailAddresses = anonymousProfile.EmailAddresses; // save the logged in user's profile Profile.Save(); }

Next, you should delete the anonymous profile to help in managing unneeded profiles. This is important since profile data is permanent and is never automatically purged (see Recipe 10.4 for an example of managing profiles).

The final step is to delete the cookie used to identify the anonymous user since it is unneeded.

If you do not delete the anonymous cookie, the OnMigrateAnonymous event will fire on every page access. This is caused by the way ASP.NET determines if the event should be fired. If the user is authenticated and the anonymous cookie exists, ASP.NET will assume this is the initial login and fire the event. If the cookie is never deleted, the event will fire every time a page is requested.


The infrastructure provided by ASP.NET 2.0 for profiles will meet the needs of most applications with little or no coding required. This can be a significant savings in developing your application.

See Also

Recipes 10.1 and 10.4

Example 10-8. Modifications to web.config to support profiles for anonymous users

 <?xml version="1.0"?> <configuration> <system.web> <!--  The <authentication> section enables configuration  of the security authentication mode used by  ASP.NET to identify an incoming user.   --> <authentication mode="Forms" >   <forms name=".ASPNETCookbookVBPersonalization3" loginUrl="Login.aspx" protection="All" timeout="30" path="/" defaultUrl="UpdateProfile.aspx" /> </authentication> <authorization>   <allow users="*" /> <!-- Allow all users --> </authorization> <membership defaultProvider="AspNetSqlMembershipProvider" userIsOnlineTimeWindow="15">   <providers>     <remove name="AspNetSqlMembershipProvider" /> <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="sqlConnectionString" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/AnonymousVB" requiresUniqueEmail="false" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />   </providers> </membership> <roleManager defaultProvider="AspNetSqlRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".ASPNETCookbookVBPersonalization1Roles" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All" > <providers>   <remove name="AspNetSqlRoleProvider" />   <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="sqlConnectionString" applicationName="/AnonymousVB" /> </providers> </roleManager> <anonymousIdentification enabled="true" cookieName="ASPNETCookbookVBAnonymousID" cookiePath="/" cookieRequireSSL="false" cookieTimeout="525600" cookieSlidingExpiration="true" cookieProtection="All" /> <profile enabled="true" defaultProvider="AspNetSqlProfileProvider" automaticSaveEnabled="false" >   <providers> <remove name="AspNetSqlProfileProvider" /> <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="sqlConnectionString" applicationName="/AnonymousVB" />   </providers>   <properties> <add name="FirstName" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" /> <add name="LastName" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" /> <add name="Theme" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" />   <group name="MailingAddress"> <add name="Address1" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" /> <add name="Address2" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" /> <add name="City" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" /> <add name="State" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" /> <add name="ZipCode" type="System.String" serializeAs="String" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" /> </group> <add name="EmailAddresses" type="System.Collections.Specialized.StringCollection" serializeAs="Xml" allowAnonymous="true" provider="AspNetSqlProfileProvider" defaultValue="" readOnly="false" />   </properties> </profile> </system.web> </configuration> 

Example 10-9. OnMigrateAnonymous event handler in Global.asax (.vb)

 Public Sub Profile_OnMigrateAnonymous(ByVal sender As Object, _   ByVal args As ProfileMigrateEventArgs)   Dim anonymousProfile As ProfileCommon   'get the anonymous user's profile   anonymousProfile = Profile.GetProfile(args.AnonymousID)   'check to see if the logged in user's profile is already active   If (Profile.LastActivityDate = DateTime.MinValue) Then 'logged in user's profile does not exist so copy the anonymous 'profile data to the logged in user's profile Profile.FirstName = anonymousProfile.FirstName Profile.LastName = anonymousProfile.LastName Profile.MailingAddress.Address1 = anonymousProfile.MailingAddress.Address1 Profile.MailingAddress.Address2 = anonymousProfile.MailingAddress.Address2 Profile.MailingAddress.City = anonymousProfile.MailingAddress.City Profile.MailingAddress.State = anonymousProfile.MailingAddress.State Profile.MailingAddress.ZipCode = anonymousProfile.MailingAddress.ZipCode Profile.EmailAddresses = anonymousProfile.EmailAddresses 'save the logged in user's profile Profile.Save() End If 'delete the anonymous user data from the database ProfileManager.DeleteProfile(anonymousProfile.UserName) 'delete the anonymous cookie so this event will no longer 'fire for a logged-in user AnonymousIdentificationModule.ClearAnonymousIdentifier() End Sub 'Profile_OnMigrateAnonymous 

Example 10-10. OnMigrateAnonymous event handler in Global.asax (C#)

 public void Profile_OnMigrateAnonymous(Object sender,    ProfileMigrateEventArgs args) { ProfileCommon anonymousProfile; // get the anonymous user's profile anonymousProfile = Profile.GetProfile(args.AnonymousID); // check to see if the logged in user's profile is already active if (Profile.LastActivityDate == DateTime.MinValue) { // logged in user's profile does not exist so copy the anonymous // profile data to the logged in user's profile Profile.FirstName = anonymousProfile.FirstName; Profile.LastName = anonymousProfile.LastName; Profile.MailingAddress.Address1 = anonymousProfile.MailingAddress.Address1; Profile.MailingAddress.Address2 = anonymousProfile.MailingAddress.Address2; Profile.MailingAddress.City = anonymousProfile.MailingAddress.City; Profile.MailingAddress.State = anonymousProfile.MailingAddress.State; Profile.MailingAddress.ZipCode = anonymousProfile.MailingAddress.ZipCode; Profile.EmailAddresses = anonymousProfile.EmailAddresses; // save the logged in user's profile Profile.Save(); } // delete the anonymous user data from the database ProfileManager.DeleteProfile(anonymousProfile.UserName); // delete the anonymous cookie so this event will no longer // fire for a logged-in user AnonymousIdentificationModule.ClearAnonymousIdentifier(); } // Profile_OnMigrateAnonymous 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2003
Pages: 202

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net