ASP .NET 4.5 Web Forms - Incluindo o carrinho de compras- V


Este tutorial descreve a lógica de negócios necessária para adicionar um carrinho ao nosso site ASP .NET Web Forms. Quando você tiver concluído este tutorial, os usuários serão capazes de adicionar, remover e modificar os produtos em seu carrinho de compras.

Obs: Acompanhe todas as partes do curso neste link: http://www.macoratti.net/Cursos/aspn_450.htm

O que você vai aprender:

Os recursos introduzidos neste artigo são:

Este artigo foi integralmente baseado no artigo original : http://www.asp.net/web-forms/tutorials/aspnet-45/getting-started-with-aspnet-45-web-forms/shopping-cart (com algumas alterações e portado para a linguagem VB .NET)

Criando um carrinho de compras

Em artigo anteriores, nesta série de tutoriais, adicionamos páginas e códigos para visualizar os dados do produto a partir de um banco de dados.

Neste tutorial, você vamos criar um carrinho de compras para gerir os produtos que os usuários estão interessados em comprar. Os usuários serão capazes de procurar e adicionar itens ao carrinho de compras, mesmo que não esteja registrado ou logado.

Para gerenciar o acesso ao carrinho de compras, vamos atribuir aos usuários uma identificação única usando um identificador exclusivo (GUID), quando o usuário acessa o carrinho pela primeira vez. Vamos armazenar esse ID utilizando o estado da sessão ASP.NET.

O estado da sessão no ASP.NET é um local conveniente para armazenar informações específicas do usuário que irá expirar após o usuário deixar o site.
Embora uso indevido de estado da sessão pode ter implicações de desempenho em sites maiores, a sua utilização com moderação funciona bem para fins de demonstração.

Adicionando um Item do Carrinho (CarrinhoItem) como uma classe do modelo

Já definimos em nossa aplicação o esquema para a categoria e dados do produto, criando classes para representar as categorias e os produtos na pasta Models.

Vamos agora incluir uma nova classe para definir o esquema para o carrinho de compras. Posteriormente vamos incluir uma classe para manipular os dados de acesso a tabela CarrinhoItem. Esta classe irá fornecer a lógica de negócio para adicionar, remover e atualizar itens no carrinho de compras.

Na janela Solution Explorer clique com o botão direito do mouse sobre a pasta Models e selecione Add -> New Item;

Na janela Add New Item selecione Visual Basic -> Code e o template Class informando o nome CarrinhoItem.vb e clicando no botão Add;

A seguir digite o código abaixo neste arquivo:

Imports System.ComponentModel.DataAnnotations

Namespace WingtipToys.Models
    Public Class CarrinhoItem
        <Key> _
        Public Property ItemId() As String
            Get
                Return m_ItemId
            End Get
            Set(value As String)
                m_ItemId = value
            End Set
        End Property
        Private m_ItemId As String

        Public Property CarrinhoId() As String
            Get
                Return m_CarrinhoId
            End Get
            Set(value As String)
                m_CarrinhoId = value
            End Set
        End Property
        Private m_CarrinhoId As String

        Public Property Quantidade() As Integer
            Get
                Return m_Quantidade
            End Get
            Set(value As Integer)
                m_Quantidade = value
            End Set
        End Property
        Private m_Quantidade As Integer

        Public Property DataCriacao() As System.DateTime
            Get
                Return m_DataCriacao
            End Get
            Set(value As System.DateTime)
                m_DataCriacao = value
            End Set
        End Property
        Private m_DataCriacao As System.DateTime

        Public Property ProdutoId() As Integer
            Get
                Return m_ProdutoId
            End Get
            Set(value As Integer)
                m_ProdutoId = value
            End Set
        End Property
        Private m_ProdutoId As Integer

        Public Overridable Property Produto() As Produto
            Get
                Return m_Produto
            End Get
            Set(value As Produto)
                m_Produto = value
            End Set
        End Property
        Private m_Produto As Produto
    End Class
End Namespace
A classe CarrinhoItem possui 6 propriedades:
  • ItemId
  • CarrinhoId
  • Quantidade
  • DataCriacao
  • ProdutoId
  • Produto

A classe carrinhoItem contém o esquema que vai definir cada produto que o usuário adiciona ao carrinho de compras. Esta classe é igual as demais classes de esquema que criamos anteriormente.

Por convenção, o Entity Framework Code-First espera que a chave primária da tabela Carrinhotem seja ou CarrinhoItemId ou ID. No entanto, o código sobrescreve o comportamento padrão usando o atributo data annotation [Key]. O atributo Key da propriedade ItemId especifica que a propriedade ItemID é a chave primária.

A propriedade CarrinhoId especifica o ID do usuário que está associado com o item para comprar. Você vai adicionar código para criar esse ID de usuário quando o usuário acessa o carrinho de compras. Este ID também será armazenado como uma variável de sessão ASP.NET.

Atualizando o Contexto Produto

Além de adicionar a classe CarrinhoItem, vamos precisar atualizar a classe de contexto de banco de dados que gerencia as classes de entidade e que fornece acesso a dados para o banco de dados. Para fazer isso, vamos adicionar a classe carrinhoItem à classe ProdutoContexto.

