Share via


Parte 6: Associação do ASP.NET

por Joe Stagner

Observação

Desde que este artigo foi escrito, os provedores de associação ASP.NET foram substituídos pelo ASP.NET Identity. É altamente recomendável atualizar aplicativos para usar a plataforma ASP.NET Identity em vez dos provedores de associação apresentados no momento em que este artigo foi escrito. ASP.NET Identity tem várias vantagens em relação ao sistema de associação ASP.NET, incluindo :

  • Melhor desempenho
  • Extensibilidade e testabilidade aprimoradas
  • Suporte para OAuth, OpenID Connect e autenticação de dois fatores
  • Suporte à identidade baseada em declarações
  • Melhor interoperabilidade com o ASP.Net Core

A Tailspin Spyworks demonstra como é extraordinariamente simples criar aplicativos avançados e escalonáveis para a plataforma .NET. Ele mostra como usar os ótimos novos recursos no ASP.NET 4 para criar uma loja online, incluindo compras, check-out e administração.

Esta série de tutoriais detalha todas as etapas executadas para criar o aplicativo de exemplo Tailspin Spyworks. A parte 6 adiciona ASP.NET Associação.

Trabalhando com associação ASP.NET

Captura de tela que mostra onde selecionar a Configuração do AZure SP Dot NET.

Clique em Segurança

Captura de tela que mostra onde clicar em Segurança.

Verifique se estamos usando a autenticação de formulários.

Captura de tela que mostra como confirmar que você está usando a autenticação de formulários.

Use o link "Criar Usuário" para criar alguns usuários.

Captura de tela que mostra onde clicar em Criar Usuário.

Quando terminar, consulte a janela Gerenciador de Soluções e atualize o modo de exibição.

Captura de tela que mostra onde atualizar a exibição.

Observe que o ASPNETDB. A multa de MDF foi criada. Esse arquivo contém as tabelas para dar suporte aos principais serviços de ASP.NET, como associação.

Agora podemos começar a implementar o processo de check-out.

Comece criando uma página CheckOut.aspx.

A página CheckOut.aspx só deve estar disponível para usuários que estão conectados, portanto, restringiremos o acesso a usuários conectados e redirecionaremos usuários que não estão conectados à página LogIn.

Para fazer isso, adicionaremos o seguinte à seção de configuração do nosso arquivo de web.config.

<location path="Checkout.aspx">
    <system.web>
      <authorization>
        <deny users="?" />
      </authorization>
    </system.web>
  </location>

O modelo para aplicativos ASP.NET Web Forms adicionou automaticamente uma seção de autenticação ao nosso arquivo web.config e estabeleceu a página de logon padrão.

<authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="2880" />
    </authentication>

Devemos modificar o arquivo code-behind Login.aspx para migrar um carrinho de compras anônimo quando o usuário fizer logon. Altere o evento Page_Load da seguinte maneira.

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("~/");
     }
}

Em seguida, adicione um manipulador de eventos "LoggedIn" como este para definir o nome da sessão para o usuário conectado recentemente e altere a ID de sessão temporária no carrinho de compras para o do usuário chamando o método MigrateCart em nossa classe MyShoppingCart. (Implementado no arquivo .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;
}

Implemente o método MigrateCart() assim.

//--------------------------------------------------------------------------------------+
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);
      }
    }           
}

Em checkout.aspx, usaremos um EntityDataSource e um GridView em nosso marcar página de saída, assim como fizemos em nossa página de carrinho de compras.

<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>

Observe que nosso controle GridView especifica um manipulador de eventos "ondatabound" chamado MyList_RowDataBound portanto, vamos implementar esse manipulador de eventos como este.

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");
        }
     }
}

Esse método mantém um total em execução do carrinho de compras, pois cada linha é associada e atualiza a linha inferior do GridView.

Nesta fase, implementamos uma apresentação de "revisão" da ordem a ser colocada.

Vamos lidar com um cenário de carrinho vazio adicionando algumas linhas de código ao nosso evento Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
   CheckOutHeader.InnerText = "Your Shopping Cart is Empty";
   LabelCartHeader.Text = "";
   CheckoutBtn.Visible = false;
}

Quando o usuário clicar no botão "Enviar", executaremos o código a seguir no manipulador de eventos Enviar Clique no Botão.

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. ";
    }
}

A "carne" do processo de envio de pedidos deve ser implementada no método SubmitOrder() da nossa classe MyShoppingCart.

SubmitOrder:

  • Pegue todos os itens de linha no carrinho de compras e use-os para criar um novo Registro de Pedidos e os registros OrderDetails associados.
  • Calcular Data de Envio.
  • Limpe o carrinho de compras.
//--------------------------------------------------------------------------------------+
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);
}

Para os fins deste aplicativo de exemplo, calcularemos uma data de envio simplesmente adicionando dois dias à data atual.

//--------------------------------------------------------------------------------------+
DateTime CalculateShipDate()
{
   DateTime shipDate = DateTime.Now.AddDays(2);
   return (shipDate);
}

A execução do aplicativo agora nos permitirá testar o processo de compra do início ao fim.