ASP.NET 2.0 Everyday Apps For Dummies (2006)
.pdfChapter 6: Building a Shopping Cart Application 207
End Get
Set(ByVal value As String) _name = value
End Set End Property
Public Property Price() As Decimal Get
Return _price End Get
Set(ByVal value As Decimal) _price = 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 ReadOnly Property Total() As Decimal
Get
Return _price * _quantity
End Get
End Property
6
7
8
End Class
Creating the Order Class
The Order class represents the order placed by the user. Its main purpose in life is to serve as the parameter passed to the WriteOrder method of the OrderDB class. The constructors and properties of this class appear back in Table 6-7; Listings 6-19 and 6-20 provide the C# and Visual Basic versions of this class.
Listing 6-19: The Order class (C# version)
using System; using System.Data;
using System.Configuration; using System.Web;
using System.Web.Security;
(continued)
208 Part III: Building E-Commerce Applications
Listing 6-19 (continued)
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
public class Order
{
private DateTime _orderDate; private Customer _cust; private ShoppingCart _cart;
public Order()
{
_cust = new Customer(); _cart = new ShoppingCart();
}
public Order(DateTime orderDate, Customer Cust, ShoppingCart Cart)
{
this.OrderDate = orderDate; this.Cust = Cust; this.Cart = Cart;
}
public DateTime OrderDate
{
get
{
return _orderDate;
}
set
{
_orderDate = value;
}
}
public Customer Cust
{
get
{
return _cust;
}
set
{
_cust = value;
}
}
public ShoppingCart Cart
{
get
1
2
3
4
5
6
Chapter 6: Building a Shopping Cart Application 209
{ |
|
return _cart; |
|
} |
|
set |
|
{ |
|
_cart = value; |
|
} |
|
} |
|
public decimal SubTotal |
7 |
{ |
|
get |
|
{ |
|
decimal subTotal = 0;
foreach (CartItem item in _cart.GetItems()) subTotal += item.Total;
return subTotal;
} |
|
} |
|
public decimal SalesTax |
8 |
{ |
|
get |
|
{ |
|
if (this.Cust.State.Equals(“CA”)) |
|
return this.SubTotal * 0.0775m; |
|
else |
|
return 0.0m; |
|
} |
|
} |
|
public decimal Shipping |
9 |
{ |
|
get |
|
{ |
|
int count = 0;
foreach (CartItem item in _cart.GetItems()) count += item.Quantity;
return count * 2.00m;
} |
|
} |
|
public decimal Total |
10 |
{ |
|
get |
|
{ |
|
return this.SubTotal + this.Shipping |
|
+ this.SalesTax; |
|
} |
|
} |
|
}
210 Part III: Building E-Commerce Applications
The following paragraphs draw your attention to the highlights of this class:
1 Private instance variables hold the data for the order. The _orderDate variable holds the order’s date, while the _cust and _cart variables hold the Customer and ShoppingCart objects associated with the order.
2 The parameterless constructor creates new Customer and ShoppingCart objects for the order.
3 The second constructor lets you create an Order object by passing the order date, customer, and shopping cart data as parameters.
4 The OrderDate property lets you set or retrieve the order date.
5 The Cust property lets you set or retrieve the order’s Customer object.
6 The Cart property lets you set or retrieve the order’s shopping cart.
7 The SubTotal property is a read-only property that returns the total for the items in the order’s shopping cart. It uses a for each loop to calculate this value by adding up the Total property for each item in the shopping cart. Notice that the cart’s GetItems method is called to retrieve the items.
8 The SalesTax property is a read-only property that calculates the sales tax. If the customer lives in California, the tax is calculated at 7.75 percent. Otherwise no tax is charged.
In a real application, you wouldn’t hard-code the tax rate into the program. Instead, you’d store the tax rate in a file, a database, or perhaps in the application’s web.config file. That way you wouldn’t have to recompile the application when the governor reneges on that campaign promise about not raising taxes.
9 The Shipping property calculates the shipping charges by adding up the quantities for each item in the shopping cart, then multiplying the total number of items ordered by $2.00.
Of course, hard-coding the shipping charges into the program is an even worse idea than hard-coding the tax rate. In an actual application, you’ll almost certainly want to choose a more flexible way to store the shipping charges, such as in a file, a database, or in the web.config file.
10 The Total property is calculated by adding the values of the
SubTotal, Shipping, and SalesTax properties.
Chapter 6: Building a Shopping Cart Application 211
Listing 6-20: The Order class (VB version)
Imports Microsoft.VisualBasic
Imports System.Data
Public Class Order
Private _orderDate As DateTime
Private _cust As Customer
Private _cart As ShoppingCart
Public Sub New()
_cust = New Customer()
_cart = New ShoppingCart()
End Sub
Public Sub New(ByVal orderDate As DateTime, _ ByVal Cust As Customer, _
ByVal Cart As ShoppingCart) Me.OrderDate = orderDate Me.Cust = Cust
Me.Cart = Cart End Sub
Public Property OrderDate() As DateTime Get
Return _orderDate End Get
Set(ByVal value As DateTime) _orderDate = value
End Set End Property
Public Property Cust() As Customer Get
Return _cust End Get
Set(ByVal value As Customer) _cust = value
End Set End Property
Public Property Cart() As ShoppingCart Get
Return _cart End Get
Set(ByVal value As ShoppingCart) _cart = value
End Set End Property
Public ReadOnly Property SubTotal() As Decimal
Get
1
2
3
4
5
6
7
(continued)
212 Part III: Building E-Commerce Applications
Listing 6-20 (continued)
Dim d As Decimal = 0D
For Each item As CartItem In _cart.GetItems() d += item.Total
Next Return d
End Get End Property
Public ReadOnly Property SalesTax() As Decimal |
8 |
Get |
|
If Me.Cust.State = (“CA”) Then |
|
Return Me.SubTotal * 0.0775D |
|
Else |
|
Return 0D |
|
End If |
|
End Get |
|
End Property |
|
Public ReadOnly Property Shipping() As Decimal |
9 |
Get |
|
Dim count As Integer = 0
For Each item As CartItem In _cart.GetItems() count += item.Quantity
Next
Return count * 2D End Get
End Property
Public ReadOnly Property Total() As Decimal |
10 |
Get |
|
Return Me.SubTotal + Me.Shipping _ |
|
+ Me.SalesTax |
|
End Get |
|
End Property |
|
End Class |
|
Creating the OrderDB Class
The last class for this application, OrderDB, contains just a single public method to write an order to the database. However, several private methods are required to support this method. The C# version of this class is shown in Listing 6-21, and Listing 6-22 shows the Visual Basic version.
Chapter 6: Building a Shopping Cart Application 213
Listing 6-21: The OrderDB class (C# version)
using |
System; |
|
using |
System.Data; |
|
using |
System.Configuration; |
|
using |
System.Web; |
|
using |
System.Web.Security; |
|
using |
System.Web.UI; |
|
using |
System.Web.UI.WebControls; |
|
using |
System.Web.UI.WebControls.WebParts; |
|
using |
System.Web.UI.HtmlControls; |
|
using |
System.Web.Configuration; |
|
using |
System.Data.SqlClient; |
|
public static class OrderDB |
1 |
|
{ |
|
|
static SqlTransaction tran; |
2 |
|
static SqlConnection con; |
|
|
public static bool WriteOrder(Order o) |
3 |
|
{ |
|
|
|
string cs = WebConfigurationManager |
|
|
.ConnectionStrings[“ConnectionString”] |
|
|
.ConnectionString; |
|
|
con = new SqlConnection(cs); |
|
|
con.Open(); |
|
|
tran = con.BeginTransaction(); |
|
|
try |
|
|
{ |
|
InsertCustomer(o.Cust); int oNum = InsertOrder(o);
foreach (CartItem item in o.Cart.GetItems()) InsertItem(item, oNum);
tran.Commit();
con.Close(); return true;
}
catch (Exception ex)
{
tran.Rollback(); return false;
}
}
private static void InsertCustomer(Customer cust) 4
{
SqlCommand cmd = new SqlCommand(); cmd.Connection = con; cmd.Transaction = tran;
try
{
cmd.CommandText = “INSERT INTO Customers “
(continued)
214 Part III: Building E-Commerce Applications
Listing 6-21 (continued)
+“(lastname, firstname, “
+“address, city, state, zipcode,”
+“phone, email) “
+“VALUES (@LastName, @FirstName, “
+“@Address, @City, @State, @ZipCode,”
+“@PhoneNumber, @Email)”; cmd.Parameters.AddWithValue(
“@LastName”, cust.LastName); cmd.Parameters.AddWithValue(
“@FirstName”, cust.FirstName); cmd.Parameters.AddWithValue(
“@Address”, cust.Address); cmd.Parameters.AddWithValue(
“@City”, cust.City); cmd.Parameters.AddWithValue( “@State”, cust.State); cmd.Parameters.AddWithValue(
“@ZipCode”, cust.ZipCode); cmd.Parameters.AddWithValue(
“@PhoneNumber”, cust.PhoneNumber); cmd.Parameters.AddWithValue(
“@Email”, cust.Email); cmd.ExecuteNonQuery();
} |
|
catch (SqlException ex) |
|
{ |
|
if (ex.Number == 2627) // Duplicate key |
|
{ |
|
cmd.CommandText = “UPDATE Customers “ |
|
+ “SET lastname = @LastName, “ |
|
+ “firstname = @FirstName, “ |
|
+ “address = @Address, “ |
|
+ “city = @City, “ |
|
+ “state = @State, “ |
|
+ “zipcode = @ZipCode, “ |
|
+ “phone = @PhoneNumber “ |
|
+ “WHERE email = @Email “; |
|
cmd.ExecuteNonQuery(); |
|
} |
|
else |
|
throw ex; |
|
} |
|
} |
|
private static int InsertOrder(Order o) |
5 |
{ |
|
SqlCommand cmd = new SqlCommand(); |
|
cmd.Connection = con; |
|
cmd.Transaction = tran; |
|
cmd.CommandText = “INSERT INTO Orders “ |
|
+ “(orderdate, custemail, “ |
|
+ “subtotal, salestax, “ |
|
Chapter 6: Building a Shopping Cart Application 215
+“shipping) “
+“VALUES (@OrderDate, @Custemail, “
+“@subtotal, @salestax, “
+“@shipping)”;
cmd.Parameters.AddWithValue( “@OrderDate”, DateTime.Now);
cmd.Parameters.AddWithValue( “@Custemail”, o.Cust.Email);
cmd.Parameters.AddWithValue( “@subtotal”, o.SubTotal); cmd.Parameters.AddWithValue( “@salestax”, o.SalesTax); cmd.Parameters.AddWithValue( “@shipping”, o.Shipping);
cmd.ExecuteNonQuery(); cmd.CommandText = “SELECT @@IDENTITY”;
return Convert.ToInt32(cmd.ExecuteScalar());
} |
|
private static void InsertItem(CartItem item, |
6 |
int oNum) |
|
{ |
|
SqlCommand cmd = new SqlCommand(); |
|
cmd.Connection = con; |
|
cmd.Transaction = tran; |
|
cmd.CommandText = “INSERT INTO OrderItems “ |
|
+ “(ordernum, productid, “ |
|
+ “name, price, quantity) “ |
|
+ “VALUES (@OrderNum, @ProductID, “ |
|
+ “@Name, @Price, @Quantity)”; |
|
cmd.Parameters.AddWithValue( |
|
“@OrderNum”, oNum); |
|
cmd.Parameters.AddWithValue( |
|
“@ProductID”, item.ID); |
|
cmd.Parameters.AddWithValue( |
|
“@Name”, item.Name); |
|
cmd.Parameters.AddWithValue( |
|
“@Price”, item.Price); |
|
cmd.Parameters.AddWithValue( |
|
“@Quantity”, item.Quantity); |
|
cmd.ExecuteNonQuery(); |
|
} |
|
}
The following list spells out the most important details of this class:
1 The C# version of the OrderDB class is defined with the static keyword. That simply means that the class can’t contain any instance properties or members. Instead, all methods and properties must be declared as static. That’s a new feature of C# for ASP.NET 2.0. Visual Basic doesn’t have this feature, which is why the Shared keyword doesn’t appear on the class declaration for
216 Part III: Building E-Commerce Applications
the VB version of the OrderDB class. (This class uses static methods so that the application doesn’t have to create an instance of the class to use its methods for database access.)
2 A pair of static (Shared in VB) variables are used to store the
SqlTransaction and SqlConnection objects used by the WriteOrder method. The SqlTransaction object is used to place all of the updates performed by the WriteOrder method in a safety net so that if any of the updates fail, any updates performed up to that point are reversed. And the SqlConnection object provides a connection to the database.
3 The WriteOrder method is the only public method provided by the
OrderDB class. It begins by using the WebConfigurationManager class to retrieve the database connection string from web.config. Then it creates and opens a connection and obtains a transaction that can be used to coordinate the updates.
Next, it calls the InsertCustomer method to insert the customer data into the Customers table, calls the InsertOrder method to insert a row into the Orders table, and uses a for each loop to call the InsertItem method once for each item in the order’s shopping cart. Notice that the InsertOrder method returns the order number generated for the order. This value is then passed to the InsertItem method so the order items will be associated with the correct order.
After all of the data has been inserted, the Commit method is called on the transaction object to commit the updates, the connection is closed, and the method returns with a return value of true to indicate that the data was written successfully.
If an exception occurs during any of the database updates, however, the exception will be caught by the Catch statement. Then the Rollback method of the transaction is called to reverse any updates that were previously made. Then the WriteOrder method returns false so the caller knows the order was not successfully written.
4 The InsertCustomer method inserts or updates the customer data in the Customers table. It begins by issuing the following SQL statement to attempt to insert the customer data:
INSERT INTO Customers (lastname, firstname,
address, city, state, zipcode, phone, email)
VALUES(@LastName, @FirstName,
@Address, @City, @State, @ZipCode, @PhoneNumber, @Email)