Na janela Solution Explorer, abra a pasta Models e selecione e abra o arquivo ProdutoContexto.vb;

A seguir inclua a linha de código : Public Property CarrinhoItens() As DbSet(Of CarrinhoItem) conforme mostrada abaixo:

Imports System.Data.Entity

Namespace WingtipToys.Models

    Public Class ProdutoContexto
        Inherits DbContext

        Public Sub New()
            MyBase.New("WingtipToys")
        End Sub

        Public Property Categorias() As DbSet(Of Categoria)
        Public Property Produtos() As DbSet(Of Produto)
        Public Property CarrinhoItens() As DbSet(Of CarrinhoItem)

    End Class
End Namespace

O código do arquivo ProdutoContexto.vb adiciona o namespace System.Data.Entity para que tenhamos acesso a todo o núcleo de funcionalidade do Entity Framework. Esta funcionalidade inclui a capacidade de consultar, inserir, atualizar e excluir dados, trabalhando com objetos fortemente tipados. A classe ProdutoContexto também acrescenta acesso à classe CarrinhoItem.

Gerenciando a lógica de negócios do carrinho de compras

Vamos criar a classe CarrinhoCompras em uma nova pasta esta classe vai manipular o acesso aos dados da tabela CarinhoItem e também incluir a lógica de negócio para adicionar, remover e atualizar os itens no carrinho de compras.

A lógica de carrinho de compras que você irá adicionar conterá a funcionalidade para gerenciar as seguintes ações:

A página do carrinho de compras (Carrinho.aspx) e a classe carrinho de compras serão utilizados em conjunto para acessar os dados do carrinho de compras. A página do carrinho de compras irá exibir todos os itens que o usuário adiciona ao carrinho de compras.

Além da página do carrinho de compras e de classe, vamos criar uma página (IncluirNoCarrinho.aspx) para adicionar produtos ao carrinho de compras. Vamos adicionar código à página ProdutoLista.aspx e na página ProdutoDetalhes.aspx que irá fornecer um link para a página IncluirNoCarrinho.aspx, de modo que o usuário possa adicionar produtos ao carrinho de compras.

O diagrama a seguir mostra o processo básico que ocorre quando o usuário adiciona um produto no carrinho de compras.

Quando o usuário clicar no link Adicionar ao carrinho de compras na página ProdutoLista.aspx ou na página ProdutoDetalhes.aspx, o aplicativo irá navegar até a página IncluirNoCarrinho.aspx e automaticamente para a página Carrinho.aspx. A página IncluirNoCarrinho.aspx irá adicionar o produto selecionado no carrinho de compras, chamando um método na classe Carrinho e a página Carrinho.aspx exibirá os produtos que foram adicionados ao carrinho de compras.

Criando a classe CarrinhoActions

A classe CarrinhoActions será adicionada a uma pasta separada no aplicativo de modo que haverá uma distinção clara entre o modelo (pasta Models), as páginas (pasta raiz) e lógica (pasta Logic).

Clique com o botão direito sobre o nome do projeto e selecione a opção Add New Folder;

Informe nome da pasta como Logic;

Clique com o botão direito sobre a pasta Logic e selecione Add-> New Item;

Inclua uma nova classe chamada CarrinhoActions.vb e substitua o código pelo código a seguir:

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports WingTipToys.WingtipToys.Models

Namespace WingtipToys.Logic

    Public Class CarrinhoActions
        Public Property CarrinhoId() As String
            Get
                Return m_CarrinhoId
            End Get
            Set(value As String)
                m_CarrinhoId = value
            End Set
        End Property
        Private m_CarrinhoId As String

        Private _db As New ProdutoContexto()

        Public Const CarrinhoSessaoChave As String = "CarrinhoId"

        Public Sub IncluirNoCarrinho(id As Integer)
            ' Retorna o produto do banco de dados
            CarrinhoId = GetCarrinhoId()

            Dim carrinhoItem = _db.CarrinhoItens.SingleOrDefault(Function(c) c.CarrinhoId = CarrinhoId AndAlso c.ProdutoId = id)
            If carrinhoItem Is Nothing Then
                ' Cria um novo item no carrinho se não existir
                carrinhoItem = New CarrinhoItem() With { _
                    .ItemId = Guid.NewGuid().ToString(), _
                    .ProdutoId = id, _
                    .CarrinhoId = CarrinhoId, _
                    .Produto = _db.Produtos.SingleOrDefault(Function(p) p.ProdutoID = id), _
                    .Quantidade = 1, _
                    .DataCriacao = DateTime.Now _
                }
                _db.CarrinhoItens.Add(carrinhoItem)
            Else
                ' se o item não existe acrescenta um unidade
                carrinhoItem.Quantidade += 1
            End If
            _db.SaveChanges()
        End Sub

        Public Function GetCarrinhoId() As String
            If HttpContext.Current.Session(CarrinhoSessaoChave) Is Nothing Then
                If Not String.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name) Then
                    HttpContext.Current.Session(CarrinhoSessaoChave) = HttpContext.Current.User.Identity.Name
                Else
                    ' Gera um novo GUID aleatorio usado usando a classe System.Guid
                    Dim tempCartId As Guid = Guid.NewGuid()
                    HttpContext.Current.Session(CarrinhoSessaoChave) = tempCartId.ToString()
                End If
            End If
            Return HttpContext.Current.Session(CarrinhoSessaoChave).ToString()
        End Function

        Public Function GetCarrinhoItems() As List(Of CarrinhoItem)
            CarrinhoId = GetCarrinhoId()
            Return _db.CarrinhoItens.Where(Function(c) c.CarrinhoId = CarrinhoId).ToList()
        End Function
    End Class
