Shopping for Products

The Details.aspx page gives full information about a book chosen on the Search.aspx or Specials.aspx page. While viewing this information, visitors can add this book to their shopping carts.

Figure 13-5. Layout of Details.aspx page.

The Details.aspx Content Page

Coding for this page is shown below. As a content page, it occupies the same ContentPlaceHolder control on the master page as do other pages of the site. The Import directives are needed for scripts described below.

<%@ Page MasterPageFile="eCommerce.master" Language="vb" Debug="True"%>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Drawing" %>

<SCRIPT Runat="Server">
  ...
</SCRIPT>

<asp:Content id="Details" ContentPlaceHolderID="CONTENT" Runat="Server">

<asp:Label Text="Book Details" Runat="Server"
Font-Size="14pt" ForeColor="#990000"/>

<asp:AccessDataSource id="BookSource" Runat="Server"
  DataFile="../Databases/BooksDB.mdb"/>

<asp:FormView id="FormViewDisplay" DataSourceID="BookSource" Runat="Server"
  Style="margin-top:10px"/>

  <ItemTemplate>
    <table border="0">
    <tr>
      <td style="width:60px">
        <asp:Image Runat="Server"
          ImageUrl='<%# "BookPictures/" & Eval("BookID") & ".jpg" %>'
          Style="float:left; margin-right:10px"/>
      </td>
      <td style="width:440px">
        <asp:Label id="BookID" Runat="Server"
          Text='<%# Eval("BookID") %>'
          Font-Bold="True"/><br/>
        <asp:Label id="BookTitle" Runat="Server"
          Text='<%# Eval("BookTitle") %>'
          Font-Bold="True" Font-Size="14pt"/><br/>
        <asp:Label id="BookAuthor" Runat="Server"
          Text='<%# Eval("BookAuthor") %>'/><br/>
        <asp:Label id="BookPrice" Runat="Server"
          Text='<%# String.Format("{0:C}", Eval("BookPrice"))) %>'/>
        <asp:Label id="BookSalePrice" Runat="Server"
          Text='<%# Get_Sale_Price(Eval("BookPrice"), Eval("BookSale")) %>'
          Font-Bold="True" ForeColor="#990000" /><br/><br/>
        <asp:Button Text="Add to Cart" OnClick="Add_To_Cart" Runat="Server"/>
      </td>	
    </tr>
    <tr>
      <td colspan="2">
        <br/>
        <asp:Label Width="500" Runat="Server"
          Text='<%# Eval("BookDescription") %>'/>
      </td>
    <tr>
    </table>

  </ItemTemplate>

</asp:FormView>

</asp:Content>
Listing 13-18. Code for Details.aspx page.

Selecting a Book for Display

A FormView control is used to display book information since it offers flexibility in arranging the display. It is associated with an AccessDataSource to retrieve book information. However, since the book to be displayed is identified in a query string passed to this page, the Page_Load subprogram must capture this query string value and use it to compose a SelectCommand for the AccessDataSource. This portion of the page script along with the function to calculate special pricing are shown below.

<SCRIPT Runat="Server">

Sub Page_Load()

  If Not Page.IsPostBack
  Dim SQLString As String
  SQLString = "SELECT * FROM Books " & _
              "WHERE BookID = '" & Request.QueryString("BookID") & "'"
    BookSource.SelectCommand = SQLString
  End If

End Sub

Function Get_Sale_Price (Price As Decimal, Sale As Boolean)

  If Sale = True Then
    Price = Price * Application("Discount")
    Return String.Format("Special Price: {0:C}", Price)
  End If

End Function

...
</SCRIPT>
Listing 13-19. Code to select and display product details.

Here, the query string value (a BookID) is appended to a SELECT statament and assigned to the SelectCommand of the AccessDataSource for the FormView. The Get_Sale_Price subprogram is similar to the one on the Search.aspx page. It returns a calculated discounted price, formatted inside a character string, or it returns nothing.

Creating a Shopping Cart

