Parte 6: Appartenenza ASP.NET

di Joe Stagner

Nota

Poiché questo articolo è stato scritto, i provider di appartenenze ASP.NET sono stati sostituiti da ASP.NET Identity. È consigliabile aggiornare le app per usare ASP.NET Identity Platform anziché i provider di appartenenze in primo piano al momento della scrittura di questo articolo. ASP.NET Identity presenta diversi vantaggi rispetto al sistema di appartenenza ASP.NET, tra cui :

  • Prestazioni migliori
  • Miglioramento dell'estendibilità e della testability
  • Supporto per OAuth, OpenID Connect e autenticazione a due fattori
  • Supporto delle identità basate sulle 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 grandi 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 Appartenenza.

Utilizzo dell'appartenenza a ASP.NET

Screenshot che mostra dove selezionare A S P dot NET Configuration (Configurazione net punto S).

Fare clic su Sicurezza

Screenshot che mostra dove fare clic su Sicurezza.

Assicurarsi di usare l'autenticazione basata su form.

Screenshot che mostra come confermare l'uso dell'autenticazione basata su form.

Usare il collegamento "Crea utente" per creare un paio di utenti.

Screenshot che mostra dove fare clic su Crea utente.

Al termine, fare riferimento alla finestra Esplora soluzioni e aggiornare la visualizzazione.

Screenshot che mostra dove aggiornare la visualizzazione.

Si noti che ASPNETDB. È stata creata una fine MDF. Questo file contiene le tabelle per supportare i servizi di base ASP.NET come l'appartenenza.

A questo punto è possibile iniziare a implementare il processo di estrazione.

Per iniziare, creare una pagina CheckOut.aspx.

La pagina CheckOut.aspx deve essere disponibile solo per gli utenti che hanno eseguito l'accesso, in modo da limitare l'accesso agli utenti connessi e reindirizzare 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 Web Forms ASP.NET applicazioni 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 con estensione 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 useremo EntityDataSource e GridView nella pagina di estrazione, 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&#39;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&#39;s correct.";
        CheckoutBtn.Visible = true;
        e.Row.Cells[5].Text = "Total: " + _CartTotal.ToString("C");
        }
     }
}

Questo metodo mantiene un totale in esecuzione del carrello acquisti perché ogni riga è associata e aggiorna la riga inferiore di GridView.

In questa fase è stata implementata una presentazione di "revisione" dell'ordine da inserire.

Per gestire uno scenario di carrello vuoto, aggiungere 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 dell'evento 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. ";
    }
}

La "carne" del processo di invio dell'ordine deve essere implementata nel metodo SubmitOrder() della classe MyShoppingCart.

SubmitOrder:

  • Prendere tutti gli elementi della riga nel carrello acquisti e usarli per creare un nuovo record ordine e i record OrderDetails 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.