End Namespace

O método IncluirNoCarrinho permite que os produtos individuais a sejam incluídos no carrinho de compras com base na identificação do produto. O produto será adicionado ao carrinho mas se o carrinho já contiver um item para o produto terá sua quantidade incrementada em uma unidade.

O método GetCarrinhoId retorna o ID do carrinho. O ID de carrinho é usado para rastrear os itens que um usuário tem em seu carrinho de compras. Se o usuário não tiver o ID do carrinho existente, um novo ID será. Se o usuário estiver conectado como um usuário registrado, a identificação do carrinho está definido como sendo o seu nome de usuário. No entanto, se o usuário não estiver conectado, o ID do carrinho será definido para um valor único (um GUID). Um GUID garante que apenas um carrinho será criado para cada usuário, com base na sua sessão.

O método GetCarrinhotItens retorna uma lista de itens do carrinho de compras para o usuário. Mais adiante veremos que o model binding será usado para exibir os itens dos no carrinho usando o método GetCarrinhoItens.

Incluindo itens no carrinho

Vamos criar uma página de processamento chamada IncluirNoCarrinho.aspx que será usada para adicionar novos produtos no carrinho de compras do usuário. Esta página irá chamar o método IncluirNoCarrinho na classe Carrinho que acabamos de criar. A página InclulirNoCarrinho.aspx vai esperar que um ID do produto seja passada a ela. Este ID de produto será usado ao chamar o método IncluirNoCarrinho na classe Carrinho.

Na janela Solution Explorer clique com o botão direito do mouse sobre o projeto e seleciona Add e a seguir New Item;

Inclua uma página Web Form com o nome IncluirNoCarrinho.aspx a partir da janela Add new Item;

A seguir selecione o arquivo IncluirNoCarrinho.aspx e clique com o botão direito sobre ele selecionando View Code e definindo o código abaixo no code-behind:

Imports System.Linq
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Diagnostics
Imports WingTipToys.WingtipToys.Logic

Namespace WingtipToys

    Partial Public Class IncluirNoCarrinho
        Inherits System.Web.UI.Page

        Protected Sub Page_Load(sender As Object, e As EventArgs)
            Dim rawId As String = Request.QueryString("ProdutoID")
            Dim produotId As Integer
            If Not [String].IsNullOrEmpty(rawId) AndAlso Integer.TryParse(rawId, produotId) Then
                Dim usuariosCarrinhoCompras As New CarrinhoActions()
                usuariosCarrinhoCompras.IncluirNoCarrinho(Convert.ToInt16(rawId))
            Else
                Debug.Fail("ERROR : Falta o produtoId para chamar IncluirNoCarrinho.aspx")
                Throw New Exception("ERROR : Não se pode carregar IncluirNoCarrinho.aspx sem definir um ProdutoId.")
            End If
            Response.Redirect("Carrinho.aspx")
        End Sub

    End Class
End Namespace

Quando a página IncluirNoCarrinho.aspx for carregada um ID do produto é obtido a partir da query string de consulta. Em seguida, uma instância da classe carrinho de compras é criada e usada para chamar o método IncluirNoCarrinho.

Este método, contido no arquivo CarrinhoActions.vb, inclui a lógica para adicionar o produto selecionado no carrinho de compras ou aumentar a quantidade de produto selecionado.

Se o produto não tiver sido adicionado ao carrinho de compras, o produto é adicionado à tabela de CarrinhoItem do banco de dados.

 Se o produto já tiver sido adicionado ao carrinho de compras e o usuário adicionar um item adicional do mesmo produto, a quantidade de produto é incrementada na tabela CarrinhoItem. Finalmente, a página redireciona o usuário para a página Carrinho.aspx que vamos criar em seguida; nesta página o usuário vê uma lista atualizada dos itens no carrinho.

O ID de usuário é usado para identificar os produtos que estão associados a um determinado usuário e este ID é adicionado na tabela CarrinhoItem cada vez que o usuário adiciona um produto no carrinho de compras.

Criando a interface Carrinho de Compras

Vamos criar a página Carrinho.aspx exibirá os produtos que o usuário adicionou ao seu carrinho de compras e fornecer a capacidade de adicionar, remover e atualizar itens no carrinho de compras.

No menu Project clique em Add New Item e na janela Add New Item selecione o item Web Form using Master Page informando o nome Carrinho.aspx;

Selecione a master page Site.Master e clique em OK;

A seguir defina o código abaixo nesta página:

