
Beginning ASP.NET 2
.0.pdf
E-Commerce
17.Select the DataList control underneath SqlDataSource1. From the smart tag dialog box that appears select Edit Templates Item Template.
18.Go to the Image Button (the graphic with the red cross), click the smart tag dialog box, and select Edit Data Bindings in the dialog that appears.
19.Click Show All Properties and select PostbackURL. Check the Custom bindings and change it so that it reads as follows:
Eval”ProductID”,”WroxShopItem.aspx?ProductID={0}”
20.Run the application from WroxShop.aspx and click the Scarf image. You should see what appears in Figure 13-18.
Figure 13-18
If you click Return to Shop and go back and select another image, you will get details about that product, too.
How It Works
The Product Item page is put together in much the same way as the Product Catalog, the main difference being that instead of all of the items being viewed, you only want to look at the details of a single item. If you view the source, you will once again see that it is comprised of the SqlDataSource and DataList controls:
<form id=”form1” runat=”server”> <div>
<asp:SqlDataSource ID=”SqlDataSource1” runat=”server” ConnectionString=”<%$ ConnectionStrings:WroxUnitedConnectionString %>”
479

Chapter 13
SelectCommand=”SELECT DISTINCT [ProductID], [Name], [Description], [Price], [PictureURL] FROM [Products] WHERE ([ProductID] = @ProductID)”>
<SelectParameters>
<asp:QueryStringParameter Name=”ProductID” QueryStringField=”ProductID” Type=”Int32” />
</SelectParameters>
</asp:SqlDataSource>
</div>
<asp:DataList ID=”DataList1” runat=”server” DataKeyField=”ProductID” DataSourceID=”SqlDataSource1”>
<ItemTemplate>
<asp:Label visible=”false” ID=”PictureURL” Text=’<%#Eval(“PictureURL”)%>’ />
<asp:Image ID=”Image1” runat=”server” ImageUrl=’<%# Eval(“PictureURL”, “ProductImages\{0}”) %>’ /><br /> <asp:Label ID=”NameLabel” runat=”server” Text=’<%# Eval(“Name”) %>’></asp:Label><br />
<asp:Label ID=”DescriptionLabel” runat=”server” Text=’<%# Eval(“Description”) %>’>
</asp:Label><br />
<asp:Label ID=”PriceLabel” runat=”server” Text=’<%# Eval(“Price”, “{0:##0.00}”) %>’></asp:Label><br />
<br /> <br />
</ItemTemplate>
</asp:DataList>
<asp:HyperLink ID=”HyperLink1” runat=”server” NavigateUrl=”~/WroxShop.aspx”>Return to Shop</asp:HyperLink>
</form>
The difference is that this time the SqlDataSource’s SelectCommand attribute has an extra WHERE clause:
SelectCommand=”SELECT DISTINCT [ProductID], [Name], [Description], [Price], [PictureURL] FROM [Products] WHERE ([ProductID] = @ProductID)”
This references a ProductID parameter. Underneath this element the SqlDataSource1 also contains a SelectParameters element, which specifies where you are going to get the parameter from:
<SelectParameters>
<asp:QueryStringParameter Name=”ProductID” QueryStringField=”ProductID” Type=”Int32” />
</SelectParameters>
These parameters are used to transfer the details across about which item you have clicked on. This is where the hidden ProductID comes into play. You haven’t used it so far, but now you most definitely need it. Each item in your catalog has a unique identifier, this being ProductID. You collect ProductID when the image is collected and send it as a QueryString as follows:
http://localhost/Chapter13/WroxShopItem.aspx?ProductID=1
Then your second page (WroxShopItem.aspx) is able to pick that up and use that in the WHERE clause of the SELECT command of the SqlDataSource control to return the details of that single item. The
480