A button on the page permits customers to add this book to their shopping carts. There are a number of ways to implement a shopping cart, the easiest probably being as a database table. Records are added to or removed from the table as customers go about their shopping. At the close of shopping, customer purchases are extracted from the table to produce sales orders summarizing purchases.

A ShopCart table is added to the BooksDB.mdb database to capture sales information for all customers visiting the site. The format of this table is shown below.

Figure 13-6. Format of ShoppingCart table.

The OrderNumber field is used to store a customer identification to distinguish one customer's books from another's. The special Session("OrderNumber") value generated when a visitor arrives at the site is used for this unique identifier. Other fields identify the book selected for purchase along with book information needed to create a final sales order for this customer. Customers and books, then, are uniquely identified by the combination OrderNumber and BookID fields.

Adding an Item to the Shopping Cart

When the "Add to Cart" button is clicked, the Add_To_ShopCart subprogram is called to write a new record to the ShopCart table. Four items of information are needed from the FormView to create this record: the BookID, title, regular price, and sale price. This information is in four Label controls inside the FormView.

Sub Add_To_Cart (Src As Object, Args As EventArgs)

  Dim FVBookID As Label = FormViewDisplay.FindControl("BookID")
  Dim FVBookTitle As Label = FormViewDisplay.FindControl("BookTitle")
  Dim FVBookPrice As Label = FormViewDisplay.FindControl("BookPrice")
  Dim FVBookSalePrice As Label = FormViewDisplay.FindControl("BookSalePrice")
  Dim BookPrice As Decimal = FVBookPrice.Text
  If FVBookSalePrice.Text <> "" Then
    BookPrice = Replace(FVBookSalePrice.Text, "Special Price: ", "")
  End If
  Dim DBConnection As OleDbConnection
  Dim DBCommand As OleDbCommand
  Dim SQLString As String
  Dim SQLAddString As String
  
  DBConnection = New OleDbConnection( _
    "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source=" & Server.MapPath("../Databases/BooksDB.mdb"))
  DBConnection.Open()
  SQLString = "SELECT Count(*) FROM ShopCart " & _
              "WHERE OrderNumber = '" & Session("OrderNumber") & "' " & _
              "AND BookID = '" & FVBookID.Text & "'"
  DBCommand = New OleDbCommand(SQLString, DBConnection)
  If DBCommand.ExecuteScalar() = 0 Then
    
    SQLAddString = "INSERT INTO ShopCart (OrderNumber, OrderDate, " & _
      "BookID, BookTitle, BookPrice, BookQty) VALUES (" & _
      "'" & Session("OrderNumber") & "', " & _
      "'" & Today & "', " & _
      "'" & FVBookID.Text & "', " & _
      "'" & FVBookTitle.Text & "', " & _
      BookPrice & ", 1)"
    DBCommand = New OleDbCommand(SQLAddString, DBConnection)
    DBCommand.ExecuteNonQuery()
    
  End If
  DBConnection.Close()
  
  Src.Text = "Item Added"
  Src.ForeColor = Color.FromName("#990000")
  Src.BackColor = Color.FromName("#E0E0E0")
  Src.Font.Bold = True
  
End Sub
Listing 13-20. Code to add a product selection to the ShopCart table.

Recall that with bound controls which themselves contain multiple controls you cannot directly reference these embedded controls. That is, with a FormView you must "find" its internal controls containing the information you need by using the its FindControl() method. As has been illustrated previously, finding the four Label controls containing needed book information is accomplished with the following statements.

Dim FVBookID As Label = FormViewDisplay.FindControl("BookID")
Dim FVBookTitle As Label = FormViewDisplay.FindControl("BookTitle")
Dim FVBookPrice As Label = FormViewDisplay.FindControl("BookPrice")
Dim FVBookSalePrice As Label = FormViewDisplay.FindControl("BookSalePrice")
Listing 13-21. Code to find book information in FormView control.

The four controls are found through their id values and assigned to script-generated objects of the same type. These objects, then, serve as surrogate controls to access their associated values in the FormView.