<%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/Site.Master" CodeBehind="Carrinho.aspx.vb" Inherits="WingTipToys.Carrinho" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="FeaturedContent" runat="server">
    <div id="CarrinhoTitulo" runat="server" class="ContentHead"><h1>Carrinho de Compras</h1></div>
    <asp:GridView ID="CarrinhoLista" runat="server" AutoGenerateColumns="False" ShowFooter="True" GridLines="Vertical" CellPadding="4"
        ItemType="WingtipToys.WingtipToys.Models.CarrinhoItem" CssClass="CarrinhoListaItem" SelectMethod="GetCarrinhoItens" Width="600">              
        <AlternatingRowStyle CssClass="CarrinhoListaItemAlt" />
        <Columns>
        <asp:BoundField DataField="ProdutoID" HeaderText="ID" SortExpression="ProduotID" />        
        <asp:BoundField DataField="Produto.ProdutoNome" HeaderText="Nome" SortExpression="ProdutoNome" />        
        <asp:BoundField DataField="Produto.PrecoUnitario" HeaderText="Preço (un.)" DataFormatString="{0:c}"/>     
        <asp:TemplateField   HeaderText="Quantidade">            
                <ItemTemplate>
                    <asp:TextBox ID="QuantidadeComprada" Width="40" runat="server" Text="<%#: Item.Quantidade%>"></asp:TextBox> 
                </ItemTemplate>        
        </asp:TemplateField>    
        <asp:TemplateField HeaderText="Total ">            
                <ItemTemplate>
                    <%#: String.Format("{0:c}", ((Convert.ToDouble(Item.Quantidade)) * Convert.ToDouble(Item.Produto.PrecoUnitario)))%>
                </ItemTemplate>        
        </asp:TemplateField> 
        <asp:TemplateField HeaderText="Remover Item">            
                <ItemTemplate>
                    <asp:CheckBox id="Remover" runat="server"></asp:CheckBox>
                </ItemTemplate>        
        </asp:TemplateField>    
        </Columns>    
        <FooterStyle CssClass="CarrinhoListaFooter"/>
        <HeaderStyle  CssClass="CarrinhoListaHead" />
    </asp:GridView>
    <div>
        <p></p>
        <strong>
            <asp:Label ID="LabelTotalText" runat="server" Text="Total Pedido: "></asp:Label>
            <asp:Label CssClass="NormalBold" id="lblTotal" runat="server" EnableViewState="false"></asp:Label>
        </strong> 
    </div>
    <br />
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
</asp:Content> 

A página Carrinho.aspx inclui um controle GridView chamado CarrinhoLista. Este controle utiliza o model binding para vincular os dados do carrinho de compras do banco de dados com o controle GridView.

Quando você define a propriedade ItemType do controle GridView, a expressão de ligação de dados Item está disponível na marcação do controle e o controle torna-se fortemente tipado.Com isso você pode selecionar detalhes do objeto do item usando o IntelliSense.

Para configurar um controle de dados para usar o Model Binding para selecionar dados, defina a propriedade SelectMethod do controle. Na marcação acima, definimos o SelectMethod para usar o método GetCarrinhotens que retorna uma lista de objetos CarrinhoItem.

O controle GridView chama o método no momento apropriado do ciclo de vida da página e vincula automaticamente os dados retornados.(O método GetCarrinhotens ainda precisa ser criado.)

Retornando os itens dos carrinho de compras

Nossa próxima tarefa é criar o código no code-behind da página Carrinho.aspx para recuperar e preencher os itens e exibi-los no carrinho de compras.

Na janela Solution Explorer clique com o botão direito do mouse sobre a página Carrinho.aspx e selecione View Code;

A seguir defina o código abaixo no code-behind:

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports WingTipToys.WingtipToys.Models
Imports WingTipToys.WingtipToys.Logic

Public Class Carrinho
     Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub

Public Function GetCarrinhoItens() As List(Of CarrinhoItem)
   Dim actions As New CarrinhoActions()
   Return actions.GetCarrinhoItens()
End Function

End Class

O controle GridView chama o método GetCarrinhotens no momento apropriado do ciclo de vida da página e vincula automaticamente os dados retornados. O método GetCarrinhotens cria uma instância do objeto CarrinhoActions e em seguida o código usa essa instância para retornar os itens no carrinho chamando o método GetCarrinhoItens.

Adicionando produtos ao carrinho

Quando a página ProdutoLista.aspx ou ProdutoDetalhes.aspx é exibida, o usuário será capaz de adicionar o produto ao carrinho de compras usando um link. Quando o usuário clicar no link, o aplicativo navega para a página de processamento chamada IncluirNoCarrinho.aspx. Esta página vai chamar o método IncluirNoCarrinho da classe Carrinho.

Vamos adicionar um link Incluir no carrinho em ambas as páginas sendo que este link incluirá o ID do produto que será retornado a partir do banco de dados.

Na janela Solution Explorer abra o arquivo ProdutoLista.aspx e copie o código abaixo para criar o link para incluir o produto pelo seu id:

 <a href="/IncluirNoCarrinho.aspx?produtoID=<%#:Item.ProdutoID %>">              
        <span class="ProdutoListaItem">
            <b>Incluir no Carrinho<b>
        </span>          
