programming4us
programming4us
WEBSITE

Microsoft ASP.NET 4 : Using the SqlProfileProvider (part 4) - The Profile API, Anonymous Profiles

6/25/2012 6:01:34 PM

10. The Profile API

Although your page automatically gets the profile information for the current user, this doesn't prevent you from retrieving and modifying the profiles of other users. In fact, you have two tools to help you—the ProfileBase class and the ProfileManager class.

The Profile object (provided by the Page.Profile property) includes a useful GetProfile() method that retrieves the profile information for a specific user by user name. Figure 4 shows an example with a Windows-authenticated user.

Figure 4. Retrieving a profile manually

Here's the code that gets the profile:

Protected Sub cmdGet_Click(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles cmdGet.Click

    Dim currentProfile As ProfileCommon
    currentProfile = Profile.GetProfile(txtUserName.Text)
    lbl.Text = "This user lives in " & currentProfile.Address.Country
End Sub

GetProfile() returns a ProfileCommon object. However, you won't find ProfileCommon in the .NET class library. That's because ProfileCommon is a dynamically generated class that ASP.NET creates to hold the profile information for your web application. In this example, the profile defines a property named Address, so that you can retrieve this information using the ProfileCommon.Address property.

Notice that once you have a ProfileCommon object, you can interact with it in the same way you interact with the profile for the current user (after all, it's the same object type). You can even make changes. The only difference is that changes aren't saved automatically. If you want to save a change, you need to call the Save() method of the ProfileCommon object. ProfileCommon also adds the LastActivityDate and LastUpdatedDate properties, which you can use to determine the last time a specific profile was accessed and modified.

If you try to retrieve a profile that doesn't exist, you won't get an error. Instead, you'll simply end up with blank data (for example, empty strings). If you change and save the profile, a new profile record will be created.

You can test for this condition by examining the ProfileCommon.LastUpdatedDate property. If the profile hasn't been created yet, this value will be a zero-date value (in other words, day 1 on month 1 in year 0001). Here's the code you'd use:

Protected Sub cmdGet_Click(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles cmdGet.Click

    Dim currentProfile As ProfileCommon
    currentProfile = Profile.GetProfile(txtUserName.Text)
    If profile.LastUpdatedDate = DateTime.MinValue Then
        lbl.Text = "No user match found."
    Else

lbl.Text = "This user lives in " & currentProfile.Address.Country
    End If
End Sub

If you need to perform other tasks with profiles, you can use the ProfileManager class in the System.Web.Profile namespace, which exposes the useful shared methods described in Table 4. Many of these methods work with a ProfileInfo class, which provides information about a profile. The ProfileInfo includes the user name (UserName), last update and last activity dates (LastUpdatedDate and LastActivityDate), the size of the profile in bytes (Size), and whether the profile is for an anonymous user (IsAnonymous). It doesn't provide the actual profile values.

Table 4. ProfileManager Methods
MethodDescription
DeleteProfile()Deletes the profile for the user you specify.
DeleteProfiles()Deletes multiple profiles at once. You supply a collection of user names.
DeleteInactiveProfiles()Deletes profiles that haven't been used since a time you specify. You also must supply a value from the ProfileAuthenticationOption enumeration to indicate what type of profiles you want to remove (All, Anonymous, or Authenticated).
GetNumberOfProfiles()Returns the number of profile records in the data source. You must supply a value from the ProfileAuthenticationOption enumeration that indicates whether you also want to see authenticated profiles (Authenticated), anonymous profiles (Anonymous), or both (All).
GetNumberOfInactive Profiles()Returns the number of profiles that haven't been used since the time you specify. You must supply a value from the ProfileAuthenticationOption enumeration.
GetAllInactiveProfiles()Retrieves profile information for profiles that haven't been used since the time you specify. You must supply a value from the ProfileAuthenticationOption enumeration. The profiles are returned as ProfileInfo objects.
GetAllProfiles()Retrieves all the profile data from the data source as a collection of ProfileInfo objects. You can choose what type of profiles you want to retrieve (All, Anonymous, or Authenticated). You can also use an overloaded version of this method that uses paging and retrieves only a portion of the full set of records based on the starting index and page size you request.
FindProfilesByUser Name()Retrieves a collection of ProfileInfo objects matching a specific user name. The SqlProfileProvider uses a LIKE clause when it attempts to match user names, which means you can use wildcards such as the % symbol. For example, if you search for the user name user%, you'll return values such as user1, user2, user_guest, and so on. You can use an overloaded version of this method that uses paging.
FindInactiveProfilesByUserName()Retrieves profile information for profiles that haven't been used since the time you specify. You can also filter out certain types of profiles (All, Anonymous, or Authenticated) or look for a specific user name (with wildcard matching). The return value is a collection of ProfileInfo objects.

For example, if you want to remove the profile for the current user, you need only a single line of code:

ProfileManager.DeleteProfile(User.Identity.Name)

And if you want to display the full list of users in a web page (not including anonymous users), just add a GridView with AutoGenerateColumns set to True and use this code:

Protected Sub Page_Load(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles Me.Load

    gridProfiles.DataSource = ProfileManager.GetAllProfiles( _
      ProfileAuthenticationOption.Authenticated)
    gridProfiles.DataBind()
End Sub

Figure 5 shows the result.

Figure 5. Retrieving information about all the profiles in the data source

11. Anonymous Profiles

So far, all the examples have assumed that the user is authenticated before any profile information is accessed or stored. Usually, this is the case. However, sometimes it's useful to create a temporary profile for a new, unknown user. For example, most e-commerce websites allow new users to begin adding items to a shopping cart before registering. If you want to provide this type of behavior and you choose to store shopping cart items in a profile, you'll need some way to uniquely identify anonymous users.

NOTE

It's worth asking whether it makes sense to store a shopping cart in a profile. It's a reasonable, workable design, but many developers find it easier to explicitly control how this type of information is stored in their database using custom ADO.NET code instead of the profile feature.

ASP.NET provides an anonymous identification feature that fills this gap. The basic idea is that the anonymous identification feature automatically generates a random identifier for any anonymous user. This random identifier stores the profile information in the database, even though no user name is available. The user name is tracked on the client side using a cookie (or in the URL, if you've enabled cookieless mode). Once this cookie disappears (for example, if the anonymous user closes and reopens the browser), the anonymous session is lost and a new anonymous session is created.

Anonymous identification has the potential to leave a lot of abandoned profiles, which wastes space in the database. For that reason, anonymous identification is disabled by default. However, you can enable it using the <anonymousIdentification> element in the web.config file, as shown here:

<configuration>
  ...
  <system.web>
    <anonymousIdentification enabled="true" />
    ...
  </system.web>
</configuration>

You also need to flag each profile property that will be retained for anonymous users by adding the allowAnonymous attribute and setting it to true. This allows you to store just some basic information and restrict larger objects to authenticated users.

<properties>
  <add name="Address" type="Address" allowAnonymous="true" />
  ...
</properties>

If you're using a complex type, the allowAnonymous attribute is an all-or-nothing setting. You configure the entire object to support anonymous storage or not support it.

The <anonymousIdentification> element also supports numerous optional attributes that let you set the cookie name and timeout, specify whether the cookie will be issued only over an SSL connection, control whether cookie protection (validation and encryption) is used to prevent tampering and eavesdropping, and configure support for cookieless ID tracking. Here's an example:

<anonymousIdentification enabled="true" cookieName=".ASPXANONYMOUS"
  cookieTimeout="43200" cookiePath="/" cookieRequireSSL="false"
  cookieSlidingExpiration="true" cookieProtection="All"
  cookieless="UseCookies"/>

For more information, refer to the Visual Studio Help.

If you use anonymous identification, it's a good idea to delete old anonymous sessions regularly using the aspnet_Profile_DeleteInactiveProfiles stored procedure, which you can run at scheduled intervals using the SQL Server Agent. You can also delete old profiles using the ProfileManager class, as described in the previous section.


11.1. Migrating Anonymous Profiles

One challenge that occurs with anonymous profiles is what to do with the profile information when a previously anonymous user logs in. For example, in an e-commerce website a user might select several items and then register or log in to complete the transaction. At this point, you need to make sure the shopping cart information is copied from the anonymous user's profile to the appropriate authenticated (user) profile.

Fortunately, ASP.NET provides a solution through the ProfileModule.MigrateAnonymous event. This event fires whenever an anonymous identifier is available (either as a cookie or in the URL if you're using cookieless mode) and the current user is authenticated. To handle the MigrateAnonymous event, you need to add an event handler to the file that handles all application events—the Global.asax file.

The basic technique when handling the MigrateAnonymous event is to load the profile for the anonymous user by calling Profile.GetProfile() and passing in the anonymous ID, which is provided to your event handler through the ProfileMigrateEventArgs.

Once you've loaded this data, you can then transfer the settings to the new profile manually. You can choose to transfer as few or as many settings as you want, and you can perform any other processing that's required. Finally, your code should remove the anonymous profile data from the database and clear the anonymous identifier so the MigrateAnonymous event won't fire again. For example:

Public Sub Profile_OnMigrateAnonymous(sender As Object, _
 e As ProfileMigrateEventArgs)

    ' Get the anonymous profile.
    Dim anonProfile As ProfileCommon = Profile.GetProfile(e.AnonymousID)

    ' Copy information to the authenticated profile
    ' (but only if there's information there).
    If Not anonProfile.IsNullOfEmpty() Then
        If anonProfile.Address.Name <> "" Then
            Profile.Address = anonProfile.Address
        End If
    End If

    ' Delete the anonymous profile from the database.
    ' (You could decide to skip this step to increase performance
    '  if you have a dedicated job scheduled on the database server
    '  to remove old anonymous profiles.)
    System.Web.Profile.ProfileManager.DeleteProfile(e.AnonymousID)

    ' Remove the anonymous identifier.
    AnonymousIdentificationModule.ClearAnonymousIdentifier()
End Sub

You need to handle this task with some caution. If you've enabled anonymous identification, the MigrateAnonymous event fires every time a user logs in, even if the user hasn't entered any information into the anonymous profile. That's a problem—if you're not careful, you could easily overwrite the real (saved) profile for the user with the blank anonymous profile. The problem is further complicated by the fact that complex types (such as the Address object) are created automatically by ASP.NET, so you can't just check for a null reference to determine whether the user has anonymous address information.

In the previous example, the code tests for a missing Name property in the Address object. If this information isn't part of the anonymous profile, no information is migrated. A more sophisticated example might test for individual properties separately or might migrate an anonymous profile only if the information in the user profile is missing or outdated.

Other  
 
Video
PS4 game trailer XBox One game trailer
WiiU game trailer 3ds game trailer
Top 10 Video Game
-   Minecraft Mods - MAD PACK #10 'NETHER DOOM!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #9 'KING SLIME!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #2 'LAVA LOBBERS!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #3 'OBSIDIAN LONGSWORD!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Total War: Warhammer [PC] Demigryph Trailer
-   Minecraft | MINIONS MOVIE MOD! (Despicable Me, Minions Movie)
-   Minecraft | Crazy Craft 3.0 - Ep 3! "TITANS ATTACK"
-   Minecraft | Crazy Craft 3.0 - Ep 2! "THIEVING FROM THE CRAZIES"
-   Minecraft | MORPH HIDE AND SEEK - Minions Despicable Me Mod
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 92 "IS JOE DEAD?!"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 93 "JEDI STRIKE BACK"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 94 "TATOOINE PLANET DESTRUCTION"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 95 "TATOOINE CAPTIVES"
-   Hitman [PS4/XOne/PC] Alpha Gameplay Trailer
-   Satellite Reign [PC] Release Date Trailer
Game of War | Kate Upton Commercial
programming4us
 
 
programming4us