Část 7: Přidání funkcí
Tailspin Spyworks ukazuje, jak je mimořádně jednoduché vytvářet výkonné a škálovatelné aplikace pro platformu .NET. Ukazuje, jak používat skvělé nové funkce v ASP.NET 4 k vytvoření online obchodu, včetně nakupování, pokladny a správy.
Tato série kurzů podrobně popisuje všechny kroky k sestavení ukázkové aplikace Tailspin Spyworks. Část 7 přidává další funkce, jako je kontrola účtu, recenze produktů a "oblíbené položky" a "také zakoupené" uživatelské ovládací prvky.
Přidání funkcí
I když uživatelé můžou procházet náš katalog, umísťovat položky do nákupního košíku a dokončit proces placení, máme k dispozici řadu podpůrných funkcí, které zahrneme ke zlepšení našeho webu.
- Kontrola účtu (výpis zadaných objednávek a zobrazení podrobností))
- Přidejte na úvodní stránku nějaký kontextový obsah.
- Přidejte funkci, která uživatelům umožní zkontrolovat produkty v katalogu.
- Vytvořte uživatelský ovládací prvek, který zobrazí oblíbené položky a umístí tento ovládací prvek na přední stránku.
- Vytvořte uživatelský ovládací prvek "Také zakoupeno" a přidejte ho na stránku s podrobnostmi o produktu.
- Přidejte stránku kontaktu.
- Přidejte stránku O aplikaci.
- Globální chyba
Kontrola účtu
Ve složce "Účet" vytvořte dvě stránky .aspx, jednu s názvem OrderList.aspx a druhou s názvem OrderDetails.aspx.
OrderList.aspx bude využívat ovládací prvky GridView a EntityDataSource stejně jako dříve.
<div class="ContentHead">Order History</div><br />
<asp:GridView ID="GridView_OrderList" runat="server" AllowPaging="True"
ForeColor="#333333" GridLines="None" CellPadding="4" Width="100%"
AutoGenerateColumns="False" DataKeyNames="OrderID"
DataSourceID="EDS_Orders" AllowSorting="True" ViewStateMode="Disabled" >
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:BoundField DataField="OrderID" HeaderText="OrderID" ReadOnly="True"
SortExpression="OrderID" />
<asp:BoundField DataField="CustomerName" HeaderText="Customer"
SortExpression="CustomerName" />
<asp:BoundField DataField="OrderDate" HeaderText="Order Date"
SortExpression="OrderDate" />
<asp:BoundField DataField="ShipDate" HeaderText="Ship Date"
SortExpression="ShipDate" />
<asp:HyperLinkField HeaderText="Show Details" Text="Show Details"
DataNavigateUrlFields="OrderID"
DataNavigateUrlFormatString="~/Account/OrderDetails.aspx?OrderID={0}" />
</Columns>
<FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
<RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
<SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />
<SortedAscendingCellStyle BackColor="#FDF5AC" />
<SortedAscendingHeaderStyle BackColor="#4D0000" />
<SortedDescendingCellStyle BackColor="#FCF6C0" />
<SortedDescendingHeaderStyle BackColor="#820000" />
<SortedAscendingCellStyle BackColor="#FDF5AC"></SortedAscendingCellStyle>
<SortedAscendingHeaderStyle BackColor="#4D0000"></SortedAscendingHeaderStyle>
<SortedDescendingCellStyle BackColor="#FCF6C0"></SortedDescendingCellStyle>
<SortedDescendingHeaderStyle BackColor="#820000"></SortedDescendingHeaderStyle>
</asp:GridView>
<asp:EntityDataSource ID="EDS_Orders" runat="server" EnableFlattening="False"
AutoGenerateWhereClause="True"
Where=""
OrderBy="it.OrderDate DESC"
ConnectionString="name=CommerceEntities"
DefaultContainerName="CommerceEntities"
EntitySetName="Orders" >
<WhereParameters>
<asp:SessionParameter Name="CustomerName" SessionField="UserName" />
</WhereParameters>
</asp:EntityDataSource>
EntityDataSource vybere záznamy z tabulky Orders filtrované na UserName (viz WhereParameter), které jsme nastavili v proměnné relace, když se uživatel přihlásí.
Všimněte si také těchto parametrů v Poli hypertextových odkazů objektu GridView:
DataNavigateUrlFields="OrderID" DataNavigateUrlFormatString="~/Account/OrderDetails.aspx?OrderID={0}"
Ty určují odkaz na zobrazení Podrobnosti objednávky pro každý produkt a určují pole OrderID jako parametr QueryString stránky OrderDetails.aspx.
OrderDetails.aspx
Použijeme ovládací prvek EntityDataSource pro přístup k Objednávce a FormView k zobrazení dat Objednávky a další EntityDataSource s GridView k zobrazení všech řádkových položek objednávky.
<asp:FormView ID="FormView1" runat="server" CellPadding="4"
DataKeyNames="OrderID"
DataSourceID="EDS_Order" ForeColor="#333333" Width="250px">
<FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<ItemTemplate>
OrderID : <%# Eval("OrderID") %><br />
CustomerName : <%# Eval("CustomerName") %><br />
Order Date : <%# Eval("OrderDate") %><br />
Ship Date : <%# Eval("ShipDate") %><br />
</ItemTemplate>
<PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
<RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
</asp:FormView>
<asp:EntityDataSource ID="EDS_Order" runat="server" EnableFlattening="False"
ConnectionString="name=CommerceEntities"
DefaultContainerName="CommerceEntities"
EntitySetName="Orders"
AutoGenerateWhereClause="True"
Where=""
EntityTypeFilter="" Select="">
<WhereParameters>
<asp:QueryStringParameter Name="OrderID" QueryStringField="OrderID" Type="Int32" />
</WhereParameters>
</asp:EntityDataSource>
<asp:GridView ID="GridView_OrderDetails" runat="server"
AutoGenerateColumns="False"
DataKeyNames="ProductID,UnitCost,Quantity"
DataSourceID="EDS_OrderDetails"
CellPadding="4" GridLines="Vertical" CssClass="CartListItem"
onrowdatabound="MyList_RowDataBound" ShowFooter="True"
ViewStateMode="Disabled">
<AlternatingRowStyle CssClass="CartListItemAlt" />
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="Product ID" ReadOnly="True"
SortExpression="ProductID" />
<asp:BoundField DataField="ModelNumber" HeaderText="Model Number"
SortExpression="ModelNumber" />
<asp:BoundField DataField="ModelName" HeaderText="Model Name"
SortExpression="ModelName" />
<asp:BoundField DataField="UnitCost" HeaderText="Unit Cost" ReadOnly="True"
SortExpression="UnitCost" DataFormatString="{0:c}" />
<asp:BoundField DataField="Quantity" HeaderText="Quantity" ReadOnly="True"
SortExpression="Quantity" />
<asp:TemplateField>
<HeaderTemplate>Item Total</HeaderTemplate>
<ItemTemplate>
<%# (Convert.ToDouble(Eval("Quantity")) * Convert.ToDouble(Eval("UnitCost")))%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle CssClass="CartListFooter"/>
<HeaderStyle CssClass="CartListHead" />
</asp:GridView>
<asp:EntityDataSource ID="EDS_OrderDetails" runat="server"
ConnectionString="name=CommerceEntities"
DefaultContainerName="CommerceEntities"
EnableFlattening="False"
EntitySetName="VewOrderDetails"
AutoGenerateWhereClause="True"
Where="">
<WhereParameters>
<asp:QueryStringParameter Name="OrderID" QueryStringField="OrderID" Type="Int32" />
</WhereParameters>
</asp:EntityDataSource>
V souboru Code Behind (OrderDetails.aspx.cs) máme dvě malé části úklidu.
Nejprve se musíme ujistit, že OrderDetails vždy dostane OrderId.
protected void Page_Load(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(Request.QueryString["OrderId"]))
{
Response.Redirect("~/Account/OrderList.aspx");
}
}
Musíme také vypočítat a zobrazit celkový počet objednávek z řádkových položek.
decimal _CartTotal = 0;
protected void MyList_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TailspinSpyworks.Data_Access.VewOrderDetail myCart = new
Data_Access.VewOrderDetail();
myCart = (TailspinSpyworks.Data_Access.VewOrderDetail)e.Row.DataItem;
_CartTotal += Convert.ToDecimal(myCart.UnitCost * myCart.Quantity);
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[5].Text = "Total: " + _CartTotal.ToString("C");
}
}
Domovská stránka
Pojďme na stránku Default.aspx přidat statický obsah.
Nejprve vytvořím složku "Obsah" a v ní složku Images (a přiložím obrázek, který se má použít na domovské stránce).
Do dolního zástupného symbolu stránky Default.aspx přidejte následující kód.
<h2>
<asp:LoginView ID="LoginView_VisitorGreeting" runat="server">
<AnonymousTemplate>
Welcome to the Store !
</AnonymousTemplate>
<LoggedInTemplate>
Hi <asp:LoginName ID="LoginName_Welcome" runat="server" />. Thanks for coming back.
</LoggedInTemplate>
</asp:LoginView>
</h2>
<p><strong>TailSpin Spyworks</strong> demonstrates how extraordinarily simple it is to create powerful, scalable applications for the .NET platform. </p>
<table>
<tr>
<td>
<h3>Some Implementation Features.</h3>
<ul>
<li><a href="#">CSS Based Design.</a></li>
<li><a href="#">Data Access via Linq to Entities.</a></li>
<li><a href="#">MasterPage driven design.</a></li>
<li><a href="#">Modern ASP.NET Controls User.</a></li>
<li><a href="#">Integrated Ajac Control Toolkit Editor.</a></li>
</ul>
</td>
<td>
<img src="Content/Images/SampleProductImage.gif" alt=""/>
</td>
</tr>
</table>
<table>
<tr>
<td colspan="2"><hr /></td>
</tr>
<tr>
<td>
<!-- Popular Items -->
</td>
<td>
<center><h3>Ecommerce the .NET 4 Way</h3></center>
<blockquote>
<p>
ASP.NET offers web developers the benefit of more that a decade of innovation.
This demo leverages many of the latest features of ASP.NET development to
illustrate really simply building rich web applications with ASP.NET can be.
For more information about build web applications with ASP.NET please visit the
community web site at www.asp.net
</p>
</blockquote>
</td>
</tr>
</table>
<h3>Spyworks Event Calendar</h3>
<table>
<tr class="rowH">
<th>Date</th>
<th>Title</th>
<th>Description</th>
</tr>
<tr class="rowA">
<td>June 01, 2011</td>
<td>Sed vestibulum blandit</td>
<td>
Come and check out demos of all the newest Tailspin Spyworks products and experience
them hands on.
</td>
</tr>
<tr class="rowB">
<td>November 28, 2011</td>
<td>Spyworks Product Demo</td>
<td>
Come and check out demos of all the newest Tailspin Spyworks products and experience
them hands on.
</td>
</tr>
<tr class="rowA">
<td>November 23, 2011</td>
<td>Spyworks Product Demo</td>
<td>
Come and check out demos of all the newest Tailspin Spyworks products and experience
them hands on.
</td>
</tr>
<tr class="rowB">
<td>November 21, 2011</td>
<td>Spyworks Product Demo</td>
<td>
Come and check out demos of all the newest Tailspin Spyworks products and experience
them hands on.
</td>
</tr>
</table>
Recenze produktů
Nejprve přidáme tlačítko s odkazem na formulář, který můžeme použít k zadání recenze produktu.
<div class="SubContentHead">Reviews</div><br />
<a id="ReviewList_AddReview" href="ReviewAdd.aspx?productID=<%# Eval("ProductID") %>">
<img id="Img2" runat="server"
src="~/Styles/Images/review_this_product.gif" alt="" />
</a>
Všimněte si, že v řetězci dotazu předáváme ID produktu.
Dále přidáme stránku s názvem ReviewAdd.aspx.
Na této stránce se použije ASP.NET AJAX Control Toolkit. Pokud jste to ještě neudělali, můžete si ho stáhnout z DevExpressu a pokyny k nastavení sady nástrojů pro použití se sadou Visual Studio najdete tady https://www.asp.net/learn/ajax-videos/video-76.aspx.
V režimu návrhu přetáhněte ovládací prvky a validátory ze sady nástrojů a sestavte formulář podobný následujícímu.
Revize bude vypadat nějak takto.
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
</asp:ToolkitScriptManager>
<div class="ContentHead">Add Review - <asp:label id="ModelName" runat="server" /></div>
<div>
<span class="NormalBold">Name</span><br />
<asp:TextBox id="Name" runat="server" Width="400px" /><br />
<asp:RequiredFieldValidator runat="server" id="RequiredFieldValidator1"
ControlToValidate="Name"
Display="Dynamic"
CssClass="ValidationError"
ErrorMessage="'Name' must not be left blank." /><br />
<span class="NormalBold">Email</span><br />
<asp:TextBox id="Email" runat="server" Width="400px" /><br />
<asp:RequiredFieldValidator runat="server" id="RequiredFieldValidator2"
ControlToValidate="Email" Display="Dynamic"
CssClass="ValidationError"
ErrorMessage="'Email' must not be left blank." />
<br /><hr /><br />
<span class="NormalBold">Rating</span><br /><br />
<asp:RadioButtonList ID="Rating" runat="server">
<asp:ListItem value="5" selected="True"
Text='<img src="Styles/Images/reviewrating5.gif" alt=""> (Five Stars) ' />
<asp:ListItem value="4" selected="True"
Text='<img src="Styles/Images/reviewrating4.gif" alt=""> (Four Stars) ' />
<asp:ListItem value="3" selected="True"
Text='<img src="Styles/Images/reviewrating3.gif" alt=""> (Three Stars) ' />
<asp:ListItem value="2" selected="True"
Text='<img src="Styles/Images/reviewrating2.gif" alt=""> (Two Stars) ' />
<asp:ListItem value="1" selected="True"
Text='<img src="Styles/Images/reviewrating1.gif" alt=""> (One Stars) ' />
</asp:RadioButtonList>
<br /><hr /><br />
<span class="NormalBold">Comments</span><br />
<cc1:Editor ID="UserComment" runat="server" />
<asp:RequiredFieldValidator runat="server" id="RequiredFieldValidator3"
ControlToValidate="UserComment" Display="Dynamic"
CssClass="ValidationError"
ErrorMessage="Please enter your comment." /><br /><br />
<asp:ImageButton ImageURL="Styles/Images/submit.gif" runat="server"
id="ReviewAddBtn" onclick="ReviewAddBtn_Click" />
<br /><br /><br />
</div>
Teď, když můžeme zadat recenze, můžeme tyto recenze zobrazit na stránce produktu.
Přidejte tuto značku na stránku ProductDetails.aspx.
<asp:ListView ID="ListView_Comments" runat="server"
DataKeyNames="ReviewID,ProductID,Rating" DataSourceID="EDS_CommentsList">
<ItemTemplate>
<tr>
<td><%# Eval("CustomerName") %></td>
<td>
<img src='Styles/Images/ReviewRating_d<%# Eval("Rating") %>.gif' alt="">
<br />
</td>
<td>
<%# Eval("Comments") %>
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr>
<td><%# Eval("CustomerName") %></td>
<td>
<img src='Styles/Images/ReviewRating_da<%# Eval("Rating") %>.gif' alt="">
<br />
</td>
<td><%# Eval("Comments") %></td>
</tr>
</AlternatingItemTemplate>
<EmptyDataTemplate>
<table runat="server">
<tr><td>There are no reviews yet for this product.</td></tr>
</table>
</EmptyDataTemplate>
<LayoutTemplate>
<table runat="server">
<tr runat="server">
<td runat="server">
<table ID="itemPlaceholderContainer" runat="server" border="1">
<tr runat="server">
<th runat="server">Customer</th>
<th runat="server">Rating</th>
<th runat="server">Comments</th>
</tr>
<tr ID="itemPlaceholder" runat="server"></tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server">
<asp:DataPager ID="DataPager1" runat="server">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button"
ShowFirstPageButton="True"
ShowLastPageButton="True" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
<asp:EntityDataSource ID="EDS_CommentsList" runat="server" EnableFlattening="False"
AutoGenerateWhereClause="True"
EntityTypeFilter=""
Select="" Where=""
ConnectionString="name=CommerceEntities"
DefaultContainerName="CommerceEntities"
EntitySetName="Reviews">
<WhereParameters>
<asp:QueryStringParameter Name="ProductID" QueryStringField="productID"
Type="Int32" />
</WhereParameters>
</asp:EntityDataSource>
Při spuštění naší aplikace a přechodu na produkt se zobrazí informace o produktu včetně recenzí zákazníků.
Ovládací prvek Oblíbené položky (vytváření uživatelských ovládacích prvků)
Abychom zvýšili prodeje na vašem webu, přidáme několik funkcí pro "sugestivní prodej" oblíbených nebo souvisejících produktů.
První z těchto funkcí bude seznam nejoblíbenějších produktů v našem katalogu produktů.
Vytvoříme "Uživatelský ovládací prvek", který zobrazí nejprodávanější položky na domovské stránce naší aplikace. Vzhledem k tomu, že se jedná o ovládací prvek, můžeme ho použít na libovolné stránce jednoduchým přetažením ovládacího prvku v návrháři sady Visual Studio na libovolnou stránku, která se nám líbí.
V průzkumníku řešení sady Visual Studio klikněte pravým tlačítkem na název řešení a vytvořte nový adresář s názvem Controls. I když to není nutné, pomůžeme nám udržet projekt uspořádaný vytvořením všech uživatelských ovládacích prvků v adresáři "Controls".
Klikněte pravým tlačítkem na složku ovládacích prvků a zvolte Nová položka:
Zadejte název našeho ovládacího prvku PopularItems. Všimněte si, že přípona souboru pro uživatelské ovládací prvky je .ascx, nikoli .aspx.
Náš uživatelský ovládací prvek Oblíbené položky bude definován následujícím způsobem.
<%@ OutputCache Duration="3600" VaryByParam="None" %>
<div class="MostPopularHead">Our most popular items this week</div>
<div id="PanelPopularItems" runat="server">
<asp:Repeater ID="RepeaterItemsList" runat="server">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<a class='MostPopularItemText'
href='ProductDetails.aspx?productID=<%# Eval("ProductId") %>'>
<%# Eval("ModelName") %></a><br />
</ItemTemplate>
<FooterTemplate></FooterTemplate>
</asp:Repeater>
</div>
Tady používáme metodu, která se v této aplikaci ještě nepoužila. Používáme ovládací prvek repeater a místo ovládacího prvku zdroje dat vážeme ovládací prvek Repeater s výsledky LINQ to Entities dotazu.
V kódu na pozadí našeho ovládacího prvku to děláme následujícím způsobem.
using TailspinSpyworks.Data_Access;
protected void Page_Load(object sender, EventArgs e)
{
using (CommerceEntities db = new CommerceEntities())
{
try
{
var query = (from ProductOrders in db.OrderDetails
join SelectedProducts in db.Products on ProductOrders.ProductID
equals SelectedProducts.ProductID
group ProductOrders by new
{
ProductId = SelectedProducts.ProductID,
ModelName = SelectedProducts.ModelName
} into grp
select new
{
ModelName = grp.Key.ModelName,
ProductId = grp.Key.ProductId,
Quantity = grp.Sum(o => o.Quantity)
} into orderdgrp where orderdgrp.Quantity > 0
orderby orderdgrp.Quantity descending select orderdgrp).Take(5);
RepeaterItemsList.DataSource = query;
RepeaterItemsList.DataBind();
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Load Popular Items - " +
exp.Message.ToString(), exp);
}
}
}
Všimněte si také tohoto důležitého řádku v horní části značky ovládacího prvku.
<%@ OutputCache Duration="3600" VaryByParam="None" %>
Vzhledem k tomu, že se nejoblíbenější položky nebudou měnit po minutách, můžeme přidat direktivu pro zlepšení výkonu aplikace. Tato direktiva způsobí, že kód ovládacích prvků se spustí pouze v případě, že vyprší platnost výstupu ovládacího prvku uloženého v mezipaměti. V opačném případě se použije verze výstupu ovládacího prvku uložená v mezipaměti.
Teď stačí přidat nový ovládací prvek na stránku Default.aspx.
Přetažením umístěte instanci ovládacího prvku do otevřeného sloupce formuláře Výchozí.
Když teď aplikaci spustíme, zobrazí se na domovské stránce nejoblíbenější položky.
Také zakoupený ovládací prvek (uživatelské ovládací prvky s parametry)
Druhý uživatelský ovládací prvek, který vytvoříme, přesune sugestivní prodej na další úroveň přidáním kontextové specifičnosti.
Logika výpočtu prvních položek "Také zakoupených" je netriviální.
Náš ovládací prvek Také zakoupený vybere záznamy OrderDetails (dříve zakoupené) pro aktuálně vybrané ID produktu a získá ID objednávky pro každou nalezenou jedinečnou objednávku.
Pak vybereme produkty ze všech těchto objednávek a sečteme zakoupené množství. Seřadíme produkty podle tohoto součtu množství a zobrazíme prvních pět položek.
Vzhledem ke složitosti této logiky budeme tento algoritmus implementovat jako uloženou proceduru.
T-SQL pro uloženou proceduru je následující.
ALTER PROCEDURE dbo.SelectPurchasedWithProducts
@ProductID int
AS
SELECT TOP 5
OrderDetails.ProductID,
Products.ModelName,
SUM(OrderDetails.Quantity) as TotalNum
FROM
OrderDetails
INNER JOIN Products ON OrderDetails.ProductID = Products.ProductID
WHERE OrderID IN
(
/* This inner query should retrieve all orders that have contained the productID */
SELECT DISTINCT OrderID
FROM OrderDetails
WHERE ProductID = @ProductID
)
AND OrderDetails.ProductID != @ProductID
GROUP BY OrderDetails.ProductID, Products.ModelName
ORDER BY TotalNum DESC
RETURN
Všimněte si, že tato uložená procedura (SelectPurchasedWithProducts) existovala v databázi, když jsme ji zahrnuli do naší aplikace, a když jsme vygenerovali Model dat entit, zadali jsme, že kromě potřebných tabulek a zobrazení by měl datový model entity obsahovat i tuto uloženou proceduru.
Pokud chcete získat přístup k uložené proceduře z modelu Entity Data Model, musíme funkci importovat.
Poklikáním na model Entity Data Model v Průzkumníku řešení ho otevřete v návrháři a otevřete Prohlížeč modelů. Potom klikněte pravým tlačítkem na návrháře a vyberte Přidat import funkce.
Tím se otevře toto dialogové okno.
Vyplňte pole, jak vidíte výše, vyberte SelectPurchasedWithProducts a jako název importované funkce použijte název procedury.
Klikněte na OK.
Když to uděláme, můžeme jednoduše programovat proti uložené proceduře stejně jako jakoukoli jinou položku v modelu.
Takže v naší složce "Controls" vytvořte nový uživatelský ovládací prvek s názvem AlsoPurchased.ascx.
Značky pro tento ovládací prvek budou pro ovládací prvek PopularItems vypadat velmi povědomě.
<div>
<div class="MostPopularHead">
<asp:Label ID="LabelTitle" runat="server" Text=" Customers who bought this also bought:"></asp:Label></div>
<div id="PanelAlsoBoughtItems" runat="server">
<asp:Repeater ID="RepeaterItemsList" runat="server">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<a class='MostPopularItemText' href='ProductDetails.aspx?productID=<%# Eval("ProductId") %>'><%# Eval("ModelName") %></a><br />
</ItemTemplate>
<FooterTemplate></FooterTemplate>
</asp:Repeater>
</div>
</div>
Rozdíl je v tom, že se výstup neukládají do mezipaměti, protože položky, které se mají vykreslit, se liší podle produktu.
ProductId bude "vlastností" ovládacího prvku.
private int _ProductId;
public int ProductId
{
get { return _ProductId ; }
set { _ProductId = Convert.ToInt32(value); }
}
V obslužné rutině události PreRender ovládacího prvku jsme chtěli udělat tři věci.
- Ujistěte se, že je nastavené ID produktu.
- Podívejte se, jestli nejsou koupené nějaké produkty s aktuálním produktem.
- Vypište některé položky podle 2.
Všimněte si, jak snadné je volat uloženou proceduru prostřednictvím modelu.
//--------------------------------------------------------------------------------------+
protected void Page_PreRender(object sender, EventArgs e)
{
if (_ProductId < 1)
{
// This should never happen but we could expand the use of this control by reducing
// the dependency on the query string by selecting a few RANDOME products here.
Debug.Fail("ERROR : The Also Purchased Control Can not be used without
setting the ProductId.");
throw new Exception("ERROR : It is illegal to load the AlsoPurchased COntrol
without setting a ProductId.");
}
int ProductCount = 0;
using (CommerceEntities db = new CommerceEntities())
{
try
{
var v = db.SelectPurchasedWithProducts(_ProductId);
ProductCount = v.Count();
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Retrieve Also Purchased Items - " +
exp.Message.ToString(), exp);
}
}
if (ProductCount > 0)
{
WriteAlsoPurchased(_ProductId);
}
else
{
WritePopularItems();
}
}
Po zjištění, že jsou "také zakoupeny", můžeme jednoduše svázat opakovač s výsledky vrácenými dotazem.
//-------------------------------------------------------------------------------------+
private void WriteAlsoPurchased(int currentProduct)
{
using (CommerceEntities db = new CommerceEntities())
{
try
{
var v = db.SelectPurchasedWithProducts(currentProduct);
RepeaterItemsList.DataSource = v;
RepeaterItemsList.DataBind();
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Write Also Purchased - " +
exp.Message.ToString(), exp);
}
}
}
Pokud nebyly koupené položky, jednoduše zobrazíme další oblíbené položky z našeho katalogu.
//--------------------------------------------------------------------------------------+
private void WritePopularItems()
{
using (CommerceEntities db = new CommerceEntities())
{
try
{
var query = (from ProductOrders in db.OrderDetails
join SelectedProducts in db.Products on ProductOrders.ProductID
equals SelectedProducts.ProductID
group ProductOrders by new
{
ProductId = SelectedProducts.ProductID,
ModelName = SelectedProducts.ModelName
} into grp
select new
{
ModelName = grp.Key.ModelName,
ProductId = grp.Key.ProductId,
Quantity = grp.Sum(o => o.Quantity)
} into orderdgrp
where orderdgrp.Quantity > 0
orderby orderdgrp.Quantity descending
select orderdgrp).Take(5);
LabelTitle.Text = "Other items you might be interested in: ";
RepeaterItemsList.DataSource = query;
RepeaterItemsList.DataBind();
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Load Popular Items - " +
exp.Message.ToString(), exp);
}
}
}
Chcete-li zobrazit také zakoupené položky, otevřete stránku ProductDetails.aspx a přetáhněte ovládací prvek AlsoPurchased z Průzkumníka řešení tak, aby se zobrazil na této pozici v přirážce.
<table border="0">
<tr>
<td>
<img src='Catalog/Images/<%# Eval("ProductImage") %>' border="0"
alt='<%# Eval("ModelName") %>' />
</td>
<td><%# Eval("Description") %><br /><br /><br />
<uc1:AlsoPurchased ID="AlsoPurchased1" runat="server" />
</td>
</tr>
</table>
Tím se vytvoří odkaz na ovládací prvek v horní části stránky ProductDetails.
<%@ Register src="Controls/AlsoPurchased.ascx" tagname="AlsoPurchased" tagprefix="uc1" %>
Vzhledem k tomu, že uživatelský ovládací prvek AlsoPurchased vyžaduje číslo ProductId, nastavíme vlastnost ProductID našeho ovládacího prvku pomocí příkazu Eval proti aktuální položce datového modelu stránky.
Když teď sestavíme a spustíme a přejdeme k produktu, zobrazí se také zakoupené položky.