</a>

Abaixo vemos um trecho do arquivo ProdutoLista.aspx com o código acima incluído:

Agora abra o arquivo ProdutoDetalhes.aspx e inclua o mesmo de código para criar o link conforme mostra o trecho de código abaixo:

1, 2, 3 ... Testando

Vamos executar a aplicação e verificar se as funcionalidades incluídas para inclusão de produtos estão funcionando;

Clique com o botão direito do mouse sobre a página Default.aspx e selecione Set As Start Page;

Pressione CTRL+F5 para rodar a aplicação;

Selecione Carros a partir do menu de navegação de categorias;

A seguir escolha um item e clique no link Incluir no Carrinho:

A página carrinho.aspx irá exibir o item selecionado com opções para alterar a quantidade e uma checkbox para selecionar a remoção do item;

Calculando o exibindo os valores dos itens no carrinho

Vamos agora definir um método chamado GetTotal na classe Carrinho para exibir a quantidade total do pedido;

Na janela Solution Explorer selecione o arquivo CarrinhoActions na pasta Logic e inclua o método GetTotal na classe conforme o código a seguir:

   Public Function GetTotal() As Decimal
            CarrinhoId = GetCarrinhoId()
            ' Multiplica o preço pela quantidade do produto para obter
            ' o preço atual dos produtos no carrinho
            ' soma todos os totaisl para obter o total do carrinho
            Dim total As System.Nullable(Of Decimal) = Decimal.Zero

            total = CType((From carrinhoItens In _db.CarrinhoItens
                           Where carrinhoItens.CarrinhoId = CarrinhoId
                           Select CType(carrinhoItens.Quantidade, System.Nullable(Of Integer)) _
                           * carrinhoItens.Produto.PrecoUnitario).Sum(), System.Nullable(Of Decimal))

            Return If(total, Decimal.Zero)
        End Function

Primeiro, o método GetTotal obtém a identificação do carrinho de compras para o usuário. Em seguida, o método obtém o total do carrinho multiplicando-se o preço do produto pela quantidade do produto para cada produto listado no carrinho.

Alterando a exibição no carrinho de compras

Vamos modificar o código da página Carrinho.aspx para chamar o método GetTotal e exibir esse total na página quando ela for carregada.

Selecione o arquivo Carrinho.aspx e clique com o botão direito do mouse sobre ele escolhendo a opção View Code;

A seguir inclua o código destacado em azul no evento Load da página abaixo no arquivo:

Imports System.Collections.Generic
Imports System.Linq
Imports WingTipToys.WingtipToys.Models
Imports WingTipToys.WingtipToys.Logic

Public Class Carrinho
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim usuarioCarrinhoCompra As New CarrinhoActions()
        Dim TotalCarrinho As Decimal = 0
        TotalCarrinho = usuarioCarrinhoCompra.GetTotal()
        If TotalCarrinho > 0 Then
            ' exibe o  Total.
            lblTotal.Text = [String].Format("{0:c}", TotalCarrinho)
        Else
            LabelTotalText.Text = ""
            lblTotal.Text = ""
            CarrinhoTitulo.InnerText = "O carrinho de compras esta vazio"
        End If
    End Sub
    Public Function GetCarrinhoItens() As List(Of CarrinhoItem)
        Dim actions As New CarrinhoActions()
        Return actions.GetCarrinhoItens()
    End Function
End Class

Quando a página Carrinho.aspx for carregada ela carrega o objeto carrinho de compras e, em seguida, recupera o total do carrinho de compras, chamando o método GetTotal da classe Carrinho. Se o carrinho de compras está vazio, uma mensagem será exibida informando o fato ao usuário.

1, 2, 3 ... Testando

Vamos executar a aplicação e verificar se as funcionalidades incluídas para inclusão de produtos e exibição dos totais estão funcionando;

Clique com o botão direito do mouse sobre a página Default.aspx e selecione Set As Start Page;

Pressione CTRL+F5 para rodar a aplicação;

Selecione Carros a partir do menu de navegação de categorias e a seguir selecione um produto e clique no link - Incluir no Carrinho;

Repetida o procedimento selecionando outra categoria e outro produto de forma a ter mais de item no seu carrinho;

Abaixo vemos o resultado para a seleção de dois produtos distintos:

Verificamos que o total esta sendo obtido corretamente a partir das quantidades e preços dos produtos no carrinho.

Incluindo os botões para atualizar e realizar o checkout no carrinho de compras

Para permitir que os usuários modifiquem o carrinho de compras, vamos adicionar um botão de atualização e um botão para fazer o Checkout na página do carrinho de compras.

Abra o arquivo Carrinho.aspx e selecione o modo Source de exibição;

Para adicionar o botão Atualizar e no botão CheckOut na página Carrinho.aspx, adicione a marcação em amarelo para a marcação existente, como mostra o seguinte código:

Quando o usuário clicar no botão Atualizar, o manipulador de eventos btnAtualizar_Click será chamado. Este manipulador de eventos irá chamar o código que vamos adicionar logo a seguir.

