Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
di Joe Stagner
Annotazioni
Poiché questo articolo è stato scritto, i provider di appartenenza ASP.NET sono stati sostituiti da ASP.NET Identity. Consigliamo vivamente di aggiornare le app per utilizzare la piattaforma ASP.NET Identity anziché i provider di appartenenza presenti al momento della stesura di questo articolo. ASP.NET Identity offre numerosi vantaggi rispetto al sistema di appartenenza ASP.NET, tra cui :
- Prestazioni migliori
- Estendibilità e testbilità migliorate
- Supporto per OAuth, OpenID Connect e autenticazione a due fattori
- Supporto per le identità basate su attestazioni
- Migliore interoperabilità con ASP.Net Core
Tailspin Spyworks dimostra quanto sia straordinariamente semplice creare applicazioni potenti e scalabili per la piattaforma .NET. Mostra come usare le nuove funzionalità di ASP.NET 4 per creare un negozio online, tra cui shopping, checkout e amministrazione.
Questa serie di esercitazioni illustra in dettaglio tutti i passaggi eseguiti per compilare l'applicazione di esempio Tailspin Spyworks. La parte 6 aggiunge ASP.NET Membership.
Utilizzo dell'appartenenza a ASP.NET
Fare clic su Sicurezza
Assicurarsi di usare l'autenticazione basata su form.
Usare il collegamento "Crea utente" per creare un paio di utenti.
Al termine, fare riferimento alla finestra Esplora soluzioni e aggiornare la visualizzazione.
Si noti che è stato creato il file ASPNETDB.MDF. Questo file contiene le tabelle per supportare i servizi di base ASP.NET come l'appartenenza.
È ora possibile iniziare a implementare il processo di checkout.
Per iniziare, creare una pagina CheckOut.aspx.
La pagina di CheckOut.aspx deve essere disponibile solo per gli utenti che hanno eseguito l'accesso, pertanto si limiterà l'accesso agli utenti connessi e reindirizzerà gli utenti che non hanno eseguito l'accesso alla pagina LogIn.
A tale scopo, aggiungeremo quanto segue alla sezione di configurazione del file web.config.
<location path="Checkout.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
Il modello per ASP.NET applicazioni Web Form ha aggiunto automaticamente una sezione di autenticazione al file web.config e ha stabilito la pagina di accesso predefinita.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
È necessario modificare il file code-behind Login.aspx per eseguire la migrazione di un carrello acquisti anonimo quando l'utente accede. Modificare l'evento Page_Load come indicato di seguito.
using System.Web.Security;
protected void Page_Load(object sender, EventArgs e)
{
// If the user is not submitting their credentials
// save refferer
if (!Page.IsPostBack)
{
if (Page.Request.UrlReferrer != null)
{
Session["LoginReferrer"] = Page.Request.UrlReferrer.ToString();
}
}
// User is logged in so log them out.
if (User.Identity.IsAuthenticated)
{
FormsAuthentication.SignOut();
Response.Redirect("~/");
}
}
Aggiungere quindi un gestore eventi "LoggedIn" come questo per impostare il nome della sessione sull'utente appena connesso e modificare l'ID sessione temporaneo nel carrello acquisti in quello dell'utente chiamando il metodo MigrateCart nella classe MyShoppingCart. (Implementato nel file .cs)
protected void LoginUser_LoggedIn(object sender, EventArgs e)
{
MyShoppingCart usersShoppingCart = new MyShoppingCart();
String cartId = usersShoppingCart.GetShoppingCartId();
usersShoppingCart.MigrateCart(cartId, LoginUser.UserName);
if(Session["LoginReferrer"] != null)
{
Response.Redirect(Session["LoginReferrer"].ToString());
}
Session["UserName"] = LoginUser.UserName;
}
Implementare il metodo MigrateCart() in questo modo.
//--------------------------------------------------------------------------------------+
public void MigrateCart(String oldCartId, String UserName)
{
using (CommerceEntities db = new CommerceEntities())
{
try
{
var myShoppingCart = from cart in db.ShoppingCarts
where cart.CartID == oldCartId
select cart;
foreach (ShoppingCart item in myShoppingCart)
{
item.CartID = UserName;
}
db.SaveChanges();
Session[CartId] = UserName;
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Migrate Shopping Cart - " +
exp.Message.ToString(), exp);
}
}
}
In checkout.aspx utilizzeremo EntityDataSource e GridView nella nostra pagina di checkout, proprio come abbiamo fatto nella pagina del carrello acquisti.
<div id="CheckOutHeader" runat="server" class="ContentHead">
Review and Submit Your Order
</div>
<span id="Message" runat="server"><br />
<asp:Label ID="LabelCartHeader" runat="server"
Text="Please check all the information below to be sure it's correct.">
</asp:Label>
</span><br />
<asp:GridView ID="MyList" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID,UnitCost,Quantity"
DataSourceID="EDS_Cart"
CellPadding="4" GridLines="Vertical" CssClass="CartListItem"
onrowdatabound="MyList_RowDataBound" ShowFooter="True">
<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>
<br />
<asp:imagebutton id="CheckoutBtn" runat="server" ImageURL="Styles/Images/submit.gif"
onclick="CheckoutBtn_Click">
</asp:imagebutton>
<asp:EntityDataSource ID="EDS_Cart" runat="server"
ConnectionString="name=CommerceEntities"
DefaultContainerName="CommerceEntities"
EnableFlattening="False"
EnableUpdate="True"
EntitySetName="ViewCarts"
AutoGenerateWhereClause="True"
EntityTypeFilter=""
Select="" Where="">
<WhereParameters>
<asp:SessionParameter Name="CartID" DefaultValue="0"
SessionField="TailSpinSpyWorks_CartID" />
</WhereParameters>
</asp:EntityDataSource>
Si noti che il controllo GridView specifica un gestore eventi "ondatabound" denominato MyList_RowDataBound quindi implementare tale gestore eventi in questo modo.
decimal _CartTotal = 0;
//--------------------------------------------------------------------------------------+
protected void MyList_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TailspinSpyworks.Data_Access.ViewCart myCart = new Data_Access.ViewCart();
myCart = (TailspinSpyworks.Data_Access.ViewCart)e.Row.DataItem;
_CartTotal += myCart.UnitCost * myCart.Quantity;
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
if (_CartTotal > 0)
{
CheckOutHeader.InnerText = "Review and Submit Your Order";
LabelCartHeader.Text = "Please check all the information below to be sure
it's correct.";
CheckoutBtn.Visible = true;
e.Row.Cells[5].Text = "Total: " + _CartTotal.ToString("C");
}
}
}
Questo metodo mantiene un calcolo progressivo del totale del carrello acquisti man mano che ogni riga viene associata e aggiorna l'ultima riga del GridView.
In questa fase è stata realizzata una presentazione di "revisione" dell'ordine da effettuare.
Gestire uno scenario di carrello vuoto aggiungendo alcune righe di codice all'evento Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
CheckOutHeader.InnerText = "Your Shopping Cart is Empty";
LabelCartHeader.Text = "";
CheckoutBtn.Visible = false;
}
Quando l'utente fa clic sul pulsante "Invia" verrà eseguito il codice seguente nel gestore eventi Submit Button Click.
protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e)
{
MyShoppingCart usersShoppingCart = new MyShoppingCart();
if (usersShoppingCart.SubmitOrder(User.Identity.Name) == true)
{
CheckOutHeader.InnerText = "Thank You - Your Order is Complete.";
Message.Visible = false;
CheckoutBtn.Visible = false;
}
else
{
CheckOutHeader.InnerText = "Order Submission Failed - Please try again. ";
}
}
Il nocciolo del processo di invio dell'ordine deve essere implementato nel metodo SubmitOrder() della classe MyShoppingCart.
SubmitOrder procederà a:
- Prendere tutti gli articoli del carrello della spesa e usarli per creare un nuovo record di ordine e i dettagli dell'ordine associati.
- Calcolare la data di spedizione.
- Cancellare il carrello acquisti.
//--------------------------------------------------------------------------------------+
public bool SubmitOrder(string UserName)
{
using (CommerceEntities db = new CommerceEntities())
{
try
{
//------------------------------------------------------------------------+
// Add New Order Record |
//------------------------------------------------------------------------+
Order newOrder = new Order();
newOrder.CustomerName = UserName;
newOrder.OrderDate = DateTime.Now;
newOrder.ShipDate = CalculateShipDate();
db.Orders.AddObject(newOrder);
db.SaveChanges();
//------------------------------------------------------------------------+
// Create a new OderDetail Record for each item in the Shopping Cart |
//------------------------------------------------------------------------+
String cartId = GetShoppingCartId();
var myCart = (from c in db.ViewCarts where c.CartID == cartId select c);
foreach (ViewCart item in myCart)
{
int i = 0;
if (i < 1)
{
OrderDetail od = new OrderDetail();
od.OrderID = newOrder.OrderID;
od.ProductID = item.ProductID;
od.Quantity = item.Quantity;
od.UnitCost = item.UnitCost;
db.OrderDetails.AddObject(od);
i++;
}
var myItem = (from c in db.ShoppingCarts where c.CartID == item.CartID &&
c.ProductID == item.ProductID select c).FirstOrDefault();
if (myItem != null)
{
db.DeleteObject(myItem);
}
}
db.SaveChanges();
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Submit Order - " + exp.Message.ToString(),
exp);
}
}
return(true);
}
Ai fini di questa applicazione di esempio, verrà calcolata una data di spedizione aggiungendo semplicemente due giorni alla data corrente.
//--------------------------------------------------------------------------------------+
DateTime CalculateShipDate()
{
DateTime shipDate = DateTime.Now.AddDays(2);
return (shipDate);
}
L'esecuzione dell'applicazione consente ora di testare il processo di acquisto dall'inizio alla fine.