The FVBookSalePrice value is not in correct format for writing to the ShopCart table. It includes the string "Special Price: " that needs to be removed leaving only a decimal number.

Dim BookPrice As Decimal = FVBookPrice.Text
If FVBookSalePrice.Text <> "" Then
  BookPrice = Replace(FVBookSalePrice.Text, "Special Price: ", "")
End If
Listing 13-22. Code to reformat book prices for writing to the ShopCart Table.

Either the FVBookPrice or FVBookSalePrice value is assigned to variable BookPrice. It is necessary to assign these values to a separate variable, otherwise the book sale price showing in the FormView also takes on the revised format of FVBookSalePrice when the "Special Price: " string is removed. If there is an FVBookSalePrice value, it becomes the final BookPrice, replacing the normal price of the item.

Once the three items of information (FVBookID, FVBookTitle, and BookPrice) have been found and formatted, they can be written as a record to the ShopCart table along with the Session("OrderNumber") to identify this customer and the current date produced by the Visual Basic Today property. First, though, one other determination needs to be made.

It is conventional to create a shopping cart record only the first time a product is selected for purchase. The record indicates the purchase of a single item. This practice avoids having to deal with multiple clicks on a "Buy" button as indicating a desire for more than one item. The clicks could, instead, indicate incompetence with a mouse, and how would the script know? It is better to deal with the quantity desired as a separate issue on a separate shopping cart page.

At present, then, the need is to ensure that only a single book record for any one book is written to the database. Therefore, the script checks for an existing record before writing a new one. This portion of the script is repeated below.

Dim DBConnection As OleDbConnection
Dim DBCommand As OleDbCommand
Dim SQLString As String
Dim SQLAddString As String
  
DBConnection = New OleDbConnection( _
  "Provider=Microsoft.Jet.OLEDB.4.0;" & _
  "Data Source=" & Server.MapPath("../Databases/BooksDB.mdb"))
DBConnection.Open()
SQLString = "SELECT Count(*) FROM ShopCart " & _
            "WHERE OrderNumber = '" & Session("OrderNumber") & "' " & _
            "AND BookID = '" & FVBookID.Text & "'"
DBCommand = New OleDbCommand(SQLString, DBConnection)
If DBCommand.ExecuteScalar() = 0 Then
    
  SQLAddString = "INSERT INTO ShopCart (OrderNumber, OrderDate, " & _
    "BookID, BookTitle, BookPrice, BookQty) VALUES (" & _
    "'" & Session("OrderNumber") & "', " & _
    "'" & Today & "', " & _
    "'" & FVBookID.Text & "', " & _
    "'" & FVBookTitle.Text & "', " & _
    BookPrice & ", 1)"
  DBCommand = New OleDbCommand(SQLAddString, DBConnection)
  DBCommand.ExecuteNonQuery()
    
End If
DBConnection.Close()
Listing 13-23. Code to write a single book record to the ShopCart Table.

An initial SELECT statement is issued to get a count of the number of records in the ShopCart table where the OrderNumber field matches the Session("OrderNumber") and the BookID field matches the FVBookID value from the FormView. If this count is not 0, then a record already exists for this purchase and no record is written to the table. If the returned count is equal to 0, then a new record is written to the table.

A new record is written to the ShopCart table by issuing an SQL INSERT statement. This statement writes six fields of information: the Session("OrderNumber") for the customer, the FVBookID from the FormView, today's date, the FVBookTitle from the FormView, the BookPrice variable, and the quantity 1. After writing this record, the script changes the text of the "Add to Cart" button to read "Item Added" to visually indicate this addition to the shopping cart.

Src.Text = "Item Added"
Src.ForeColor = Color.FromName("#990000")
Src.BackColor = Color.FromName("#E0E0E0")
Src.Font.Bold = True
Listing 13-24. Code to style "Add to Cart" button to indicate addition of item to ShopCart table.

At this point, the customer can return to shopping or can go to the shopping cart page to review purchases, change quantities ordered, delete items from the shopping cart, or proceed to checkout.