Em seguida, você pode atualizar o código contido no arquivo Carrinho.aspx.vb para percorrer os itens do carrinho e chamar os métodos RemoveItem e UpdateItem.

Abra o arquivo code-behind Carrinho.aspx.vb e inclua o código destacado em azul no arquivo:

Imports System.Collections.Generic
Imports System.Linq
Imports WingTipToys.WingtipToys.Models
Imports WingTipToys.WingtipToys.Logic
Imports System.Collections.Specialized
Imports System.Collections
Imports System.Web.ModelBinding


Public Class Carrinho
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim usuarioCarrinhoCompra As New CarrinhoActions()
        Dim TotalCarrinho As Decimal = 0
        TotalCarrinho = usuarioCarrinhoCompra.GetTotal()
        If TotalCarrinho > 0 Then
            ' exibe o Total.
            lblTotal.Text = [String].Format("{0:c}", TotalCarrinho)
        Else
            LabelTotalText.Text = ""
            lblTotal.Text = ""
            CarrinhoTitulo.InnerText = "O carrinho de compras esta vazio"
            btnAtualizar.Visible = False
        End If
    End Sub
    Public Function GetCarrinhoItens() As List(Of CarrinhoItem)
        Dim actions As New CarrinhoActions()
        Return actions.GetCarrinhoItens()
    End Function

    Public Function AtualizaItensCarrinho() As List(Of CarrinhoItem)
        Dim usuariosCarrinho As New CarrinhoActions()
        Dim carrinhoId As String = usuariosCarrinho.GetCarrinhoId()

        Dim carrinhoAtualiza As CarrinhoActions.CarrinhoAtualiza() = New CarrinhoActions.CarrinhoAtualiza(CarrinhoLista.Rows.Count - 1) {}

        For i As Integer = 0 To CarrinhoLista.Rows.Count - 1
            Dim rowValues As IOrderedDictionary = New OrderedDictionary()
            rowValues = GetValues(CarrinhoLista.Rows(i))
            carrinhoAtualiza(i).ProdutoId = Convert.ToInt32(rowValues("ProdutoID"))

            Dim cbRemove As New CheckBox()
            cbRemove = DirectCast(CarrinhoLista.Rows(i).FindControl("Remove"), CheckBox)
            carrinhoAtualiza(i).RemoveItem = cbRemove.Checked

            Dim quantidadeTextBox As New TextBox()
            quantidadeTextBox = DirectCast(CarrinhoLista.Rows(i).FindControl("QuantidadeComprada"), TextBox)
            carrinhoAtualiza(i).QuantidadeComprada = Convert.ToInt16(quantidadeTextBox.Text.ToString())
        Next
        usuariosCarrinho.AtualizaCarrinhoBD(carrinhoId, carrinhoAtualiza)
        CarrinhoLista.DataBind()
        lblTotal.Text = [String].Format("{0:c}", usuariosCarrinho.GetTotal())
        Return usuariosCarrinho.GetCarrinhoItens()
    End Function

    Public Shared Function GetValues(row As GridViewRow) As IOrderedDictionary
        Dim values As IOrderedDictionary = New OrderedDictionary()
        For Each cell As DataControlFieldCell In row.Cells
            If cell.Visible Then
                ' Extrai os valores da celula
                cell.ContainingField.ExtractValuesFromCell(values, cell, row.RowState, True)
            End If
        Next
        Return values
    End Function

    Protected Sub btnAtualizar_Click(sender As Object, e As EventArgs) Handles btnAtualizar.Click
        AtualizaItensCarrinho()
    End Sub
End Class

Quando o usuário clica no botão Atualizar na página Carrinho.aspx o método AtualizaItensCarrinho() é chamado. Este método recebe os valores atualizados para cada item no carrinho de compras. Em seguida, o método AtualizaCarrinhoBD(que será criado mais adiante) para adicionar ou remover itens do carrinho de compras.

Uma vez que o banco de dados foi atualizado para refletir as atualizações do carrinho de compras, o controle GridView é atualizado na página do carrinho de compras, chamando o método DataBind para o GridView. Além disso, o valor total do pedido na página do carrinho de compras é atualizado para refletir a lista atualizada dos itens.

Atualizando e removendo itens do carrinho de compras

Na página Carrinho.aspx, podemos ver que os controles foram adicionados para atualizar a quantidade de um item e remover um item. Agora, vamos adicionar o código que vai fazer esses controles funcionarem.

Abra o arquivo CarrinhoAction.vb na pasta Logic;

Inclua o código destacado em azul neste arquivo:

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports WingTipToys.WingtipToys.Models

