Edit or 's N ot e : Th is a r t icle ' s code h a s be e n u pda t e d t o w or k w it h t h e fin a l r e le a se of t h e .N e t fr a m e w or k .
As w eb developers w e are required t o face a w ide variet y of applicat ion needs. Each w eb sit e developed is unique and furnished according t o each client 's specific needs. The fact is t hat w ebsit es are indeed fabricat ed for each client w it h different specificat ions but every sit e shares som e com m on charact erist ics. Those part s of t he sit e t hat share funct ionalit y feat ures can be t reat ed as separat e applicat ions t o be reused.
I n t his case w e w ill address t he developm ent cycle for one of t he com m on blocks in t oday's w ebsit es - an Online Shopping Cart .
We w ill analyze t he developm ent of a shopping cart as a group of com ponent s described clearly before w e im plem ent t hem , t hus allow ing us t o use t his know ledge in areas ot her t han ASP.NET. Aft er a descript ion of each com ponent t he im plem ent at ion w ill be explained using C# .
The applicat ion w ill be designed t o w ork w it h a SQLServer dat abase for st orage. Applicat ion logic w ill be done w it hin t he Web Form and present ed t o t he user t hrough t he w eb brow ser. Core logic w ill reside in a separat e C#
CATEGORY: Applicat ion Developm ent
ARTI CLE TYPE: Tut orial Reader Com m ent s I n t his art icle Juan Mart ínez discusses and im plem ent s t he building blocks of an online shopping cart -
covering in t his part it em cat alogs, it em det ails, a cart and a checkout syst em . This act s as t he foundat ion for fur t her ar t icles, w here Juan covers ot her funct ionalit y like adm inist rat ion pages and set t ing up credit card paym ent s.
Art icle Discussion Rat e t his ar t icle Relat ed Links I ndex Ent ries
Aft er t hese st eps w e w ill have a clear pat h of developm ent and be ready t o im plem ent our online shopping cart in t he C# language.
D iggin g in t h e On lin e Sh oppin g Ca r t M ode l
We w ill first t ake a look at a sim plified diagram of an Online Shopping Cart . These are t he funct ionalit y blocks t o be discussed.
We t hen have four basic m odules:
z I t e m Ca t a log - Her e w e display t he opt ions t o our client s in an or ganized w ay.
z I t e m D e t a ils - Here w e show t he client as m uch info as w e can t o show off our product .
z Sh oppin g Ca r t - Here we m anage t he user's select ed it em s.
z Ch e ck ou t Sy st e m - Her e w e save t he it em s select ed and t he client 's infor m at ion t o close t he t ransact ion.
These are t he basic blocks t o be im plem ent ed in our online st ore. I t includes t he indispensable funct ionalit y t hat w ill be described in det ail lat er. These blocks could be enriched furt her w it h m ore feat ures, w hich w ill be covered in lat er art icles.
D e fin in g r e qu ir e m e n t s
As in every soft w are developm ent cycle, w e need t o define our requirem ent s first so w e can design soft w are capable of giving sat isfact ion t o our cust om ers.
Our online shopping cart applicat ion should do t he follow ing:
z Have a list of cat egories and subcat egories.
z I t em s should be ar r anged in it s corresponding subcat egory.
z I t em s could be select ed for cat egory and hom e prom ot ion.
z Each product should have an id, nam e, shor t and long descript ions, sm all and lar ge im ages, st ock and price.
z Users should be able t o add product s t o t he basket and rem ove t hem .
z The user should be given an order num ber and w ill be able t o t rack it t hrough an order t racking syst em .
From our requir em ent s w e define t he dat abase schem a. The t ables ar e show n as a concept ual m odel, w it h all t ables used in t his version of t he shopping cart .
The t ables ar e gr ouped as follow s:
z Green - The cat alog part of our applicat ion.
z Sky blue - I t em det ails.
z Orange - Shopping cart basket .
z Yellow - The checkout syst em .
Ca t a log Se ct ion
sect ion/ subsect ion approach. As t his approach will work in m ost cases, you could im prove t his t o a com plet ely flexible design using r ecur sive sect ions, which will inherit a parent I d.
I t e m D e t a ils
The it em det ails part of our m odel is a t rim m ed down version of an it em det ails design. We have only one t able in which we save t he vit al inform at ion of t he it e m such as descript ion, price and im ages. We have a couple of Boolean values t hat are used t o specify if t he it em should be displayed as a hom e or sect ion it em .
Sh oppin g ca r t ba sk e t
The shopping basket is a sim ple t able t hat is used t em por ar ily t o st or e t he it em s select ed by t he user . We j ust save t he se ssion I d, t he it e m id and t he qu a n t it y. We will im plem ent t his as an in - m e m or y da t a t a ble and hold our select ed it em s in a session var iable. This t able is show n t o show you're t he inform at ion t hat needs t o be ret ained during our session.
Ch e ck ou t syst e m
This is t he m ost com plicat ed par t or our syst em . Upon checkout w e creat e an order I d in t he order t able. Then t he it em s st ored in t he shopping basket are t ransferred and saved in our order I t em s t able. The user inform at ion is st or ed in t he order det ails t able. These t w o t ables inher it t he order I d. We have a fourt h t able which also inherit s t he order I d. This is t he order Progress t able and it is used for order t racking. As progress is done, t he online shop adm inist rat or should add a record t o t his t able indicat ing t he progress done t o dat e. This is t hen checked by t he buyer.
Le t t h e codin g be gin
As our design basis is done, w e are all set t o st art our coding. The archit ect ure will be based on sim ple Web Form s calling cust om User Cont rols. Core logic w ill be done in separat e com ponent s using t he code behind t echnique.
Applica t ion fr a m e w or k
We st art by set t ing our basic fram ew ork. We m ake use of our
web.config
file t o save im port ant applicat ion inform at ion such as our connect ion st ring. This is how our configurat ion file will look:<configuration>
<appSettings>
<add key="connString" value="server=(local)\NetSDK;database=ShoppingCart;Trusted_Con
</appSettings>
</configuration>
To r et rieve t his inform at ion w e use t he follow ing code snippet .
String connString = ConfigurationSettings.AppSettings["connString"];
As you can see, t his is a very easy and convenient w ay t o st ore applicat ion w ise dat a.
Ca t e gor y List Block
All being set , w e have our first t ask w hich is t o display a list of pr oduct s w hich w ill be filt ered by sect ion and subsect ion if select ed.
The first t ask is t o set up t he w orkspace of our Web Form s. We set up our language and add t he appropriat e nam espaces for our code t o w ork.. We set C# as our language and im port t he
System
nam espace for general purposes. We t hen add t heSystem.Data
andSystem.Data.OleDb
since w e w ill be using SQLSer ver as our dat abase engine. We should set t he debug flag t o false once w e deliver t his applicat ion t o t he real w orld.<%@ Page Language="C#" Debug="true" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient " %>
<%@ Register TagPrefix="SC" TagName="Site" Src="uc_header.ascx" %>
cont rol,uc_catalog_section.ascx
w hich displays t he list of sect ions available on t he sit e. This is done by binding a dat a ret rieval codebehind class t o t he user cont rol.This is our User Cont rol Code:
<%@ Control Language="C#" Debug="true" Inherits="CodeBehind.UcSection" %>
<%@ Import Namespace="System.Data" %>
<html>
<head>
<title></title>
<script language="C#" runat="server"></script>
</head>
<body>
<font face="Verdana" size="-1">
<asp:DataList id="MySectionList" runat="server"
BorderColor="black"
<a href="catalog.aspx?sectionId=<%# DataBinder.Eval(Container.DataItem,"ca
§ionIndex=<%#Cont
inform at ion. The<%# DataBinder.Eval(Container.DataItem, "catalogSectionName") %>
code is used t o select specific inform at ion from t he bound dat a and put it in place.protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
Bind_MySectionList();
}
if (Request.QueryString["sectionIndex"] != null) {
MySectionList.SelectedIndex = Int32.Parse(Request.QueryString["sectionIndex"]);
}
}
protected void Bind_MySectionList() {
String connString = ConfigurationSettings.AppSettings["connString"];
SqlConnection myConnection = new SqlConnection(connString);
SqlDataAdapter myCommand = new SqlDataAdapter("SELECT catalogSectionId, catalogSecti
FROM catalogSection ORDER BY catalogSectionName", myConnec
DataSet ds = new DataSet();
MySectionList.DataSource = new DataView(ds.Tables[0]);
MySectionList.DataBind();
}
}
We t hen have t o im plem ent our su bse ct ion u se r con t r ol. This cont rol w ill do a sim ilar t ask t o t he sect ion cont rol. We w ill j ust add a filt er t o t he Query applied t o t he dat abase. We will select subsect ions corresponding t o t he select ed sect ion. The rest is pret t y m uch t he sam e.
"SELECT catalogSubSectionId, catalogSubSectionName FROM catalogSubSection WHERE catalogS
sectionId + " ORDER BY catalogSub
We t hen need t o display our product list . We have t hr ee t ypes of pr oduct s:
z Sit e Product s: These are shown if no sect ion is select ed
z Sect ion Product s: These are shown if a sect ion is select ed but no subsect ion is select ed.
z Nor m al Product s: These ar e product s t hat belong t o t he select ed subsect ion.
We need t o filt er t he t hree possibilit ies and creat e t he proper query. This is done in t he
UcProductList
class w it h t his code. Aft er w e have our query w e bind it t o a Dat aGr id Web Cont rol t o display t he it em s in a t able arrangem ent .string SQLQuery = "SELECT itemId, itemName, itemShortDescription, itemSmallImage, itemPr
FROM item WHERE itemPromoteSite=1 ORDER
int mysectionId = 0;
if (Request.QueryString["sectionId"] != null) {
mysectionId = Int32.Parse(Request.QueryString["sectionId"]);
}
if (mysectionId != 0) {
//If we have a section selected we filter products for this section
SQLQuery = "SELECT item.itemId, item.itemName, item.itemShortDescription, item.itemSma
FROM (catalogSection INNER JOIN catalogSubSection ON catalogSection.catalogSectionI
INNER JOIN item ON catalogSubSection.catalog
WHERE (((catalogSection.catalogSectionId)=" + mysectionId + "
}
int mysubsectionId = 0;
if (Request.QueryString["subsectionId"] != null) {
mysubsectionId = Int32.Parse(Request.QueryString["subsectionId"]);
}
if (mysubsectionId != 0) {
//If we have a subsection selected we filter products for this subsection
SQLQuery = "SELECT itemId, itemName, itemShortDescription, itemSmallImage, itemPrice,
WHERE catalogSubSectionId=" + mysubsectionId + " ORDER BY itemName";
}
This concludes our cat alog present at ion layer which consist s of four m ain user cont rols.
z The first cont rol is responsible for displaying a list of sect ions.
z The second cont rol is responsible for t he subsect ion list .
z The t hird cont rol is responsible for displaying a grid of it em s. This list of it em s is ret rieved from one of t hree sql queries depending on t he sit uat ion.
z A final cont rol renders t he t op of t he page.
All t he cont r ols w or k t oget her t o for m
catalog.aspx
. The user cont r ols m ake use of codebehind classes for dat abase access and bind t he Dat aList s in our page.I t e m D e t a ils
Our next st ep in building our shopping cart is t o show off t he it em det ails. We first w ill use som e of t he code done for t he cat alog present at ion before. We w ill t ake t he basic ht m l fram ew ork and t hree user cont rols. We will reuse t he header, sect ion and subsect ion cont r ol.
The difference here w ill be t o replace t he it e m list cont rol w it h a ne w it e m de t a ils cont r ol. We w ill use a dat a list Web Cont rol t o display t he it em s charact erist ics as well as it s cor r esponding class in our code behind reposit ory.
The code t o do t his sim ple t ask is as follow s for t he user cont r ol:
<%@ Control Language="C#" Debug="true" Inherits="CodeBehind.UcItemDetails" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script language="C#" runat="server"></script>
<font face="Verdana" size="-1">
<asp:DataList id="MyItemDetails" runat="server"
BorderColor="black"
BorderWidth="1"
GridLines="Both"
CellPadding="3"
Font-Name="Verdana"
Font-Size="8pt"
Width="600px"
HeaderStyle-BackColor="#aaaadd"
SelectedItemStyle-BackColor="Gainsboro"
RepeatDirection = "Horizontal"
>
<ItemTemplate>
<table>
<tr>
<td valign="top">
<img src="images/<%# DataBinder.Eval(Container.DataItem, "itemLargeImage") %>" wid
</td>
<td valign="top">
<span class="itemTitle"><%# DataBinder.Eval(Container.DataItem, "itemName") %></sp
<br>
<span class="itemText"><%# DataBinder.Eval(Container.DataItem, "itemLongDescriptio
<br><br>
<span class="itemText">Price: <%# (DataBinder.Eval(Container.DataItem, "itemPrice"
<br>
<span class="itemText">Stock: <%# DataBinder.Eval(Container.DataItem, "itemStock")
<br><br>
<a href="catalog.aspx?sectionId=<%=sectionId%>§ionIndex=<%=sectionIndex%>&subs
&subsectionIndex=<%=subsectionIndex
<span class="itemText"> | </span>
<a href="cart.aspx?cartAction=1&itemId=<%# DataBinder.Eval(Container.DataItem, "it
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
</font>
And our code behind class:
protected void Bind_ItemDetails() {
int myItemId = 0;
if (Request.QueryString["itemId"] != null) {
myItemId = Int32.Parse(Request.QueryString["itemId"]);
}
string SQLQuery = "SELECT itemId, itemName, itemLongDescription, itemLargeImage, itemP
FROM item WHERE itemId
String connString = ConfigurationSettings.AppSettings["connString"];
SqlConnection myConnection = new SqlConnection(connString);
SqlDataAdapter myCommand = new SqlDataAdapter(SQLQuery, myConnection);
DataSet ds = new DataSet();
myCommand.Fill(ds, "item");
MyItemDetails.DataSource = new DataView(ds.Tables[0]);
MyItemDetails.DataBind();
}
Furt her enhancem ent s can be done t o t his sim ple m odule. This form show s t he st ored det ails of t he it em and can be enriched w it h user review s and r elat ed it em list s.
Sh oppin g ca r t ba sk e t
The shopping cart basket im plem ent s t he m aj orit y of t he funct ionalit y. I t should provide w ays t o add, edit and delet e it em s from it . The basket is m erely a t em poral st orage area for t he user t o group t he it em s of int er est . We t hen need som e session m anagem ent t o be able t o r ecognize w hich it em s belong t o each client in it s ow n session.
ASP.NET, as in previous asp applicat ions, provides t he necessary obj ect s t o work wit h sessions. I n t his case we w ill t ake advant age of t he Se ssion obj ect . We will st ore a D a t a Ta ble obj ect as a Session var iable t herefor e all shopping cart basket operat ions ar e done in m em or y. This is a very fast approach but w ill need t o be provided w it h enough m em ory t o handle concurrent client s.
The shopping basket m odule com prises t w o fundam ent al part s. The fir st involves m anaging t he it em s t hat t he user w ant s t o have in t he basket . The second is in charge of displaying t he it em s current ly in t he basket . We w ill see t he det ails now .
We inst ruct our Web Form t o add an it em t o t he cart w it h queryst ring variables. We j ust add an it em t o t he Dat aTable. To im plem ent t he updat e and delet e m et hods w e bind t he Dat aTable t o t he Dat aList Web Cont rol and perform t he operat ions.
void Page_Load(Object Sender, EventArgs E) {
if (Request.QueryString["cartAction"] != null) {
this.cartAction = Int32.Parse(Request.QueryString["cartAction"]);
}
if (Session["ShoppingCart"] == null) {
Cart = new DataTable();
Cart.Columns.Add(new DataColumn("ItemId", typeof(string)));
Cart.Columns.Add(new DataColumn("Item", typeof(string)));
Cart.Columns.Add(new DataColumn("Qty", typeof(string)));
Cart.Columns.Add(new DataColumn("Price", typeof(string)));
Session["ShoppingCart"] = Cart;
Cart = (DataTable)Session["ShoppingCart"];
if (Request.QueryString["cartAction"] != null) {
myCartAction = Int32.Parse(Request.QueryString["cartAction"]);
}
String connString = ConfigurationSettings.AppSettings["connString"];
SqlConnection myConnection = new SqlConnection(connString);
protected void DataCartList_DeleteCommand1(Object Sender, DataListCommandEventArgs e
string item = ((Label)e.Item.FindControl("Label4")).Text;
CartView.RowFilter = "Item='"+item+"'";
protected void DataCartList_EditCommand1(Object Sender, DataListCommandEventArgs e)
CartList.EditItemIndex = (int)e.Item.ItemIndex;
BindCartList();
BindTotalList();
}
protected void DataCartList_CancelCommand1(Object Sender, DataListCommandEventArgs e
CartList.EditItemIndex = -1;
BindCartList();
BindTotalList();
}
protected void DataCartList_UpdateCommand1(Object Sender, DataListCommandEventArgs e
string itemId = ((Label)e.Item.FindControl("Label1")).Text;
string qty = ((TextBox)e.Item.FindControl("Text1")).Text;
string price = ((Label)e.Item.FindControl("Label3")).Text;
DataTable CartTable = (DataTable)Session["ShoppingCart"];
foreach(DataRow myRow in CartTable.Rows) {
Double tempPrice = Double.Parse(myRow[3].ToString());
Int32 tempQty = Int32.Parse(myRow[2].ToString());
mySubTotal += tempPrice * tempQty;
CartTotal.Columns.Add(new DataColumn("SubTotal", typeof(string)));
CartTotal.Columns.Add(new DataColumn("Tax", typeof(string)));
CartTotal.Columns.Add(new DataColumn("Total", typeof(string)));
DataRow drTotal = CartTotal.NewRow();
drTotal[0] = mySubTotal.ToString();
Ch e ck ou t Sy st e m
The checkout syst em has t he responsibilit y of saving t he client info and select ed it em s for processing. We use t hree t ables t o save t he client info. These are t he follow ing:
z order Dat a - St or es t he dat e of t he order and generat es t he order I d.
z orderI t em - List of it em s bought , it also saves t he pr ice at t he t im e of pur chase.
z orderDet ail - Saves shipping and billing inform at ion for t he order.
We divide our process int o t hr ee st eps:
z Shipping and Billing I nform at ion - Here w e get t he shipping inform at ion. Wit h t his info w e can calculat e t he shipping cost s. This should be done accor dingly t o each st or e's necessit ies. We validat e credit car d infor m at ion also. This should be done using a specific provider like paypal.
z Confirm at ion - Her e w e present a sum m ary of t he inform at ion received and show t he list of it em s t o be bought , as w ell as t he grand t ot al of t he order. The user is asked t o subm it t he inform at ion if it is correct .
z Sum m ary - We finish t he t ransact ion and show t he user t he order num ber.
We post t he info from t he first t o t he second st ep. We t hen use Web Form Cont rols t o ask for confirm at ion. I f t he info is correct , t hen w e regist er t he order for our client .
We do need t o im plem ent som e form validat ion before post ing t he infor m at ion and im plem ent som e credit card validat ion t hrough an ext ernal pr ovider or your ow n soft w are.
Tr a ck in g y ou r or de r
The final part of our online shopping car t applicat ion is t he t r acking syst em . We w ill im plem ent a basic t racking syst em w hich w ill ask t he user for t heir em ail and order num ber. The syst em w ill t hen show a list of m ilest ones regist ered in t he t racking dat abase.
This is t he code required:
protected void ButtonView_Click(object Source, EventArgs e) {
//Look for order id with provided email and order number
String connString = ConfigurationSettings.AppSettings["connString"];
string strSelect = "SELECT orderId FROM orderDetail WHERE orderId=" + orderIdBox.Text
AND orderDetailShippingEmail='" + emailBox.Text + "'";
SqlConnection myConnection = new SqlConnection(connString);
SqlCommand myCommand = new SqlCommand(strSelect, myConnection);
myConnection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
int newOrderId = 0;
if (dr.Read()) {
//emailBox.Text = "Encontramos!!!";
Bind_TrackingList();
}
myConnection.Close();
}
protected void Bind_TrackingList() {
string SQLQuery = "SELECT orderProgressText, orderProgressDescription, orderProgressD
WHERE orderId = " + orderIdBox.Text;
String connString = ConfigurationSettings.AppSettings["connString"];
SqlConnection myConnection = new SqlConnection(connString);
SqlDataAdapter myCommand = new SqlDataAdapter(SQLQuery, myConnection);
DataSet ds = new DataSet();
myCommand.Fill(ds, "orderProgress");
MyTrackingList.DataSource = new DataView(ds.Tables[0]);
MyTrackingList.DataBind();
D e ploy m e n t of t h e sit e
Deploym ent of t his part icular applicat ion is ver y sim ple.
z Creat e a ne w da t a ba se in SQLServer online shopping cart . Furt her enhancem ent s can be m ade and w ill be t he responsibilit y of t he reader. These enhancem ent s should be m ade t o enrich t he shopping cart applicat ion give a bet t er ser vice t o t he online com m unit y. Som e ideas are present ed here.
Fe a t u r e im pr ove m e n t s
z Recursive sect ions for n levels of pr ofundit y
z I t em review s
z I t em relat ed it em s
z User account s and m anagem ent
z Mailing list t o cust om ers
z Specific shipping cost s calculat ions
Te ch n ica l im pr ove m e n t s
z Build based on com ponent s for perform ance and possible code reuse
z Migrat e t o SQL Server dat abase using st ored procedures for perform ance
z I m plem ent SSL in your server ( a m ust but out of scope! )
z I m plem ent real t im e credit card processing and charging.
Con clu sion s
The syst em present ed shows t he basis of a working online shopping cart . I t involves t he m ain aspect s of an online st ore which are t he cat alog of it em s, t he it em det ail m odule, t he shopping cart basket and t he checkout m odule. Every shopping car t online t oday m ust im plem ent t hese basic part s t o be funct ional. Hopefully t his ar t icle has given you t he know ledge t o build your own w it h ease and t o add new funct ionalit y t o m eet your needs as ideas for im provem ent have been given.
I n fut ure art icles, w e w ill cover som e of t he im port ant requirem ent s of a real - w orld shopping cart t hat have been
z See ot her art icles in t he Applicat ion Develo
z See ot her Tut orial art icles
z Reader Com m ent s on t his ar t icle
z Go t o Previous Art icle
( Opt ion a l)
ht t p: / / w ww.sybase.com / product s/ ent erprisem odeling/ pow erdesigner
z Pay Pal: w w w .paypal.com
Ecom m erce Perform ance Securit y Sit e Design XML SO
Dat a Access/ ADO.NET Applicat ion
Developm ent Web Services Graphics/ Gam es Mobile Ot her Technologies
C# Today is brought t o you by Wrox Press (w w w .w rox.com) . Please see our t erm s and condit ions and privacy C# Today is opt im ised for Microsoft I nt ernet Explorer 5 brow sers.