Now that anonymous users can visit your site and add items to the shopping cart, they need the ability to log in when they're ready to check out and purchase their selections. In this section you will create a checkout page that only authenticated users can access.
5.3.1. Creating New User Accounts
When a user has finished shopping (i.e., selecting items in the storefront), you need to some way to authenticate her so that you can retrieve particulars such as shipping address, credit card number, and so on. In this section, you will build a page through which the user can register as a member of your site.
First, as always, you need to create the registration page. Add a new Web Form to the project and name it Register.aspx. Select MasterPage.master as the Master Page once again to assure Register.aspx has the same look and feel as other pages on your site.
Drag and drop the CreateUserWizard control from the Login tab in the Toolbox onto the Content control in Register.aspx. The CreateUserWizard control is a visual control that prompts the user to supply the necessary information to create a new user account.
The CreateUserWizard control
Because creating user accounts is such as common task, one performed by most web sites, Microsoft has provided a new CreateUserWizard control in ASP.NET 2.0. The CreateUserWizard control takes the drudgery out of creating user accounts by providing a highly customizable control that accepts users' information. It performs such tasks as verifying users' passwords and authenticating email addresses. It then automatically adds user accounts to the site using the specified Membership Provider.
Now set the look and feel of the registration form. On the CreateUserWizard Tasks menu, click on the Auto Format… link to apply the Professional scheme to the control.
ASP.NET 2.0 comes with several standard schemes to make your controls look professional.
You'll want the Main.aspx page to be loaded when the user has finished registering a new account. Set the ContinueDestinationPageUrl property (through the Properties window) of the CreateUserWizard control to Main.aspx.
Now position the control on the page. Highlight the CreateUserWizard control and select Format Justify Center on the Visual Studio menu bar to centralize the position of the control on the page. The 5.3.2. Creating a Login Page
Once you have created a registration page, you'll want to create a login page so returning customers can log into the web site.
First, create the login page. Add a new Web Form to the project and name it Login.aspx. Select MasterPage.master as the Master Page once again to assure Login.aspx has the same look and feel as other pages on your site.
Now create a login form for users to complete. Drag and drop the Login control from the Login tab in the Toolbox onto the Login.aspx page. The Login control allows a user to log into your web site using the Membership class that you have seen earlier.
Figure 5-21. The Register.aspx page
New Login Controls in ASP.NET 2.0
ASP.NET 2.0 ships with several new Login controls (such as Login, LoginView, LoginStatus, LoginName, CreateUserWizard, and ChangePassword) to help you accomplish tasks such as user authentication, display of login status and login name, and more. The figure shows the various new Login controls in the Toolbox.
Set the look and feel of the control. Using the Login Tasks menu, click on the Auto Format… link to apply the Elegant scheme to the control.
Under the Login control, type the text "New Member? Register here." At the end of the text, add a LinkButton control from the Toolbox (see Figure 5-22).
Figure 5-22. Populating the Login.aspx page
Finally, set the PostBackUrl property of the LinkButton control to ~/Register.aspx so that the Register.aspx page will be loaded to help an unregistered user create a new account. Also, set the ContinueDestinationPageUrl property of the Login control to Main.aspx so that upon successful login, the user would be redirected to Main.aspx.
5.3.3. Restrict Unauthorized Access to Pages
So far, you have seen how to easily add a login page to your web site and how you can allow users to register for a new account in your application. In this section, you will add a new members-only folder to your web site and restrict access to authenticated users only.
First, create the folder in your project that will contain the restricted pages. To add a new folder to your project right-click on the project name, ShoppingApp in the Solution Explorer and then select Add Folder Regular Folder. Name the folder Next, set the authorization required to access the folder. In Web.config, add the markup shown in bold in Example 5-7 to restrict anonymous users from accessing the files contained within the Members folder.
Example 5-7. Denying anonymous users access to the Members page
… </system.web> <location path="Members"> <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </location> </configuration>
The <location> element together with the <authorization> element allows you to restrict access to a particular folder on your web site. In this case, you have used the <deny> element to prevent all anonymous (represented by "?") users from accessing the Members folder.
5.3.4. Checking Out from the Store
While an unauthenticated user is selecting items on the Storefront page (Main.aspx) of ShoppingApp and adding them to the shopping cart, the Profile service treats the user as anonymous. Once the user has finished choosing items, clicks on the Checkout button to check out, and is authenticated, you need to take special steps to preserve the items he has added to the shopping cart. This is because the profile data that was saved while the user was anonymous is lost when he switches from using a GUID to using a user ID for identification. To migrate the profile of the user, you need to transfer whatever information was saved in the anonymous profile to the user profile.
In this section, you will learn how to migrate an anonymous profile to an authenticated profile once a user has been authenticated. Using the authenticated profile, you'll display a Checkout page that shows the user what's in the shopping cart and offers the option to continue shopping. The completed page is shown in Figure 5-25.
First, add a Global.asax file to the project (Figure 5-23). (Right-click on project name in Solution Explorer and then select Add New Item…. Select Global Application Class.) You will need the Global.asax file to service an event (see the next step) when the user changes from an anonymous state to an authenticated one. Visual Studio opens the file for you after adding it to your project.
The Global.asax file, also known as the ASP.NET application file, is an optional file that contains code for responding to application-level events raised by ASP.NET or by HttpModules. In this example, the Profile_MigrateAnonymous event will be fired when a user changes from an anonymous state to an authenticated one. This event is serviced in the Global.asax file.
Figure 5-23. Adding a Global.asax file to the project
Type the Profile_MigrateAnonymous event handler shown in Example 5-8 into Global.asax. The Profile_MigrateAnonymous event is raised whenever a user changes her status from anonymous to authenticated (when she logs into the application via the Login.aspx page).
You can get the anonymous ID from the AnonymousId property (in the ProfileMigrateEventArgs class) and then use the GetProfile method to retrieve the anonymous profile. The retrieved profile can then be assigned to the authenticated user profile. You will also delete the old profile associated with the anonymous user.
Example 5-8. Profile_MigrateAnonymous event handler
Sub Profile_MigrateAnonymous(ByVal sender As Object, _ ByVal e As ProfileMigrateEventArgs) Dim anonymousProfile As ProfileCommon = _ Profile.GetProfile(e.AnonymousID) If anonymousProfile.shoppingcart IsNot Nothing Then Profile.shoppingcart = anonymousProfile.shoppingcart End If '---delete the items associated with the anonymous user ProfileManager.DeleteProfile(e.AnonymousID) '---clear the anonymous identifier from the request ' so that this event will not fire for an authenticated ' user AnonymousIdentificationModule.ClearAnonymousIdentifier End Sub
Now you'll create the Checkout page that will be used to display the items currently stored in the user's shopping cart. Add a new Web Form to the Members folder and select the MasterPage.master Master Page. Name the new Web Form Checkout.aspx.
Populate the form with a GridView control and apply the Sand & Sky scheme to it. (Select Auto Format… in the GridView Tasks menu; see Figure 5-24.)
Figure 5-24. Applying Auto Format to a GridView control
Also, add a LinkButton control under the GridView control and set its Text property to "Continue Shopping" and its PostBackUrl property to ~/Main.aspx. The results are shown in Figure 5-25.
The GridView control in ASP.NET 2.0 is similar to the DataGridView control you have seen in Chapter 4, except that GridView is web based and DataGridView is Windows based.
In the code behind of Checkout.aspx, code the Form_Load event as shown in Example 5-9. The Checkout.aspx page will first create a dataset containing all the items in the shopping cart and then use it to bind to the GridView control. It also changes the image in the imgHeader control in the Master Page using the FindControl method in the Master property.
Figure 5-25. Members/Checkout. aspx page
Example 5-9. Checkout. aspx Form_Load event
Imports System.Data Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load Dim myCart As OReilly.Cart myCart = Profile.shoppingcart Dim item As OReilly.itemType '---change the image Dim masterImage As Image masterImage = CType(Master.FindControl("imgHeader"), _< Image) If masterImage IsNot Nothing Then masterImage.ImageUrl = "~/Images/header_shopping.gif" End If '---create a dataset--- Dim ds As New DataSet ds.Tables.Add("Items") ds.Tables("Items").Columns.Add("ISBN") ds.Tables("Items").Columns.Add("Qty") Dim row As DataRow '---return all the items as a dataset--- For Each item In myCart.items row = ds.Tables("Items").NewRow row("ISBN") = item.isbn row("Qty") = item.qty ds.Tables("Items").Rows.Add(row) Next '---Bind the GridView control to the dataset GridView1.DataSource = ds GridView1.DataBind() End Sub
Think of a dataset as a database containing tables stored in memory.
Modifying a Master Page at Runtime
When a Web Form that uses a Master Page is loaded at runtime, it displays the content of the Master Page together with its own content. However there are times when you will want to modify parts of the Master Page when a particular Content page is loaded.
You locate the controls you want to modify on the Master Page by using the FindControl method of the Master property, then supplying the name and type of the control you want to modify. Once the control is located, you can change its properties as if it were a local object.
Master is a special property exposed by the Web Form as a handle with which to access the Master Page. However, the Master property is valid only on pages that reference a Master Page.
You can programmatically check if a page is using a Master Page by doing this:
If Master Is Nothing Then '---Page does not use master page--- … End If
You'll want Checkout.aspx to be displayed when a user clicks on the Checkout button in Main.aspx. So, as a last step, go to Main.aspx and set the PostPackUrl property of the Checkout button in Main.aspx to ~/ Members/Checkout.aspx so that the user can be brought to the Checkout.aspx page to check out. If an unauthenticated user clicks on the Checkout button, he will be redirected to Login.aspx.