Namespace WingtipToys.Logic

    Public Class CarrinhoActions
        Public Property CarrinhoId() As String
            Get
                Return m_CarrinhoId
            End Get
            Set(value As String)
                m_CarrinhoId = value
            End Set
        End Property
        Private m_CarrinhoId As String

        Private _db As New ProdutoContexto()

        Public Const CarrinhoSessaoChave As String = "CarrinhoId"

        Public Sub IncluirNoCarrinho(id As Integer)
            ' Retorna o produto do banco de dados
            CarrinhoId = GetCarrinhoId()

            Dim carrinhoItem = _db.CarrinhoItens.SingleOrDefault(Function(c) c.CarrinhoId = CarrinhoId AndAlso c.ProdutoId = id)
            If carrinhoItem Is Nothing Then
                ' Cria um novo item no carrinho se não existir
                carrinhoItem = New CarrinhoItem() With { _
                    .ItemId = Guid.NewGuid().ToString(), _
                    .ProdutoId = id, _
                    .CarrinhoId = CarrinhoId, _
                    .Produto = _db.Produtos.SingleOrDefault(Function(p) p.ProdutoID = id), _
                    .Quantidade = 1, _
                    .DataCriacao = DateTime.Now _
                }

                _db.CarrinhoItens.Add(carrinhoItem)
            Else
                ' se o item não existe acrescenta um unidade
                carrinhoItem.Quantidade += 1
            End If
            _db.SaveChanges()
        End Sub

        Public Function GetCarrinhoId() As String
            If HttpContext.Current.Session(CarrinhoSessaoChave) Is Nothing Then
                If Not String.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name) Then
                    HttpContext.Current.Session(CarrinhoSessaoChave) = HttpContext.Current.User.Identity.Name
                Else
                    ' Gera um novo GUID aleatorio usado usando a classe System.Guid
                    Dim tempCartId As Guid = Guid.NewGuid()
                    HttpContext.Current.Session(CarrinhoSessaoChave) = tempCartId.ToString()
                End If
            End If
            Return HttpContext.Current.Session(CarrinhoSessaoChave).ToString()
        End Function

        Public Function GetCarrinhoItens() As List(Of CarrinhoItem)
            CarrinhoId = GetCarrinhoId()
            Return _db.CarrinhoItens.Where(Function(c) c.CarrinhoId = CarrinhoId).ToList()
        End Function

        Public Function GetTotal() As Decimal
            CarrinhoId = GetCarrinhoId()
            ' Multiplica o preço pela quantidade do produto para obter
            ' o preço atual dos produtos no carrinho
            ' soma todos os totaisl para obter o total do carrinho
            Dim total As System.Nullable(Of Decimal) = Decimal.Zero

            total = CType((From carrinhoItens In _db.CarrinhoItens
                           Where carrinhoItens.CarrinhoId = CarrinhoId
                           Select CType(carrinhoItens.Quantidade, System.Nullable(Of Integer)) _
                           * carrinhoItens.Produto.PrecoUnitario).Sum(), System.Nullable(Of Decimal))

            Return If(total, Decimal.Zero)
        End Function

        Public Function GetCarrinho(context As HttpContext) As CarrinhoActions
            Dim carrinho = New CarrinhoActions()
            carrinho.CarrinhoId = carrinho.GetCarrinhoId()
            Return carrinho
        End Function

        Public Sub AtualizaCarrinhoBD(carrinhoId As String, CarrinhoItemAtualiza As CarrinhoAtualiza())
            Using db = New ProdutoContexto()
                Try
                    Dim CartItemCount As Integer = CarrinhoItemAtualiza.Count()
                    Dim myCart As List(Of CarrinhoItem) = GetCarrinhoItens()
                    For Each carrinhoItem In myCart
                        ' Itera através de todas aslinhas na lista de carrinho
                        For i As Integer = 0 To CartItemCount - 1
                            If carrinhoItem.Produto.ProdutoID = CarrinhoItemAtualiza(i).ProdutoId Then
                                If CarrinhoItemAtualiza(i).QuantidadeComprada < 1 OrElse CarrinhoItemAtualiza(i).RemoveItem = True Then
                                    RemoveItem(carrinhoId, carrinhoItem.ProdutoId)
                                Else
                                    UpdateItem(carrinhoId, carrinhoItem.ProdutoId, CarrinhoItemAtualiza(i).QuantidadeComprada)
                                End If
                            End If
                        Next
                    Next
                Catch exp As Exception
                    Throw New Exception("ERRO: Não foi possível atualizar o Banco de dados - " + exp.Message.ToString(), exp)
                End Try
            End Using
        End Sub

        Public Sub RemoveItem(removeCarrinhoID As String, removeProdutoID As Integer)
            Using db = New ProdutoContexto()
                Try
                    Dim meuItem = (From c In db.CarrinhoItens
                                           Where c.CarrinhoId = removeCarrinhoID _
                                           AndAlso c.Produto.ProdutoID = removeProdutoID).FirstOrDefault()

                    If meuItem IsNot Nothing Then
                        ' db.DeleteObject(meuItem);
                        db.CarrinhoItens.Remove(meuItem)
                        db.SaveChanges()
                    End If
                Catch exp As Exception
                    Throw New Exception("ERROR: Não foi possível Remover o Item do Carrinho - " + exp.Message.ToString(), exp)
                End Try
            End Using
        End Sub

        Public Sub UpdateItem(atualizaCarrinhoID As String, atualizaProdutoID As Integer, quantidade As Integer)
            Using db = New ProdutoContexto()
                Try
                    Dim meuItem = (From c In db.CarrinhoItens Where c.CarrinhoId = atualizaCarrinhoID AndAlso c.Produto.ProdutoID = atualizaProdutoID).FirstOrDefault()
                    If meuItem IsNot Nothing Then
                        meuItem.Quantidade = quantidade
                        db.SaveChanges()
                    End If
                Catch exp As Exception
                    Throw New Exception("ERROR: Não foi possível atualizar o item do carrinho - " & exp.Message.ToString(), exp)
                End Try
            End Using
        End Sub

        Public Sub CarrinhoVazio()
            CarrinhoId = GetCarrinhoId()
            Dim carrinhoItens = _db.CarrinhoItens.Where(Function(c) c.CarrinhoId = CarrinhoId)
            For Each carrinhoItem In carrinhoItens
                _db.CarrinhoItens.Remove(carrinhoItem)
            Next
            ' Salva as mudanças
            _db.SaveChanges()
        End Sub

        Public Function GetContador() As Integer
            CarrinhoId = GetCarrinhoId()
            ' Obtem a contagem de cada item no carrinho e as soma
            Dim contador As System.Nullable(Of Integer) = (From carrinhoItems In _db.CarrinhoItens
                                                                                     Where carrinhoItems.CarrinhoId = CarrinhoId
                                                                                      Select CType(carrinhoItems.Quantidade, System.Nullable(Of Integer))).Sum()
            ' Retorna 0 se todas as entradas forem nulas
            Return If(contador, 0)
        End Function

        Public Structure CarrinhoAtualiza
            Public ProdutoId As Integer
            Public QuantidadeComprada As Integer
            Public RemoveItem As Boolean
        End Structure

    End Class