E-Commerce
DataList control of WroxShopItem is incredibly similar to the WroxShop DataList control. The only two changes are that instead of referencing the thumbnail version of the image, you just use the whole version of the image. Space is no longer such an essential here, because you don’t have to worry about nine other items. The second change is that you have added the Description from the Products table as an extra label. You’ve also used the PictureURL from PictureURLLabel as a URL for your <asp:Image> control that you use to display the merchandise. Apart from that, it is business as usual.
You’re actually quite a distance into this chapter and so far you haven’t created anything totally specific to e-commerce. I’m not deliberately playing a waiting game here; the problem is that without a catalog and a set of items, you have nothing to put into your cart. The order in which you create things is quite essential. Now that you have a catalog and the ability to browse specific items in the catalog, it’s at last time to wheel out your shopping cart.
The Shopping Car t
The shopping cart is a simple enough control in principle, but until ASP.NET 2.0, it has been an awkward feature to create. The simple reason is this — how do you go about remembering which items are stored in the cart? The quick answer is state. State management, though, has never been quite as straightforward as it perhaps should be. Chapter 14 looks at sessions and state in greater detail, but we need to talk about it briefly here.
It’s not new feature and to be fair it’s been going on behind the scenes throughout this book, because every page contains a ViewState control that holds an encrypted version of each page’s control contents. However, this is squared against the fact that the Internet is stateless, and so every time you move from page to page, the web server acts like a goldfish — asking the same question, “Who are you?” So you must do the remembering for the web server.
Previously in ASP.NET 1.1 you could go about remembering the items in the cart in one of two common ways. Either you could create a cart and stick the whole contents of the cart in a Session object, and lose the list of items every time someone logged out and back in again, or alternatively you could create a shopping cart item in the database, and then be tied to updating the database each time you added something to the cart. The advantage of the second approach is of course that if you lost your Internet connection suddenly when you came to log back in, you would still have the contents of the cart. This is particularly useful if you’ve just spent an hour assembling the weekly shop, only to have to endure your ISP’s 0.01% downtime at that crucial point. Of course, the first approach could make use of cookies so that it could link back to your shopping cart if you logged on again, but then this would rely on a whole membership system, so you can see how suddenly your nice small shopping cart becomes a rather larger and more complex shopping cart and membership system.
ASP.NET 2.0 is able to take some of the advantages from both approaches (remembering the state between connections) while leaving at home some of the awkwardness (constant database access, needing to log on as a member before you can use the shopping cart). It does this by making use of the new profiles features that you looked at in Chapter 11. You’ll see how you can use this as you come to build your shopping cart control. First, though, you need to build the object that is going to form the foundations of your shopping cart’s memory.
481

Chapter 13
The Shopping Object
You’re going to create an object that can store your items. You need to start once again at the drawing board by creating a design. The first thing to mention is that your shopping object needs to look after two things: the items in the cart and the cart itself. Therefore, you’re going to need two objects:
CartItem
ShoppingCart
Both merit some more in-depth discussion as to what is required.
The CartItem Object
The CartItem object is easiest. Design is often just a case of sitting down with pen and paper and trying to imagine what you as a user would require from a site. A second option is to look at what everyone else is doing. However, it’s probably best to just stick to the pen and paper option when brainstorming, because what you might require from a site might be unduly influenced by you looking at other vendors’ sites. So you’re going to have a quick think now. It doesn’t matter if you don’t get it absolutely right the first time, because you can amend it as you go along.
With your shopping cart a good first stab would be the following list of attributes:
A representation of the item
The quantity of the item
The price of the item
The total price
For the representation of the item, you could quite easily use the title or the description of the item, but given that you have some thumbnail pictures at hand, it would be nice to use them as well. In your cart you can start with the name and a link to the image of the item purchased. The quantity and the price are both self-explanatory enough. However, the total price needs a little expanding. You could have a total price as follows:
Item |
Quantity |
Price |
Scarf |
2 |
$4.95 |
Bug |
2 |
$0.75 |
Total Price |
|
$11.40 |
It looks a little strange. That’s because you’re immediately totalling the $4.95 and the 75 cents, and they don’t add up to make $11.40. So as well as the total price, it might be better to do it spreadsheet style and total the price and the quantity first and create a total for each line, as shown in the following table:
482

