A Simple Example of Using a Shopping Cart


This example shows how you can use the profiles feature of ASP.NET to maintain information for users between visits to your site. It stores the same profile information you saw in previous sections of this chapter, but allows new users to input the information on their first visit and modify it during subsequent visits. The example also allows users to add items to their shopping cart, empty the cart, and view the current cart contents. Finally, it shows how you can migrate a shopping cart created by an anonymous visitor to a logged-in user's profile.

This last point is important. Visitors to online stores generally dislike having to log in or create a new account just to be able to browse the products available. Most online stores avoid this by allowing anonymous visitors to browse, add items to their shopping cart, and then log in only when they want to place an order. Therefore, being able to migrate an existing shopping cart from anonymous to logged-in users is a requirement in most situations.

The example shown here is a new section added to the example you saw in the previous chapter that allows users to register, create a new account, and then log in using this new account. An extra link on the Home page takes them to the Shopping Cart page, shown in Figure 12.2.

Figure 12.2. The shopping cart page as seen by a new visitor


Figure 12.2 shows the page as it appears to a new anonymous visitor. You can see their User name (UserID property), as well as the read-only Site name that is also exposed to anonymous visitors. The LastUpdatedDate property of the Profile class shows the date and time that the profile was last updatedthis value is maintained and exposed by the profile system.

Below this is a drop-down list where visitors can choose the text size they prefer. This is another anonymous property, saved in the profile when the visitor clicks the Update button. It is used to select the appropriate stylesheet each time the page loads. Finally, below this, are details of this visitor's shopping cart. Because this is their first visit, and they have not added anything to the cart, it is empty and there is no UserID property set for it.

The code in the Page_Load event handler calls a routine that displays the profile property values the first time that the page loads. Listing 12.11 shows the Page_Load event handler and the first section of the ShowProfileValues routine that it calls. Other than formatting the strongly typed values returned from the profile, the code works in the same way as you saw when reading profile information in the previous sections of this chapter.

Listing 12.11. Showing the Profile Properties When the Page Loads