End Namespace

O método AtualizaCarrinhoBD, chamado a partir do método AtualizaItensCarrinho() na página Carrinho.aspx.vb, contém a lógica para atualizar ou remover itens do carrinho de compras. O método AtualizaCarrinhoBD percorre todas as linhas dentro da lista carrinho de compras.

Se um item de carrinho de compras foi marcado para ser removido, ou a quantidade for menor do que um, o método RemoveItem é chamado. Caso contrário, o item do carrinho de compras está marcado para atualizações e o método UpdateItem é chamado. Depois que o item do carrinho de compras foi removido ou atualizado, as alterações dos dados são salvas.

A estrutura CarrinhoAtualiza é usada para armazenar todos os itens do carrinho de compras. O método AtualizaCarrinhoBD usa a estrutura CarrinhoAtualiza para determinar se qualquer um dos elementos precisa de ser atualizado ou removido.

No próximo tutorial, vamos usar o método CarrinhoVazio para limpar o carrinho de compras após a compra de produtos. No momento vamos usar o método GetContador que acabamos de incluir para determinar quantos itens estão no carrinho de compras.

Incluindo um contador no carrinho de compras

Para permitir que o usuário veja o número total de itens no carrinho de compras, vamos adicionar um contador na página Site.Master. Este contador também vai atuar como um link para o carrinho de compras.

Na janela Solution Explorer abra o arquivo Site.Master e faça as alterações conforme o código destacado em abaixo no trecho de código deste arquivo:

A seguir vamos atualizar o code-behind Site.Master.vb com o código abaixo:

Antes da que a página seja processada no navegador, o evento Page_PreRender é gerado.

No manipulador Page_PreRender, a contagem total do carrinho de compras é determinada chamando o método GetContador. O valor retornado é adicionado à extensão carrinhoContador incluído na marcação da página Site.Master.

As tags <span> permitem que os elementos internos sejam devidamente renderizados. Quando qualquer página do site é exibida, o total do carrinho de compras será mostrado.

O usuário também poderá clicar no total do carrinho de compras para visualizar o carrinho de compras.

1, 2, 3 ... Testando e concluindo

Vamos executar o aplicativo agora para ver como podemos adicionar, excluir e atualizar os itens no carrinho de compras. O total carrinho de compras irá refletir o custo total de todos os itens no carrinho de compras.

  1. Pressione Ctrl + F5 para executar o aplicativo;
  2. O navegador abre e mostra a página Default.aspx;
  3. Selecione Carros no menu de navegação categoria;
  4. Clique no link Adicionar no carrinho de compras ao lado do primeiro produto;
  5. A página Carrinho.aspx é exibida com o total do pedido;
  6. Selecione Aeronaves do menu de navegação categoria;
  7. Clique no link Adicionar no carrinho de compras ao lado do primeiro produto;
  8. Defina a quantidade do primeiro item no carrinho de compras para 3 e marque a caixa de seleção Remover item do segundo item;
  1. Clique no botão Atualizar para atualizar a página do carrinho de compras e exibir o total nova ordem.

Após concluir todas as implementações discutidas neste tutorial nosso carrinho de compras suporta a adição, exclusão e atualização de itens que o usuário tenha selecionado para compra. Além de implementar a funcionalidade de carrinho de compras, você aprendeu como exibir itens de carrinho de compras em um controle GridView e calcular o total do pedido.

Ufa... acabamos...

No próximo tutorial vamos incluir as funcionalidades de registro e autenticação do usuário: Autorizando e registrando o usuário  - VI

Referências:


José Carlos Macoratti