E-Commerce
Item |
Quantity |
Price |
Item Total |
|
|
|
|
Scarf |
2 |
$4.95 |
$9.90 |
Bug |
2 |
$0.75 |
$1.50 |
Total Price |
|
|
$11.40 |
|
|
|
|
So you can now add line total to the list of attributes you want to store. I think that’s as much as you need for each CartItem, so let’s move onto the ShoppingCart.
The WroxShoppingCart Object
The CartItem object was the easiest, because it’s fairly static in its conception. Either you have a CartItem object or you don’t, unless you prescribe to some sort of parallel universe theory where you can have both at the same time. However, computing is quite complicated enough already without parallel universes to think about, too! The reason the WroxShoppingCart object is more complex is because it will comprise one or several items in the cart. So you immediately need somewhere to store a stack of cart items in your object. Rather than a warehouse or a shopping trolley, you can use the collections talked about in Chapter 9 to do this.
This also raises other questions, namely how do you differentiate between different items in the cart, and how do you maintain some sort of order with them? The answer is to add an index, so that, for example, if you add a scarf and that is item 1 in the cart, and then you add a bug, that becomes item 2 in the cart.
Your cart will also need to deal with the set of possible actions that you can perform on the contents of the cart. Briefly the most common actions you might perform on a shopping cart are as follows:
Adding an item to the cart
Updating the information about an item in the cart
Updating the total price of all of the items in the cart
Deleting an item from the cart
You will need to handle these four actions. Last, because you are keeping a record of all of the items within the cart, it might be easier to move the total purchase price across to this object instead. This is just the kind of amendment we talked about earlier when creating a design. Better to discover it now, than when you’ve actually created it. So the cart item collection; an index; the add, update, and delete actions; and a final total are all the things you are going to have build into your ShoppingCart object.
Now that you’ve got an outline of what you need to store, in this Try It Out you build the object to store it.
Try It Out |
Building the WroxShoppingCart Object |
1.Go to Solution Explorer, right-click the top item, and select Add New Item. Choose Class and call it Shopping.vb.
2.Click OK. Visual Web Developer will inform you with a dialog that you are attempting to add a class to an ASP.NET application and that it should be moved to the App_Code folder to be generally consumable. Click Yes to accept this proposition.
483

Chapter 13
3.Add the following code to create a shopping cart item object, called CartItem:
Imports Microsoft.VisualBasic
Imports System.Data
Imports System.Data.SqlClient
Imports System.Collections.Generic
Namespace Wrox.Commerce
<Serializable()> _ Public Class CartItem
Private _productID As Integer Private _productName As String Private _productImageUrl As String Private _quantity As Integer Private _price As Double
Private _lineTotal As Double
Public Sub New()
End Sub
Public Sub New(ByVal ProductID As Integer, ByVal ProductName As String, _ ByVal ProductImageUrl As String, ByVal Quantity As Integer, _
ByVal Price As Double)
_productID = ProductID
_productName = ProductName
_productImageUrl = ProductImageUrl
_quantity = Quantity
_price = Price
_lineTotal = Quantity * Price
End Sub
Public Property ProductID() As Integer Get
Return _productID End Get
Set(ByVal value As Integer) _productID = value
End Set
End Property
Public Property ProductName() As String Get
Return _productName End Get
Set(ByVal value As String) _productName = value
End Set
End Property
Public Property ProductImageUrl() As String
Get
Return _productImageUrl
484

E-Commerce
End Get
Set(ByVal value As String) _productImageUrl = value
End Set
End Property
Public Property Quantity() As Integer Get
Return _quantity End Get
Set(ByVal value As Integer) _quantity = value
End Set
End Property
Public Property Price() As Double Get
Return _price End Get
Set(ByVal value As Double) _price = value
End Set
End Property
Public ReadOnly Property LineTotal() As Double
Get
Return _quantity * _price
End Get
End Property
End Class
4.Underneath the CartItem class add the following code to create the WroxShoppingCart object:
<Serializable()> _
Public Class WroxShoppingCart
Private _dateCreated As DateTime
Private _lastUpdate As DateTime
Private _items As List(Of CartItem)
Public Sub New()
_items = New List(Of CartItem)
_dateCreated = DateTime.Now
End Sub
Public Property Items() As List(Of CartItem) Get
Return _items End Get
Set(ByVal value As List(Of CartItem)) _items = value
End Set
485

Chapter 13
End Property
Public Sub Insert(ByVal ProductID As Integer, ByVal Price As Double, _ ByVal Quantity As Integer, ByVal ProductName As String, _ ByVal ProductImageUrl As String)
Dim ItemIndex As Integer = ItemIndexOfID(ProductID) If ItemIndex = -1 Then
Dim NewItem As New CartItem()
NewItem.ProductID = ProductID
NewItem.Quantity = Quantity NewItem.Price = Price NewItem.ProductName = ProductName NewItem.ProductImageUrl = ProductImageUrl _items.Add(NewItem)
Else
_items(ItemIndex).Quantity += 1 End If
_lastUpdate = DateTime.Now() End Sub
Public Sub Update(ByVal RowID As Integer, ByVal ProductID As Integer, _
ByVal Quantity As Integer, ByVal Price As Double)
Dim Item As CartItem = _items(RowID)
Item.ProductID = ProductID
Item.Quantity = Quantity
Item.Price = Price
_lastUpdate = DateTime.Now()
End Sub
Public Sub DeleteItem(ByVal rowID As Integer) _items.RemoveAt(rowID)
_lastUpdate = DateTime.Now() End Sub
Private Function ItemIndexOfID(ByVal ProductID As Integer) As Integer Dim index As Integer
For Each item As CartItem In _items If item.ProductID = ProductID Then
Return index End If
index += 1 Next
Return -1
End Function
Public ReadOnly Property Total() As Double
Get
Dim t As Double
If _items Is Nothing Then
Return 0
End If
For Each Item As CartItem In _items
t += Item.LineTotal
486