protected void Page_Load(Object sender, EventArgs e) {   if (! Page.IsPostBack)   {     ShowProfileValues();   } } protected void ShowProfileValues() {   // display user name stored in profile and authentication status   lblUserName.Text = Profile.UserName + "(authenticated = "                 + User.Identity.IsAuthenticated.ToString() + ")";   // display read-only property value and last updated date   lblSiteName.Text = Profile.SiteName;   lblLastUpdated.Text = Profile.LastUpdatedDate.ToString(                                      "ddd d MM yyyy \\a\\t hh:mm:ss");   ...

Setting the Text Size

The page contains a <link> element that loads the default stylesheet for the site:

<link  runat="server" type="text/css"       rel="stylesheet" href="StyleSheet.css" />


Notice that this element contains the runat="server" attribute and an ID value, so server-side ASP.NET code can access it at runtime. The declaration of the profile property in web.config indicates that it is available to anonymous visitors, and that it has a default value of "small":

<add name="TextSize" type="String" allowAnonymous="true"            defaultValue="small" />


In the ShowProfileValues routine, code can extract the value of this property for the current user, set the drop-down list to this value, and create a suitable stylesheet name to insert into the <link> element as the href attribute. This forces the browser to use the corresponding stylesheet, which sets the selected text size for the page:

lstTextSize.SelectedValue = Profile.TextSize; lnkStylesheet.Href = "Style-" + Profile.TextSize + ".css";


You can see the effect of selecting a large text size in Figure 12.3. This approach can be used to change almost any aspect of the page style or appearance, and will persist between visits by this user.

Figure 12.3. Changing the text size using an anonymous profile property


Displaying the Shopping Cart and Adding Items

The ShowProfileValues routine calls another routine named ShowShoppingCart (see Listing 12.12), which accesses the Cart profile property and displays the UserID and TotalValue property values in Label controls on the page. Then, as in earlier examples, it binds the DataTable returned from the CartItems property to a GridView control on the page.

Listing 12.12. Displaying Details of the Shopping Cart for This Visitor

protected void ShowShoppingCart() {   if (Profile.Cart != null)   {     lblCartUserID.Text = Profile.Cart.UserID;     lblCartValue.Text = Profile.Cart.TotalValue.ToString("F2");     gridCartItems.DataSource = Profile.Cart.CartItems;     gridCartItems.DataBind();   } }

The page has a drop-down list containing the items available to add to the cart, an Add button to add the selected item, and a Clear button to empty the cart (see Figure 12.4).

Figure 12.4. Adding items anonymously to the shopping cart


Listing 12.13 shows the code that runs when you click the Add or Clear button. The AddToShoppingCart routine takes the name and value of the item selected in the drop-down list and passes it to the AddItem method of the ShoppingCart instance stored in the visitor's Cart profile property. Notice that the code must convert the value to the correct data type (a Double) first.

The code to clear the shopping cart simply calls the Clear method of the ShoppingCart instance stored in the visitor's Cart profile property. In both routines, a call to the ShowShoppingCart routine updates the page so that it displays the current state of the cart.

Listing 12.13. The Routines to Add Items To and Clear (Empty) the Shopping Cart

protected void AddToShoppingCart(Object sender, EventArgs e) {   Profile.Cart.UserID = Profile.UserName;   Profile.Cart.AddItem(lstAddToCart.SelectedItem.Text, 1,                 Double.Parse(lstAddToCart.SelectedItem.Value));   ShowShoppingCart(); } protected void EmptyShoppingCart(Object sender, EventArgs e) {   Profile.Cart.Clear();   ShowShoppingCart(); }

Displaying Details of Logged In Users

All the profile data used so far is available to anonymous visitors, and the screenshots show it accessed by a visitor who has not yet logged in. This is obvious from the long user ID string, which is a unique auto-generated ID stored in their anonymous profile cookie. You can see this in Figure 12.5, together with the value of the User.Identity.IsAuthenticated property appended to the end of the ID. This part of the code you saw in Listing 12.11 generates this value:

lblUserName.Text = Profile.UserName + "(authenticated = "           + User.Identity.IsAuthenticated.ToString() + ")";


Figure 12.5. The Login link and User name for a visitor not yet logged in


However, the page also contains a LoginStatus and a LoginView control, just as in the Home page you saw in the previous chapter. When there is no logged-in user, the LoginStatus control displays the text "Login" and the LoginView control displays an empty string. You can see this in Figure 12.5.

Once a visitor logs in and returns to this page, by following the Login link shown in Figure 12.5 or by going to the Home page and following the Login link there, the Shopping Cart page can access the profile properties that are not available to anonymous visitors. The Shopping Cart page contains an HTML table that has the runat="server" attribute and contains the controls to display and allow updates to the stored profile information. Therefore, as part of the ShowProfileValues routine you saw in Listing 12.11, the code first determines if the visitor is authenticated, andif sodisplays the values from the profile properties in Label controls on the page and makes the table visible. If the visitor is not authenticated, it hides the table. Listing 12.14 shows this section of code.

Listing 12.14. Displaying the Profile Property Values for Authenticated Users

if (User.Identity.IsAuthenticated) {   txtFirstName.Text = Profile.FirstName;   txtLastName.Text = Profile.LastName;   txtAge.Text = Profile.Age.ToString();   txtStreet.Text = Profile.Address.Street;   txtCity.Text = Profile.Address.City;   txtZip.Text = Profile.Address.ZipCode;   txtCountry.Text = Profile.Address.Country;   tblUserDetails.Visible = true; } else {   tblUserDetails.Visible = false; }

You can see the result after logging on in Figure 12.6. Now text boxes display the name and address details of the authenticated user, drawn from the profile property values saved the last time this user visited the site. You can see the value of the Profile.LastUpdatedDate property as well as the user name and an indication that this is an authenticated user. The LoginStatus and a LoginView control at the top of the page now display the text "Logout" and the user name.

Figure 12.6. Displaying details of an authenticated user


Updating the Profile Properties

Both authenticated and anonymous visitors can update their profile information at any time using the Update button at the foot of the page. The code in the page that you saw in Listing 12.13 automatically updates the shopping cart within their profile as they add items to it or empty it. For anonymous visitors, therefore, the only item to update is the TextSize property. However, authenticated users can update their name, age, and address details as well.

Listing 12.15 shows the routine that accomplishes this. It first checks if the user is authenticated, and if so, takes the values from the text boxes and updates the profile properties. Because the properties are strongly typed, an exception will occur for a non-numeric value found in the Age text box, in which case the code displays an error message. Finally, for both authenticated and anonymous visitors, the code updates the TextSize profile property and then calls the routine to display the current profile values in the page.

Listing 12.15. Updating the Stored Profile Property Values

protected void UpdateProfileValues(Object sender, EventArgs e) {   if (User.Identity.IsAuthenticated)   {     Profile.FirstName = txtFirstName.Text;     Profile.LastName = txtLastName.Text;     try     {       Profile.Age = Int32.Parse(txtAge.Text);     }     catch (Exception ex)     {       lblMessage.Text = "<p>Error: Cannot update Age -"                       + ex.Message + "</p>";     }     Profile.Address.Street = txtStreet.Text;     Profile.Address.City = txtCity.Text;     Profile.Address.ZipCode = txtZip.Text;     Profile.Address.Country = txtCountry.Text;   }   Profile.TextSize = lstTextSize.SelectedValue;   ShowProfileValues(); }

Migrating Anonymous Users

The one remaining task in this example is to migrate the values for an anonymous user to an authenticated profile for the user when that user logs on to the site. While this is often a time-consuming process in other Web development environments, ASP.NET makes it easy. The integrated membership, profiles, and personalization system includes methods and events that allow you to interact with the authentication process to perform this kind of operation.

The profile system exposes an event named OnMigrateAnonymous that you can handle within the global.asax file for your site or application. It is raised when a user logs on, after successful authentication, and exposes a ProfileMigrateEventArgs instance that contains the anonymous user ID.

The underlying profiles system automatically exposes the set of profile property values for the current user as a ProfileCommon class instance, which is created as the application starts up based on the properties you declare in the <profile> section of web.config. The set of property values stored in the ProfileCommon instance are those of the current user, anonymous or authenticated. As a user logs on and is successfully authenticated, the ProfileCommon instance switches to expose the values of the logged on user.

However, the Profile class exposes a method called GetProfile that accepts a user ID as a parameter and returns a ProfileCommon instance containing the profile properties for that user. Therefore, you can use the anonymous user ID saved in the ProfileMigrateEventArgs instance to fetch the profile properties that were active for this user before he or she logged on and apply them to this user's current profile.

Listing 12.16 shows the complete global.asax file that the example uses to migrate a user's profile as he or she logs on to the site. The first stage fetches the anonymous profile that the visitor had before logging on using the GetProfile method. Then the code can apply the values to the current profile. However, you must consider how you want this process to behave in your specific application scenarios. For example, here the user's profile may have a saved shopping cart, and so the code only migrates the anonymous shopping cart if it contains some items. If the user has not added anything to the shopping cart before logging in, it does not overwrite the existing shopping cart with the anonymous one.

Listing 12.16. Migrating the Anonymous Profile to the Authenticated Profile

<%@ Application Language="C#" %> <script runat="server">   public void Profile_OnMigrateAnonymous(Object sender,                                          ProfileMigrateEventArgs e)   {     // get profile data from anonymous profile     ProfileCommon anonProfile = Profile.GetProfile(e.AnonymousID);     // apply to authenticated profile - only need to do this     // for the TextSize and Cart properties because these are     // the only anonymous profile properties available     Profile.TextSize = anonProfile.TextSize;     // if nothing in "anonymous" cart, no need to copy     // this means any previous cart will still be available     if (anonProfile.Cart.TotalValue > 0)     {       Profile.Cart = anonProfile.Cart;     }     // because User name is stored in Cart must update this as well     Profile.Cart.UserID = Profile.UserName;     // delete the anonymous profile and remove the cookie     ProfileManager.DeleteProfile(e.AnonymousID);     AnonymousIdentificationModule.ClearAnonymousIdentifier();   } </script>

Once all the anonymous profile properties have been migrated to the current profile, the code deletes the anonymous profile (freeing up database space) and removes the anonymous cookie from the browser. Of course, this means that the user's saved anonymous profile values will not be visible to the user until he or she logs on to the site.

You may decide to leave the anonymous profile and cookie in place so that the user reconnects to the anonymous profile on his or her next visit. Just bear in mind that any changes the user makes to his or her profile after logging on will not be reflected in the anonymous profile that the user sees before logging on again the next time the user returns to the site. This may be confusing for users, and so in general it is better to remove the anonymous profile values and cookie.

Note

Whether you migrate a shopping cart (or any other property) or not depends on the business rules for your site. You may decide to abandon the shopping cart if the user leaves the site without going through the "checkout and order" stage. In this case, you will just migrate the anonymous shopping cart and other properties every time. This is what the example does with the TextSize profile property. Remember that the anonymous cookie sent to the user's browser should reconnect the user to his or her existing profile so that any values stored there will appear even before the user logs inand will be persisted. However, if the user removes the cookie or logs in from a different machine, ASP.NET cannot reconnect that user to his or her stored profile. In this case, the default anonymous profile will overwrite the stored profile.


Figure 12.7 shows a page where the visitor has added items to the shopping cart and changed the text size while anonymous, and is now about to log in.

Figure 12.7. Shopping anonymously and then logging in


Figure 12.8 shows the result after logging in. You can see that the shopping cart and text size are both migrated to the current authenticated profile.

Figure 12.8. The migrated text size setting and shopping cart contents


Other Features of the Profile Class

Access Profile Properties Values

You saw some of the features of the profiles system that you can use in code to manipulate profiles in the previous section. Rather than reading and assigning values directly using indexers, you can access the values of profile properties using the GetPropertyValue and SetPropertyValue methods of the ProfileBase class exposed by the Profile property of the current page:

Object property-value = myProfile.GetPropertyValue(property-name) myProfile.SetPropertyValue(property-name, property-value)


Access Profile Property Group

You can access a profile property group and its members using the methods of the ProfileGroupBase class, an instance of which is returned from the GetProfileGroup method of the ProfileBase class:

ProfileGroupBase group = myProfile.GetProfileGroup(group-name) Object property-value = group.GetPropertyValue(property-name) group.SetPropertyValue(property-name, property-value)


Push Values into the Database

You can force the profile provider to push updated profile property values into the database using the Save method:

myProfile.Save()


Create New ProfileBase Instance

You can create a new ProfileBase instance to store a new user profile using the static Create method:

Profile.Create(user-name) Profile.Create(user-name, is-authenticated)


You can also access other properties of the ProfileBase class that you have not seen so far in this chapter to provide information about the current profile. These include the self-explanatory IsAnonymous, IsDirty, and LastActivityDate; Context (returns a reference to the current ASP.NET context), PropertyValues (returns a collection of the profile property values), and Providers (returns a collection of the available providers).

For a full list of the members of the ProfileBase class, see http://msdn2.microsoft.com/en-us/library/system.web.profile.profilebase_members.aspx. For a full list of the members of the ProfileGroupBase class, see http://msdn2.microsoft.com/en-us/library/ms151849(en-US,VS.80).aspx.




ASP. NET 2.0 Illustrated
ASP.NET 2.0 Illustrated
ISBN: 0321418344
EAN: 2147483647
Year: 2006
Pages: 147

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