E-Commerce
Next
Return t
End Get
End Property
End Class
End Namespace
5.Save this page. Unfortunately there’s nothing you can do with the class until you come to instantiate an instance of the object, so there’s nothing to see just yet.
How It Works
The WroxShoppingCart class provides you with an object that you can just insert into your code. You start by defining both objects as being in the Namespace Wrox.Commerce. This means that you can insert them into any page by using the following reference at the top of a page:
<%@ Imports Namespace = “Wrox.Commerce” %>
This reference enables you to make use of all of the properties and methods within the ShoppingCart object. There is a lot of code here within the object, so let’s briefly skip through what is happening with each object inside the ShoppingCart object.
The CartItem is just a series of properties to store each of the cart attributes in. You define a set of private variables that represent each of the items in your CartItem object. On top of the five previously mentioned, the productID is also there so you can uniquely identify the type of item:
Private _productID As Integer
Private _productName As String
Private _productImageUrl As String
Private _quantity As Integer
Private _price As Double
Private _lineTotal As Double
The productID attribute is an integer, because it stores your unique identifier. The productName attribute is text, so you store that as a String. Next comes the productImageUrl attribute, and rather than store a physical image, you store a URL of the location where you can find that image (thus saving you having to physically store the images in the database), and so that is also stored as Text. The quantity attribute is also stored as an Integer, because it is impossible to have a fraction of an item (Wrox United doesn’t sell half a scarf, or a bug with two legs). The price attribute, however, is a representation of currency, so that requires a Double data type because you will be dealing with fractions, and because the lineTotal attribute is made from quantity multiplied by price, that must also be a Double data type.
Each of these attributes must be both readable and writable, so you create a set of properties for each in this format, using the ProductID() property as an example:
Public Property ProductID() As Integer Get
Return _productID End Get
Set(ByVal value As Integer) _productID = value
End Set
End Property
487

Chapter 13
Each one of the properties takes this format with both Get and Set constructors, referencing the variables you defined at the top of the ShoppingCart definition. The only one that is any different is the LineTotal() property, which is a multiplication of the quantity and price properties. You don’t want anyone to be able to alter this because you change it yourself, so it only has a Get part:
Public ReadOnly Property LineTotal() As Double
Get
Return _quantity * _price
End Get
End Property
That sums up the entire CartItem object. The WroxShoppingCart object is a little trickier. Because you are constantly updating your shopping cart, you need to keep a track of when it was created and when it was last updated. You start by defining a couple of variables that do this for you:
Private _dateCreated As DateTime
Private _lastUpdate As DateTime
These two variables store the time at which the WroxShoppingCart object was created and the time at which it was last updated. Next you create the collection. The collection is a List object and it contains a list of CartItem objects. You create a New() method that you can call in your code, to create a new instance of a shopping cart:
Public Sub New()
_items = New List(Of CartItem)
_dateCreated = DateTime.Now
End Sub
You create a property called Items in which to store your List of CartItems:
Public Property Items() As List(Of CartItem) Get
Return _items End Get
Set(ByVal value As List(Of CartItem)) _items = value
End Set
End Property
Then you come to your three actions, which you code as methods. The first method insert requires all the information that your cart requires, namely ProductID, Quantity, Price, ProductName, and the
ProductImageUrl:
Public Sub Insert(ByVal ProductID As Integer, ByVal Price As Double, _ ByVal Quantity As Integer, ByVal ProductName As String, _ ByVal ProductImageUrl As String)
Dim ItemIndex As Integer = ItemIndexOfID(ProductID) If ItemIndex = -1 Then
Dim NewItem As New CartItem()
NewItem.ProductID = ProductID
NewItem.Quantity = Quantity NewItem.Price = Price NewItem.ProductName = ProductName
488