Você está na página 1de 213

ÍNDICE

01 - INTRODUÇÃO AO ASP.NET 4.5 WEB FORMS E VISUAL STUDIO 2013...................................................................5


INTRODUÇÃO.................................................................................................................................................................... 5
Download do projeto concluído...............................................................................................................................5
Revisão do conteúdo, tomando o quiz de ASP.NET Web Formulários relacionado...........................................5
Audiência....................................................................................................................................................................5
Características do aplicativo.....................................................................................................................................6
Tarefas e cenários de aplicativos.............................................................................................................................6
VISÃO GERAL.................................................................................................................................................................... 7
O aplicativo de exemplo do Wingtip Toys..............................................................................................................7
PRÉ-REQUISITOS.............................................................................................................................................................. 11
BAIXAR O APLICATIVO DE EXEMPLO.....................................................................................................................................12
Baixe o arquivo do site de exemplos do MSDN:..............................................................................................................12
Comentários e apoio tutorial.................................................................................................................................12
02 - CRIAR O PROJETO............................................................................................................................................ 14
O QUE VOCÊ VAI APRENDER:..............................................................................................................................................14
CRIANDO O PROJETO........................................................................................................................................................ 14
Noções básicas sobre os quadros ASP.NET...........................................................................................................16
Revisão do projeto...................................................................................................................................................17
Executando o aplicativo da Web padrão..............................................................................................................19
ASP.NET WEB FORMULÁRIOS PLANO DE FUNDO..................................................................................................................19
Recursos de aplicativo da Web no modelo de aplicativo de formulários Web............................................................20
Associação............................................................................................................................................................................20
SQL Server Express LocalDB...............................................................................................................................................21
Páginas mestras................................................................................................................................................................... 22
HTML5.................................................................................................................................................................................. 22
Modernizr.............................................................................................................................................................................22
Bootstrap.............................................................................................................................................................................. 22
Pacotes NuGet.....................................................................................................................................................................22
jQuery................................................................................................................................................................................... 23
Validação discreta............................................................................................................................................................... 23
Entity Framework Code First..............................................................................................................................................23
Tour pelo Visual Studio...........................................................................................................................................24
RESUMO........................................................................................................................................................................ 24
03 - CRIAR A CAMADA DE ACESSO A DADOS........................................................................................................... 25
O QUE VOCÊ VAI APRENDER:..............................................................................................................................................25
Estes são os recursos introduzidos no tutorial:.....................................................................................................25
CRIANDO OS MODELOS DE DADOS.......................................................................................................................................25
Referências e entity Framework.............................................................................................................................26
Classes de entidade.................................................................................................................................................26
Anotações de dados................................................................................................................................................29
Classe de contexto...................................................................................................................................................29
Classe de inicializador.............................................................................................................................................30
Configurando o aplicativo para usar o modelo de dados...................................................................................38
Atualizando o arquivo global asax....................................................................................................................................38
CRIANDO O APLICATIVO.................................................................................................................................................... 40
RESUMO........................................................................................................................................................................ 41

1
04 - INTERFACE DO USUÁRIO E NAVEGAÇÃO.......................................................................................................... 42
O QUE VOCÊ VAI APRENDER:..............................................................................................................................................42
MODIFICAR A INTERFACE DO USUÁRIO.................................................................................................................................42
@Page Directiva......................................................................................................................................................44
Controles de servidor Web......................................................................................................................................44
Código do servidor..................................................................................................................................................45
Atualizando a página mestra.................................................................................................................................45
Páginas mestras.......................................................................................................................................................49
Adicionando arquivos de imagem....................................................................................................................................49
Baixe do site de exemplos do MSDN:...............................................................................................................................49
Adicionando páginas...............................................................................................................................................51
Atualizando o Bootstrap.........................................................................................................................................52
Modificando o padrão de navegação....................................................................................................................54
Adicionando um controle de dados para exibir dados de navegação...............................................................55
Vinculando o controle de dados para o banco de dados....................................................................................56
Executando o aplicativo e criando o banco de dados..........................................................................................57
Revendo o banco de dados.....................................................................................................................................58
RESUMO........................................................................................................................................................................ 61
05 - EXIBIR ITENS DE DADOS E DETALHES................................................................................................................ 63
O QUE VOCÊ VAI APRENDER:..............................................................................................................................................63
Estes são os recursos introduzidos no tutorial:.....................................................................................................63
ADICIONANDO UM CONTROLE DE DADOS PARA EXIBIR OS PRODUTOS.........................................................................................63
Usando um controle de fonte de dados para vincular a dados..........................................................................63
Codificação manual para vincular dados.............................................................................................................63
Usando o modelo de ligação para ligar dados.....................................................................................................64
EXIBINDO PRODUTOS........................................................................................................................................................64
Adicionar código para exibir os produtos.............................................................................................................67
Executando o aplicativo..........................................................................................................................................69
Adicionando um controle de dados para exibir detalhes do produto................................................................71
Executando o aplicativo..........................................................................................................................................74
RESUMO........................................................................................................................................................................ 75
06 - CARRINHO DE COMPRAS................................................................................................................................. 76
O QUE VOCÊ VAI APRENDER:..............................................................................................................................................76
CARACTERÍSTICAS DO CÓDIGO NESTE TUTORIAL:.....................................................................................................................76
CRIANDO UM CARRINHO DE COMPRAS.................................................................................................................................76
Adicionar CartItem como uma classe de modelo................................................................................................77
Atualizar o contexto do produto............................................................................................................................79
Gerenciando a lógica de negócios do carrinho compras....................................................................................80
Criando a classe carrinho de compras..............................................................................................................................81
Criando a funcionalidade de adicionar ao carrinho............................................................................................84
Para criar o Add To Cart funcionalidade:..........................................................................................................................84
Criando a interface do usuário do carrinho de compras.....................................................................................86
Recuperando os itens do carrinho de compras...............................................................................................................88
Adicionando produtos ao carrinho de compras...................................................................................................89
Teste do carrinho de compras................................................................................................................................92
Calcular e exibir o Total do pedido........................................................................................................................94
Modificar a exibição de carrinho compras............................................................................................................97
Testar o Total carrinho compras............................................................................................................................99
Adicionando botões de Checkout e atualização para o carrinho de compras................................................100

2
Atualizar e remover itens do carrinho de compras............................................................................................105
Adicionar um contador de carrinho de compras...............................................................................................111
TESTE CONCLUÍDO O CARRINHO DE COMPRAS........................................................................................................................115
RESUMO...................................................................................................................................................................... 116
07 - CHECK-OUT E PAGAMENTO COM PAYPAL...................................................................................................... 117
O QUE VOCÊ VAI APRENDER:............................................................................................................................................117
RASTREAMENTO DE ORDEM DE ADIÇÃO..............................................................................................................................117
Adicionar as classes de modelo Order e OrderDetail........................................................................................118
ADICIONAR O ACESSO DE CHECKOUT.................................................................................................................................121
Adicionar uma pasta de Checkout e páginas.....................................................................................................121
Adicionar um arquivo Web. config......................................................................................................................124
HABILITAR LOGONS DE OUTROS SITES USANDO OAUTH E OPENID..........................................................................................125
Modificar a funcionalidade de Login...................................................................................................................127
MIGRANDO O CARRINHO DE COMPRAS..............................................................................................................................130
Atualizando a conexão de banco de dados........................................................................................................137
INTEGRAÇÃO PAYPAL.....................................................................................................................................................137
Criar contas de teste PaylPal................................................................................................................................137
Adicionar a classe de PayPal e credenciais de API............................................................................................140
Atualizar o número da porta de LocalHost na classe de PayPal......................................................................150
Adicione o botão do PayPal Checkout................................................................................................................151
Envie informações de compra para o PayPal.....................................................................................................152
Detalhes do pedido de revisão.............................................................................................................................154
Concluir compra....................................................................................................................................................160
Segurar cancelar compra......................................................................................................................................164
Manipular erros de compra..................................................................................................................................164
EXECUTANDO O APLICATIVO.............................................................................................................................................165
REVENDO O BANCO DE DADOS......................................................................................................................................... 172
RESUMO...................................................................................................................................................................... 173
RECURSOS ADICIONAIS....................................................................................................................................................173
RESUMO...................................................................................................................................................................... 173
08 - ASSOCIAÇÃO E ADMINISTRAÇÃO................................................................................................................... 175

O que você vai aprender:......................................................................................................................................175


ESSES RECURSOS ESTÃO INCLUÍDOS NO TUTORIAL:................................................................................................................175
Adicionar um administrador................................................................................................................................176
Restringir o acesso para a página de administração..............................................................................................181
Adicionar uma pasta de administração e a página...............................................................................................................181
Adicionar um arquivo Web. config......................................................................................................................................182
Incluindo navegação do administrador...................................................................................................................182
Habilitando a administração de produtos..............................................................................................................183
Validação discreta................................................................................................................................................................191
Expressões regulares...........................................................................................................................................................191
Controle fileUpload............................................................................................................................................................. 192
Vinculação do modelo......................................................................................................................................................... 192
Como o aplicativo funcionará.................................................................................................................................194
Executando o aplicativo........................................................................................................................................195
Resumo...................................................................................................................................................................199
09 - ROTEAMENTO DE URL................................................................................................................................... 200

O que você vai aprender:......................................................................................................................................200


VISÃO GERAL DE ROTEAMENTO DO ASP.NET.....................................................................................................................200
Rotas........................................................................................................................................................................200

3
Padrões de URL........................................................................................................................................................201
Mapeamento e registro de rotas............................................................................................................................201
Recuperando e usando dados de rota.................................................................................................................204
Rotas de configuração.............................................................................................................................................204
Habilitar rotas para categorias e produtos..........................................................................................................................204
Adicione código para detalhes do produto..........................................................................................................................207
Executando o aplicativo........................................................................................................................................208
RESUMO.........................................................................................................................................................................208
10 - TRATAMENTO DE ERROS DO ASP.NET............................................................................................................ 209
O QUE VOCÊ VAI APRENDER:............................................................................................................................................209
VISÃO GERAL................................................................................................................................................................ 209
Classe de exceção..................................................................................................................................................209
Hierarquia de herança de exceção......................................................................................................................210
Hierarquia de manipulação de exceção..............................................................................................................210
Manipulação de erro de nível aplicação.............................................................................................................210
Manipulação de eventos de erro de nível de página.........................................................................................211
Código manipulação de erro de nível.................................................................................................................212
ADICIONANDO SUPORTE DE LOG DE ERRO...........................................................................................................................213
Adicionando uma página de erro........................................................................................................................215
Exibindo mensagens de erro do aplicativo.........................................................................................................219
Atualize a configuração....................................................................................................................................................219
Executando o aplicativo....................................................................................................................................................220
Incluindo uma exceção para fins de teste...........................................................................................................220
Executando o aplicativo....................................................................................................................................................221
Adicionando a manipulação de erro de aplicativo-nível..................................................................................222
Executando o aplicativo....................................................................................................................................................223
Adicionando a manipulação de erro de nível de página..................................................................................224
Executando o aplicativo....................................................................................................................................................225
Removendo a exceção usada para testes............................................................................................................226
Adicionando o log de erro de nível de código....................................................................................................226
Inspecionando as informações de log de erro....................................................................................................228
Mensagens de erro seguras..................................................................................................................................229
USANDO O ELMAH.......................................................................................................................................................229
Visualização do Log ELMAH.................................................................................................................................231
RESUMO...................................................................................................................................................................... 232
CONCLUSÃO................................................................................................................................................................. 232
RECURSOS ADICIONAIS....................................................................................................................................................232
AGRADECIMENTOS.........................................................................................................................................................232
CONTRIBUIÇÕES DA COMUNIDADE....................................................................................................................................233
INFORMAÇÕES DO AUTOR................................................................................................................................................233

4
01 - Introdução ao ASP.NET 4.5 Web
Forms e Visual Studio 2013
Introdução
Esta série de tutoriais orienta você através dos passos necessários para criar um aplicativo de
formulários da Web ASP.NET usando o Visual Studio Express 2013 para Web e 4.5 do ASP.NET.

O aplicativo que você vai criar chama-se Wingtip Toys. É um exemplo simplificado de um site de
frente de loja que vende itens on-line. Esta série de tutoriais destaques novos recursos disponíveis
no ASP.NET 4.5.

Comentários são bem-vindos, e nós vamos fazer todos os esforços para atualizar esta série de
tutoriais com base em suas sugestões.

Download do projeto concluído

Você pode baixar um projeto c# que contém o tutorial completo.

 Introdução ao ASP.NET 4.5 Web Forms e Visual Studio 2013 - Wingtip Toys (C#)

Revisão do conteúdo, tomando o quiz de ASP.NET Web Formulários relacionado


Depois de concluir este tutorial, teste os seus conhecimentos e reforçar conceitos-chave, tendo o
Quiz de formulários da Web do ASP.NET . Este questionário foi projetado especificamente do
conteúdo contido nesta série tutorial. Cada pergunta no questionário fornece uma explicação
juntamente com links para orientação adicional.

 ASP.NET Web Formulários Quiz

Audiência

O público-alvo desta série de tutoriais é formado por desenvolvedores experientes que são
novatos no uso do ASP.NET Web Forms. Um desenvolvedor interessado nesta série tutorial deve
ter as seguintes habilidades:

 Familiar com um objeto orientado a linguagem de programação (OOP)

 Familiarizado com os conceitos de desenvolvimento Web (HTML, CSS, JavaScript)

 Familiarizado com os conceitos de banco de dados relacional

 Familiarizado com os conceitos de arquitetura n-tier

Se você está interessado em rever as áreas listadas acima, considere-se de revisar o conteúdo a
seguir:
5
 Introdução ao Visual c#
 Desenvolvimento web, HTML, CSS, JavaScript, SQL, PHP, JQuery

 Banco de dados relacional


 Arquitetura de várias camadas

Características do aplicativo

Os recursos de formulário da Web ASP.NET apresentados nesta série incluem:

 O projeto de aplicativo Web (não o projeto de Web Site)

 Formulários da Web

 Páginas mestras, configuração

 Bootstrap

 Entity Framework código primeiro, LocalDB

 Validação de solicitação

 Rigidez de controles de dados, modelo de vinculação, anotações de dados e provedores de


valor
 OAuth e OpenID

 Identidade do ASP.NET, configuração e autorização

 Validação discreta

 Roteamento

 Tratamento de erros do ASP.NET

Tarefas e cenários de aplicativos

Tarefas demonstradas nesta série incluem:

 Criação, revisão e execução do projeto novo

 Criando a estrutura de banco de dados

 Inicializando e preparação do banco de dados

 Personalizando a interface do usuário usando estilos, gráficos e uma página-mestre

 Adição de páginas e navegação

 Exibindo detalhes do menu e dados do produto

 Criando um carrinho de compras

 Adicionando suporte a OpenID

 Adicionando um método de pagamento

 Incluindo uma função de administrador e um usuário para o aplicativo

 Restringir o acesso a páginas específicas e pasta

6
 Carregando um arquivo para o aplicativo da web

 Implementação de validação de entrada

 Registrar rotas para o aplicativo da web

 Manipulação de erro e log de erro de execução

Visão geral
Se você é novo no ASP.NET Web Forms mas tem familiaridade com conceitos de programação,
você tem o tutorial certo. Se você já está familiarizado com Web Forms do ASP.NET, você pode
beneficiar desta série de tutoriais por novos recursos disponíveis no ASP.NET 4.5. Se você não
estiver familiarizado com formulários da Web ASP.NET e conceitos de programação, consulte os
tutoriais adicionais fornecidos na seção Web Forms Começando no site da Web do ASP.NET.

Os recursos específicos mais recente ASP.NET 4.5 fornecidos nesta série tutorial Web Forms
incluem o seguinte:
 Uma interface de usuário simples para criação de projetos que oferecem suporte para
múltiplas estruturas do ASP.NET (Web Forms, MVC e Web API).
 Quadro Bootstrap, um layout e temas que fornece recursos de design e temas sensíveis.
 Identidade do ASP.NET, um novo sistema de associação do ASP.NET que funciona da
mesma maneira em todos os quadros ASP.NET e trabalha com web hosting software diferente
do IIS.
 6 estrutura de entidade, uma atualização para o Entity Framework que permite que você
recuperar e manipular dados como objetos com rigidez de tipos, acesso a dados assíncronos,
lidar com falhas de conexão transitória e instruções SQL de log.

Para uma lista completa dos recursos do ASP.NET 4.5, consulte ASP.NET e Web Tools para Visual
Studio 2013 notas de lançamento.

O aplicativo de exemplo do Wingtip Toys

As capturas de tela a seguir fornecem uma visão rápida do aplicativo ASP.NET Web formulários
que você irá criar nesta série tutorial. Quando você executar o aplicativo do Visual Studio Express
2013 para Web, você verá a seguinte página da web em casa.

7
Você pode se registrar como um novo usuário, ou login como um usuário existente. Navegação é
fornecida no topo de cada categoria de produto, recuperando os produtos disponíveis no banco
de dados.

Selecionando o link de produtos, você poderá ver uma lista de todos os produtos disponíveis.

Você também pode ver detalhes do produto individual, selecionando qualquer um dos produtos
listados.

8
Como um usuário, você pode registrar e faça o login usando a funcionalidade padrão do modelo
de Web Forms. Este tutorial também explica como fazer o login usando uma conta existente do
Gmail. Além disso, você pode logar como o administrador adicionar e remover produtos do banco
de dados.

Uma vez que você tiver conectado como um usuário, você pode adicionar produtos ao carrinho de
compras e checkout com PayPal. Observe que esse aplicativo de exemplo é projetado para
funcionar com o sandbox de desenvolvedores do PayPal. Nenhuma transação de dinheiro real terá
lugar.

9
PayPal vai confirmar sua conta, ordem e informações de pagamento.

Depois de retornar do PayPal, você pode rever e concluir a sua encomenda.


10
Pré-requisitos
Antes de começar, certifique-se de que você tem o seguinte software instalado no seu
computador:

 Microsoft Visual Studio 2013 ou Microsoft Visual Studio Express 2013 para Web . O .NET
Framework é instalado automaticamente.

Esta série de tutoriais usa o Microsoft Visual Studio Express 2013 para Web. Você pode usar o
Microsoft Visual Studio Express 2013 para Web ou Microsoft Visual Studio 2013 para completar
esta série de tutoriais.

Nota  

Microsoft Visual Studio 2013 e Microsoft Visual Studio Express 2013 para Web serão muitas vezes
referido como o Visual Studio em toda esta série de tutoriais.

Se você já tem uma versão do Visual Studio instalada, o processo de instalação irá instalar Visual
Studio 2013 ou Microsoft Visual Studio Express 2013 para Web ao lado a versão existente. Sites
que você criou em versões anteriores podem ser abertos no Visual Studio 2013 e continuam a abrir
em versões anteriores.

Nota  

Esta explicação passo a passo presume que você selecionou a coleção de configurações de
Desenvolvimento Web a primeira vez que você começou a Visual Studio. Para obter mais
informações, consulte como: selecionar configurações de ambiente de desenvolvimento Web .

Baixar o aplicativo de exemplo


11
Depois de instalar os pré-requisitos, você está pronto para começar a criar o novo projeto de Web
que é apresentado nesta série tutorial. Se você gostaria de , opcionalmente, executar o aplicativo
de exemplo que cria esta série de tutoriais, você pode baixá-lo a partir do site de exemplos do
MSDN. Este download contém o seguinte:
 O aplicativo de exemplo na pasta WingtipToys .
 Os recursos utilizados para criar o aplicativo de exemplo na pasta WingtipToys-ativos na
pasta WingtipToys .

Baixe o arquivo do site de exemplos do MSDN:


Introdução ao ASP.NET 4.5 Web Forms e Visual Studio 2013 - Wingtip Toys (C#)

O download é um arquivo . zip . Para ver o projeto concluído que cria esta série de tutoriais,
localize e selecione a pasta C# no arquivo . zip . Salve a pasta de C# para a pasta que você usar
para trabalhar com projetos de Visual Studio de 2013. Por padrão, a pasta de projetos do Visual
Studio de 2013 é o seguinte:

C:\Users\ < username > \Documents\Visual studio 2013\Projects

Renomeie a pasta c# para WingtipToys .

Nota  

Se você já tiver uma pasta chamada WingtipToys na sua pasta de projetos, temporariamente
renomear essa pasta existente antes de renomear a pasta c# para WingtipToys.

Para executar o projeto concluído, abra a pasta WingtipToys e clique duas vezes no arquivo
WingtipToys.sln . Visual Studio 2013 irá abrir o projeto. Em seguida, clique no arquivo aspx na
janela Solution Explorer e clique em Exibir no navegador no menu de atalhos.

Comentários e apoio tutorial


Use a seção de Q e uma incluído com o exemplo Começando com 4.5 ASP.NET Web Forms e
Visual Studio 2013 - Wingtip Toys (c#) para quaisquer perguntas ou comentários.

Comentários sobre esta série de tutoriais são bem-vindos, e quando esta série de tutoriais é
atualizado todo esforço será feito para levar em conta correções ou sugestões de melhorias que
são fornecidas nos comentários tutorial.

Quando um erro acontece durante o desenvolvimento, ou se o site não funciona corretamente, as


mensagens de erro podem dar pistas complexas para a fonte do problema ou não podem explicar
como corrigir isso. Para ajudá-lo com alguns cenários comuns de problema, você também pode
usar o ASP.NET fóruns ou a Q e uma seção incluído com o exemplo Começando com 4.5 ASP.NET
Web Forms e Visual Studio 2013 - Wingtip Toys (c#). Se você receber uma mensagem de erro ou
alguma coisa não funciona como você atravessa os tutoriais, certifique-se de verificar os locais
acima.

12
13
02 - Criar o projeto

Neste tutorial você vai criar, revisar e executar o projeto padrão no Visual Studio, que permitirá que
você se familiarize com os recursos do ASP.NET. Além disso, você revisará o ambiente do Visual
Studio.

O que você vai aprender:


 Como criar um novo projeto de Web Forms.

 A estrutura de arquivos do projeto Web Forms.

 Como executar o projeto no Visual Studio.

 As diferentes características do aplicativo de formulários da Web padrão.

 Algumas noções básicas sobre como usar o ambiente Visual Studio.

Criando o projeto
1. Abra o Visual Studio.

2. Selecione New Project no menu arquivo no Visual Studio.

3. Selecione os modelos -> Visual c# -> grupo de modelos Web à esquerda.

4. Escolha o modelo de aplicativo da Web do ASP.NET na coluna central.

5. Nomeie o projeto WingtipToys e escolha o botão OK .

14
Nota O nome do projeto nesta série tutorial é WingtipToys. É recomendável que você use esse
nome exato do projeto para que o código fornecido ao longo da série tutorial funções conforme o
esperado.

6. Em seguida, selecione o modelo de Formulários da Web e escolha o botão de Criar o


projeto .

15
O projeto levará um breve período de tempo para ser criado. Quando estiver pronto, abra a página
Default. aspx .

Você pode alternar entre o modo de exibição Design e exibição da fonte , selecionando uma
opção na parte inferior da janela do centro. O modo design exibe páginas da Web ASP.NET,
páginas mestras, páginas de conteúdo, páginas HTML e controles de usuário usando um modo de
exibição próximo a WYSIWYG. Fonte exibe a marcação HTML para sua página Web, que você pode
editar.

Noções básicas sobre os quadros ASP.NET


ASP.NET Web Forms permite construir sites dinâmicos usando um modelo familiar de arrastar-e-
soltar, orientada a eventos. Uma superfície de design e centenas de componentes e controles
permitem que você rapidamente criar sites sofisticados, poderosos orientado a interface do usuário
com acesso a dados. A loja de brinquedos do Wingtip é baseada em Web Forms do ASP.NET, mas
muitos dos conceitos que você aprendeu nesta série tutorial são aplicáveis a todos do ASP.NET.

ASP.NET oferece quatro estruturas de desenvolvimento primário:

 Web Forms do ASP.NET

A estrutura de formulários da Web alvo desenvolvedores que preferem a programação declarativa


e baseado no controle, como Microsoft Windows Forms (WinForms) e XAML/WPF/Silverlight.
Oferece um modelo de desenvolvimento orientado para o designer WYSIWYG, por isso é popular
16
entre os desenvolvedores à procura de um ambiente de desenvolvimento (RAD) rápido de
aplicativos para desenvolvimento web. Se você é novo em programação web e está familiarizados
com as ferramentas de desenvolvimento de cliente Microsoft RAD tradicionais (por exemplo, para
Visual Basic e Visual c#), você pode criar rapidamente um aplicativo da web sem ter experiência em
HTML e JavaScript.

 ASP.NET MVC
ASP.NET MVC alvo são os desenvolvedores que estão interessados em padrões e princípios como
o desenvolvimento orientado a testes, separação de preocupações, inversão de controle (IoC) e
injeção de dependência (DI). Este quadro incentiva separando a camada de lógica de negócios de
uma aplicação web de sua camada de apresentação.

 Páginas da Web ASP.NET


Páginas da Web ASP.NET destina a desenvolvedores que querem uma história de desenvolvimento
web simples, ao longo das linhas de PHP. No modelo de páginas da Web, você pode cria páginas
HTML e em seguida, adicione código baseado em servidor para a página a fim de controlar
dinamicamente como essa marcação é processada. Páginas da Web é especificamente projetado
para ser uma estrutura leve, e é o ponto de entrada mais fácil em ASP.NET para pessoas que sabem
HTML mas pode não ter experiência de programação ampla — por exemplo, estudantes ou
amadores. É também uma boa maneira para os desenvolvedores web que sabe PHP ou estruturas
similares para começar a usar o ASP.NET.

 Aplicação de página ASP.NET Single


Aplicação de página ASP.NET Single (SPA) ajuda a construir aplicações que incluem interações
significativas do lado do cliente usando o HTML 5, CSS 3 e JavaScript. O ASP.NET e Web 2012.2 a
atualização das ferramentas é fornecido um novo modelo para a construção de aplicações de única
página usando a API knockout.js e ASP.NET Web. Além do novo modelo SPA, novos modelos
criados pelo comunidade do SPA também estão disponíveis para download.

Além dos quatro quadros de desenvolvimento principal, o ASP.NET também oferece tecnologias
adicionais que são importantes para estar ciente e familiarizado com, mas não são abordadas nesta
série tutorial:

 ASP.NET Web API – um framework para construção de serviços HTTP que alcançam uma
ampla gama de clientes, incluindo os navegadores e dispositivos móveis.
 ASP.NET SignalR - uma biblioteca que facilita a funcionalidade em desenvolvimento de web
em tempo real.

Revisão do projeto
No Visual Studio, a janela Solution Explorer permite que você gerencie arquivos para o projeto.
Vamos dar uma olhada nas pastas que foram adicionados ao seu aplicativo em Gerenciador de
soluções. O modelo de aplicativo da web adiciona uma estrutura de pasta básica:

17
O Visual Studio cria alguns arquivos e pastas iniciais para seu projeto. Os primeiros arquivos com
os quais você trabalhará mais adiante neste tutorial são os seguintes:

Arquivo Finalidade

Default. Normalmente a primeira página exibida quando o aplicativo é executado em um


aspx navegador.

Site. Uma página que permite criar um layout consistente e usar um comportamento padrão
Master nas páginas do seu aplicativo.

Global. Um arquivo opcional que contém código para responder a eventos de nível de
asax aplicativo e sessão-nível gerados pelo ASP.NET ou por módulos HTTP.

Web. Os dados de configuração para um aplicativo.

18
config

Executando o aplicativo da Web padrão

O aplicativo da Web padrão fornece uma rica experiência baseada na funcionalidade incorporada e
suporte. Sem qualquer alteração de projeto de formulários da Web padrão, o aplicativo está
pronto para ser executado no navegador da Web local.

1. Pressione a tecla F5 no Visual Studio.


O aplicativo irá construir e exibir no navegador da Web.

2. Depois de ter concluído a revisão do aplicativo em execução, feche a janela do navegador.

Existem três principais páginas neste aplicativo da Web padrão: Default. aspx (Home), about. aspxe
Contact.aspx. Cada uma dessas páginas pode ser alcançada a partir da barra de navegação
superior. Há também duas páginas adicionais contidas na pasta de conta, a página Register. aspx e
a página login. aspx. Estas duas páginas permitem que você use os recursos de associação do
ASP.NET para criar, armazenar e validar as credenciais do usuário.

ASP.NET Web Formulários plano de fundo


Web Forms do ASP.NET são páginas que são baseadas na tecnologia Microsoft ASP.NET, no qual o
código que é executado no servidor dinamicamente gera saída de página da Web para o
19
dispositivo de navegador ou cliente. Uma página de formulários da Web ASP.NET
automaticamente processa o HTML compatível com o navegador correto para recursos, como
estilos, layout e assim por diante. Formulários da Web são compatíveis com qualquer idioma
suportado pelo .NET common language runtime, tais como o Microsoft Visual Basic e Visual c#.
Além disso, Web Forms são construídas sobre o Microsoft .NET Framework, que fornece benefícios
como um ambiente gerenciado, segurança de tipos e herança.

Quando uma página de Web Forms do ASP.NET é executado, a página passa por um ciclo de vida
em que ele executa uma série de etapas de processamento. Estas etapas incluem inicialização,
instanciando controles, restaurar e manter o estado, executando o código manipulador de eventos
e renderização. Como você se familiarizar com o poder da Web Forms do ASP.NET, é importante
para você entender o ciclo de vida de página do ASP.NET que você pode escrever o código no
estágio do ciclo de vida apropriado para o efeito que pretende.

Quando um servidor Web recebe uma solicitação para uma página, ele localiza a página, processa-
a, envia-a ao navegador e, em seguida, descarta todas as informações da página. Se o usuário
solicitar a mesma página novamente, o servidor repetirá a sequência inteira, reprocessando a
página do zero. Dito de outra forma, um servidor não tem memória das páginas que ele tenha
processado — páginas são apátridas. A estrutura da página ASP.NET automaticamente manipula a
tarefa de manter o estado da sua página e seus controles, e que lhe fornece maneiras explícitas
para manter o estado de informações específicas do aplicativo.

Recursos de aplicativo da Web no modelo de aplicativo de formulários Web


O modelo de aplicativo de formulários da Web do ASP.NET fornece um rico conjunto de
funcionalidades internas. Isso não só proporciona-lhe uma página Home. aspx , uma página. aspx ,
uma página de Contact.aspx , mas também inclui a funcionalidade de adesão que registra usuários
e salva suas credenciais para que eles podem aceder ao seu site. Esta visão geral fornece mais
informações sobre algumas das características contidas do modelo de aplicativo de formulários da
Web do ASP.NET e como eles são usados no aplicativo Wingtip Toys.

Associação
ASP.NETIdentidade armazena as credenciais dos usuários em um banco de dados criado pelo
aplicativo. Quando os usuários efetuar login, o aplicativo valida suas credenciais através da leitura
do banco de dados. A pasta Account do seu projeto contém os arquivos que implementam as
várias partes da associação: registro, logon, alteração de uma senha e autorização de acesso. Além
disso, o ASP.NET Web Forms oferece suporte a OAuth e OpenID. Esses aprimoramentos de
autenticação permitem que os usuários façam logon no seu site usando credenciais existentes, de
contas como Facebook, Twitter, Windows Live e Google.

20
Por padrão, o modelo cria um banco de dados de associação usando um nome de banco de dados
padrão em uma instância do SQL Server Express LocalDB, o servidor de banco de dados de
desenvolvimento que vem com o Visual Studio Express 2013 para Web.

SQL Server Express LocalDB


SQL Server Express LocalDB é uma versão leve do SQL Server que possui muitos recursos de
programabilidade de um banco de dados do SQL Server. SQL Server Express LocalDB é executado
no modo de usuário e tem uma instalação rápida, configuração zero que tem uma pequena lista de
pré-requisitos de instalação. No Microsoft SQL Server, qualquer banco de dados ou código
Transact-SQL pode ser movido de SQL Server Express LocalDB para SQL Server e SQL Azure sem
quaisquer etapas de atualização. Então, SQL Server Express LocalDB pode ser usado como um
ambiente de desenvolvedor para aplicações como alvo todas as edições do SQL Server. SQL Server

21
Express LocalDB permite que recursos como procedimentos armazenados, funções definidas pelo
usuário e agregados, integração do .NET Framework, tipos espaciais e outros que não estão
disponíveis no SQL Server Compact.

Páginas mestras
Uma página mestra ASP.NET define uma aparência consistente e comportamento para todas as
páginas em seu aplicativo. O layout da página mestra funde-se com o conteúdo de uma página de
conteúdo individual para produzir a última página que o usuário vê. No aplicativo Wingtip Toys,
você modifica a página mestra Site.Master para que todas as páginas no site do Wingtip Toys
compartilhem o mesmo logotipo distintivo e a barra de navegação.

HTML5
O modelo de aplicativo de formulários da Web ASP.NET suporta HTML5, que é a mais recente
versão da linguagem de marcação HTML. HTML5 oferece suporte a novos elementos e
funcionalidades que tornam mais fácil criar sites da Web.

Modernizr
Para navegadores que não oferecem suporte a HTML5, você pode usar o Modernizr. Modernizr é
uma biblioteca JavaScript open source que pode detectar se um navegador suporta recursos de
HTML5 e habilitá-los, se isso não acontecer. No modelo de aplicativo de formulários da Web do
ASP.NET, o Modernizr é instalado como um pacote NuGet.

Bootstrap
Os modelos de projeto Visual Studio 2013 usam Bootstrap, um layout e temas quadro criado pelo
Twitter. Bootstrap usa CSS3 para fornecer design responsivo, que significa layouts dinamicamente
podem adaptar-se aos tamanhos de janela de navegador diferente. Você também pode usar o
recurso de temas do Bootstrap para facilmente efetuar uma mudança na aparência do aplicativo.
Por padrão, o modelo de aplicativo da Web do ASP.NET no Visual Studio 2013 inclui Bootstrap
como um pacote NuGet.

Pacotes NuGet
O modelo de aplicativo de formulários da Web ASP.NET inclui um conjunto de pacotes NuGet .
Esses pacotes oferecem funcionalidade modular na forma de bibliotecas de código aberto e
ferramentas. Há uma grande variedade de pacotes para ajudá-lo a criar e testar seus aplicativos.
Visual Studio torna fácil adicionar, remover e atualizar pacotes NuGet. Os desenvolvedores podem
criar e adicionar pacotes NuGet também.

22
Quando você instala um pacote, o NuGet copia arquivos para sua solução e automaticamente faz
com que as mudanças são necessárias, tais como adicionar referências e mudando você tem a
configuração associada com seu aplicativo da Web. Se você decidir remover a biblioteca, o NuGet
remove arquivos e reverte as mudanças que fez em seu projeto para que a desordem não é
deixada. NuGet está disponível no menu ferramentas no Visual Studio.

jQuery
jQuery é uma biblioteca JavaScript rápida e concisa que simplifica o HTML documento
atravessando, manipulação de eventos, animação e interações Ajax para desenvolvimento web
rápido. A biblioteca JavaScript jQuery é incluída no modelo de aplicativo de formulários da Web do
ASP.NET como um pacote NuGet.

Validação discreta
Controles de validação interna foram configurados para usar JavaScript discreta para a lógica de
validação do lado do cliente. Isso significativamente reduz a quantidade de JavaScript processado
embutido na marcação da página e reduz o tamanho total da página. Discreta validação é
adicionada globalmente para o modelo de aplicativo de formulários da Web do ASP.NET com base
na configuração no elemento < appSettings > do arquivo Web. config na raiz do aplicativo.

Entity Framework Code First


Além das características do modelo de aplicativo de formulários da Web do ASP.NET, o aplicativo
do Wingtip Toys usa Entity Framework Code First, que é uma biblioteca de NuGet que permite o
desenvolvimento centrado no código quando você trabalhar com dados. Simplificando, ele cria a
parte de banco de dados do seu aplicativo com base no código que você escreve. Usando o Entity
Framework, recuperar e manipular dados como objetos com rigidez de tipos. Esta função permite

23
que você se concentrar na lógica de negócios em seu aplicativo, em vez dos detalhes de como os
dados são acessados.

Para obter informações adicionais sobre as bibliotecas instaladas e os pacotes incluídos com o
modelo de Web Forms do ASP.NET, consulte a lista de pacotes NuGet instalados. Para fazer isso,
no Visual Studio cria um novo projeto de formulários da Web, selecione ferramentas ->
Gerenciador de pacotes da biblioteca -> Gerenciar pacotes de NuGet para soluçãoe selecione
pacotes instalados na caixa de diálogo Gerenciar pacotes de NuGet .

Tour pelo Visual Studio


Os principais windows no Visual Studio incluem o Solution Explorer, o Server Explorer (Database
Explorer no expresso), a Janela de propriedades, a caixa de ferramentas, a barra de
ferramentase a Janela do documento.

Para obter mais informações sobre Visual Studio, consulte Guia Visual de Visual Web Developer.

Resumo
Neste tutorial você criou, revisto e executar o aplicativo de formulários da Web padrão. Você tem
analisado as características diferentes do aplicativo de formulários da Web padrão e aprendeu
algumas noções básicas sobre como usar o ambiente Visual Studio. Nos seguintes tutoriais você
vai criar a camada de acesso de dados.

24
03 - Criar a camada de acesso a dados
Este tutorial descreve como criar, acessar e analisar dados de um banco de dados usando Web
Forms do ASP.NET e Entity Framework Code First. Este tutorial baseia-se no tutorial anterior "Criar
o projeto" e faz parte da série tutorial Wingtip Toy Store. Quando tiver completado este tutorial,
você vai ter construído um grupo de classes de acesso a dados que estão na pasta de modelos do
projeto.

O que você vai aprender:


 Como criar os modelos de dados.

 Como inicializar e o banco de dados de sementes.

 Como atualizar e configurar o aplicativo para oferecer suporte a banco de dados.

Estes são os recursos introduzidos no tutorial:

 Entity Framework Code First

 LocalDB

 Anotações de dados

Criando os modelos de dados


Entity Framework é um framework de mapeamento objeto-relacional (ORM). Ele permite que você
trabalhe com dados relacionais como objetos, eliminando a maior parte do código de acesso a
dados que você geralmente precisa escrever. Usando o Entity Framework, você pode emitir
consultas usando LINQ, em seguida, recuperar e manipular dados como objetos com rigidez de
tipos. LINQ fornece padrões para consultar e atualizar dados. Usar o Entity Framework permite que
você se concentrar em criar o resto do seu aplicativo, em vez de enfocando os dados fundamentos
de acesso. Mais tarde na série neste tutorial, mostraremos como usar os dados para preencher a
navegação e produto de consultas.

Entity Framework oferece suporte a um paradigma de desenvolvimento chamado Code First.


Código primeiro permite que você defina seus modelos de dados usando classes. Uma classe é
uma construção que permite que você crie seus próprios tipos personalizados agrupando variáveis
de outros tipos, métodos e eventos. Você pode mapear classes para um banco de dados existente
ou usá-los para gerar um banco de dados. Neste tutorial, você vai criar os modelos de dados
escrevendo classes de modelo de dados. Então, vou deixar o Entity Framework criar banco de
dados em tempo real dessas novas classes.

Você começará criando as classes de entidade que definem os modelos de dados para o aplicativo
de formulários da Web. Em seguida, você criará uma classe de contexto que gerencia as classes de
entidade e fornece acesso a dados no banco de dados. Você também criará uma classe de
inicializador que você usará para preencher o banco de dados.

25
Referências e entity Framework
Por padrão, o Entity Framework está incluído quando você criar um novo aplicativo da Web
ASP.NET usando o modelo de Web Forms . Entity Framework pode ser instalado, desinstalado e
atualizado como um pacote NuGet.

Este pacote NuGet inclui os seguintes módulos de tempo de execução dentro de seu projeto:

 EntityFramework.dll – todo o código comum tempo de execução usado pelo Entity


Framework
 EntityFramework.SqlServer.dll – o provedor Microsoft SQL Server para o Entity Framework

Classes de entidade

As classes que você cria para definir o esquema dos dados são chamadas de classes de entidade.
Se você é novo para o projeto de banco de dados, pense as classes de entidade, como definições
de tabela de um banco de dados. Cada propriedade da classe especifica uma coluna na tabela do
banco de dados. Essas classes fornecem uma interface leve, objeto-relacional entre código
orientado a objeto e a estrutura de tabela relacional de banco de dados.

Neste tutorial, você vai começar adicionando classes de entidade simples que representam os
esquemas para produtos e categorias. A classe de produtos irá conter as definições para cada
produto. O nome de cada um dos membros da classe de produto será ProductID, ProductName,
Description, ImagePath, UnitPrice, CategoryIDe Category. A classe de categoria irá conter as
definições para cada categoria de um produto pode pertencer, como carro, barco ou avião. O
nome de cada um dos membros da classe de categoria será CategoryID, CategoryName,
Descriptione Products. Cada produto pertence a uma das categorias. Essas classes de entidade
serão adicionados à pasta de modelos do projeto existente.

1. No Solution Explorer, clique com botão direito na pasta de modelos e em seguida


selecione Add -> New Item.

26
Caixa de diálogo Add New Item é exibida.

2. No Visual c#, no painel Instalado à esquerda, selecione Código.

27
3. Selecione classe do painel do meio e o nome desta nova classe Product.cs.

4. Clique em Adicionar.
O novo arquivo de classe é exibido no editor.

5. Substitua o código padrão com o seguinte código:

using System.ComponentModel.DataAnnotations;

namespace WingtipToys.Models
{
public class Product
{
[ScaffoldColumn(false)]
public int ProductID { get; set; }

[Required, StringLength(100), Display(Name = "Name")]


public string ProductName { get; set; }

[Required, StringLength(10000), Display(Name = "Product Description"),


DataType(DataType.MultilineText)]
public string Description { get; set; }

public string ImagePath { get; set; }

[Display(Name = "Price")]
public double? UnitPrice { get; set; }

public int? CategoryID { get; set; }

public virtual Category Category { get; set; }


}

6. Criar outra classe, repetindo as etapas 1 a 4, no entanto, o nome da nova classe Category.cs
e substitua o código padrão com o seguinte código:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace WingtipToys.Models
{
public class Category
{

28
[ScaffoldColumn(false)]
public int CategoryID { get; set; }

[Required, StringLength(100), Display(Name = "Name")]


public string CategoryName { get; set; }

[Display(Name = "Product Description")]


public string Description { get; set; }

public virtual ICollection<Product> Products { get; set; }


}

Como mencionado anteriormente, a Category classe representa o tipo de produto que o aplicativo
é projetado para vender (tais como "Carros", "Barcos", "Foguetes" e assim por diante), e a classe de
Product representa os produtos individuais (brinquedos) no banco de dados. Cada instância de um
objeto Product corresponderá a uma linha dentro de uma tabela de banco de dados relacional, e
cada propriedade da classe de produto serão mapeados para uma coluna na tabela de banco de
dados relacional. No final deste tutorial, você vai analisar os dados do produto contidos no banco
de dados.

Anotações de dados
Você deve ter notado que alguns membros das classes têm atributos especificando detalhes sobre
o membro, como [ScaffoldColumn(false)]. Estas são anotações de dados. Os atributos de
anotação de dados podem descrever como validar entrada do usuário para esse membro, para
especificar a formatação para ele e para especificar como ele é modelado quando o banco de
dados é criado.

Classe de contexto
Para começar a usar as classes para acesso a dados, você deve definir uma classe de contexto.
Como mencionado anteriormente, a classe de contexto gerencia as classes de entidade (por
exemplo, a classe de Product e a classe de Category ) e fornece acesso a dados no banco de dados.

Esse procedimento adiciona uma nova classe de contexto c# para a pasta de modelos .

1. Clique com o botão direito do mouse na pasta Models e, em seguida, selecione Add ->
New Item.
Caixa de diálogo Add New Item é exibida.

2. Selecione classe de painel do meio, o nome ProductContext.cs e clique em Adicionar.

3. Substitua o código padrão contido na classe com o código a seguir:

using System.Data.Entity;

29
namespace WingtipToys.Models
{
public class ProductContext : DbContext
{
public ProductContext() : base("WingtipToys")
{
}
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}

Este código adiciona o namespace System.Data.Entity para que você tenha acesso a todas as
funcionalidades do núcleo do Entity Framework, que inclui a capacidade de consultar, inserir,
atualizar e excluir dados ao trabalhar com objetos com rigidez de tipos.

A classe ProductContext representa o contexto de banco de dados de produto do Entity


Framework, que lida com a busca, armazenar e atualizar instâncias de classe de Product no banco
de dados. O ProductContext classe deriva da classe base DbContext fornecida pelo Entity
Framework.

Classe de inicializador

Você precisará executar alguma lógica personalizada para inicializar o banco de dados na primeira
vez em que o contexto for usado. Isso permitirá que dados de semente a ser adicionado ao banco
de dados para que você possa exibir imediatamente produtos e categorias.

Esse procedimento adiciona uma nova classe de inicializador c# para a pasta de modelos .

1. Criar outra Class na pasta de modelos e o nome ProductDatabaseInitializer.cs.

2. Substitua o código padrão contido na classe com o código a seguir:

using System.Collections.Generic;
using System.Data.Entity;

namespace WingtipToys.Models
{
public class ProductDatabaseInitializer :
DropCreateDatabaseIfModelChanges<ProductContext>
{
protected override void Seed(ProductContext context)
{
GetCategories().ForEach(c => context.Categories.Add(c));
GetProducts().ForEach(p => context.Products.Add(p));
}

30
private static List<Category> GetCategories()
{
var categories = new List<Category> {
new Category
{
CategoryID = 1,
CategoryName = "Cars"
},
new Category
{
CategoryID = 2,
CategoryName = "Planes"
},
new Category
{
CategoryID = 3,
CategoryName = "Trucks"
},
new Category
{
CategoryID = 4,
CategoryName = "Boats"
},
new Category
{
CategoryID = 5,
CategoryName = "Rockets"
},
};

return categories;
}

private static List<Product> GetProducts()


{
var products = new List<Product> {
new Product
{
ProductID = 1,
ProductName = "Convertible Car",
Description = "This convertible car is fast! The engine is powered
by a neutrino based battery (not included)." +
"Power it up and let it go!",
ImagePath="carconvert.png",
UnitPrice = 22.50,
CategoryID = 1
},
new Product
{
ProductID = 2,
ProductName = "Old-time Car",

31
Description = "There's nothing old about this toy car, except it's
looks. Compatible with other old toy cars.",
ImagePath="carearly.png",
UnitPrice = 15.95,
CategoryID = 1
},
new Product
{
ProductID = 3,
ProductName = "Fast Car",
Description = "Yes this car is fast, but it also floats in
water.",
ImagePath="carfast.png",
UnitPrice = 32.99,
CategoryID = 1
},
new Product
{
ProductID = 4,
ProductName = "Super Fast Car",
Description = "Use this super fast car to entertain guests. Lights
and doors work!",
ImagePath="carfaster.png",
UnitPrice = 8.95,
CategoryID = 1
},
new Product
{
ProductID = 5,
ProductName = "Old Style Racer",
Description = "This old style racer can fly (with user
assistance). Gravity controls flight duration." +
"No batteries required.",
ImagePath="carracer.png",
UnitPrice = 34.95,
CategoryID = 1
},
new Product
{
ProductID = 6,
ProductName = "Ace Plane",
Description = "Authentic airplane toy. Features realistic color
and details.",
ImagePath="planeace.png",
UnitPrice = 95.00,
CategoryID = 2
},
new Product
{
ProductID = 7,
ProductName = "Glider",
Description = "This fun glider is made from real balsa wood. Some
assembly required.",
32
ImagePath="planeglider.png",
UnitPrice = 4.95,
CategoryID = 2
},
new Product
{
ProductID = 8,
ProductName = "Paper Plane",
Description = "This paper plane is like no other paper plane. Some
folding required.",
ImagePath="planepaper.png",
UnitPrice = 2.95,
CategoryID = 2
},
new Product
{
ProductID = 9,
ProductName = "Propeller Plane",
Description = "Rubber band powered plane features two wheels.",
ImagePath="planeprop.png",
UnitPrice = 32.95,
CategoryID = 2
},
new Product
{
ProductID = 10,
ProductName = "Early Truck",
Description = "This toy truck has a real gas powered engine.
Requires regular tune ups.",
ImagePath="truckearly.png",
UnitPrice = 15.00,
CategoryID = 3
},
new Product
{
ProductID = 11,
ProductName = "Fire Truck",
Description = "You will have endless fun with this one quarter
sized fire truck.",
ImagePath="truckfire.png",
UnitPrice = 26.00,
CategoryID = 3
},
new Product
{
ProductID = 12,
ProductName = "Big Truck",
Description = "This fun toy truck can be used to tow other trucks
that are not as big.",
ImagePath="truckbig.png",
UnitPrice = 29.00,
CategoryID = 3

33
},
new Product
{
ProductID = 13,
ProductName = "Big Ship",
Description = "Is it a boat or a ship. Let this floating vehicle
decide by using its " +
"artifically intelligent computer brain!",
ImagePath="boatbig.png",
UnitPrice = 95.00,
CategoryID = 4
},
new Product
{
ProductID = 14,
ProductName = "Paper Boat",
Description = "Floating fun for all! This toy boat can be
assembled in seconds. Floats for minutes!" +
"Some folding required.",
ImagePath="boatpaper.png",
UnitPrice = 4.95,
CategoryID = 4
},
new Product
{
ProductID = 15,
ProductName = "Sail Boat",
Description = "Put this fun toy sail boat in the water and let it
go!",
ImagePath="boatsail.png",
UnitPrice = 42.95,
CategoryID = 4
},
new Product
{
ProductID = 16,
ProductName = "Rocket",
Description = "This fun rocket will travel up to a height of 200
feet.",
ImagePath="rocket.png",
UnitPrice = 122.95,
CategoryID = 5
}
};

return products;
}
}

34
Como você pode ver o código acima, quando o banco de dados é criado e inicializado, a
propriedade de Seed é substituída e definida. Quando a Seed for definida, os valores das categorias
e produtos são usados para preencher o banco de dados. Se você tentar atualizar os dados de
semente, modificando o código acima depois que foi criado o banco de dados, você não verá
nenhuma atualização quando você executar o aplicativo da Web. A razão é que o código acima usa
uma implementação da classe DropCreateDatabaseIfModelChanges para reconhecer se o modelo
(esquema) foi alterado antes de redefinir os dados de sementes. Se nenhuma alteração será feita
para as classes de entidade Category e Product , o banco de dados não serão ser reinicializado
com os dados da semente.

Nota  

Se você quisesse o banco de dados para ser recriada a cada vez que você executou o aplicativo,
você pode usar a classe DropCreateDatabaseAlways em vez da classe
DropCreateDatabaseIfModelChanges . No entanto, para esta série de tutoriais, use a classe
DropCreateDatabaseIfModelChanges .

Neste momento, neste tutorial, você terá uma pasta de modelos com quatro novas classes e um
classe de padrão:

35
Configurando o aplicativo para usar o modelo de dados
Agora que você criou as classes que representam os dados, você deve configurar o aplicativo para
usar as classes. No arquivo global.asax, adicione o código que inicializa o modelo. No arquivo
Web.config, você adiciona informações que dizem ao aplicativo qual banco de dados você usará
para armazenar os dados que são representados pelas novas classes de dados. O arquivo global
asax pode ser usado para manipular eventos de aplicativo ou métodos. O arquivo Web. config
permite que você controle a configuração do seu aplicativo da web ASP.NET.

Atualizando o arquivo global asax


Para inicializar os modelos de dados quando o aplicativo for iniciado, você irá atualizar o
manipulador Application_Start no arquivo Global.asax.cs .

36
Nota  

No Solution Explorer, você pode selecionar o arquivo global asax ou o arquivo Global.asax.cs para
editar o arquivo Global.asax.cs .

1. Adicione o seguinte código realçado em amarelo para o método Application_Start no


arquivo Global.asax.cs .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;
using System.Data.Entity;
using WingtipToys.Models;

namespace WingtipToys
{
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

// Initialize the product database.


Database.SetInitializer(new ProductDatabaseInitializer());
}
}

Nota  

Seu navegador deve suportar HTML5 para exibir o código destacado em amarelo, ao ver esta série
de tutoriais em um navegador.

Conforme mostrado no código acima, quando o aplicativo for iniciado, o aplicativo especifica o
inicializador que será executado durante a primeira vez que os dados é acessado. Os dois
namespaces adicionais são necessários para acessar o objeto de Database e o objeto de
ProductDatabaseInitializer .

Modificar o arquivo Web. config

37
Embora o Entity Framework Code First gere um banco de dados para você em um local padrão
quando o banco de dados é populado com dados de semente, adicionar suas próprias
informações de conexão para seu aplicativo proporciona controle do local do banco de dados.
Você especifica esta conexão de banco de dados usando uma cadeia de conexão no arquivo
Web.config do aplicativo na raiz do projeto. Adicionando uma nova seqüência de conexão, você
pode direcionar a localização do banco de dados (wingtiptoys.mdf) a ser criado no diretório de
dados do aplicativo (App_Data), ao invés de seu local padrão. Fazer essa alteração permitirá que
você encontrar e inspecionar o arquivo de banco de dados no final deste tutorial.

1. No Solution Explorer, localize e abra o arquivo Web. config .

2. Adicione seqüência de conexão, destacada em amarelo para a seção <connectionStrings>


do arquivo Web. config da seguinte forma:

<connectionStrings>
<add name="DefaultConnection" connectionString="Data
Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-WingtipToys-
20131119102907.mdf;Initial Catalog=aspnet-WingtipToys-20131119102907;Integrated
Security=True"
providerName="System.Data.SqlClient" />
<add name="WingtipToys"
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|
DataDirectory|\wingtiptoys.mdf;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>

Quando o aplicativo é executado pela primeira vez, vai construir o banco de dados no local
especificado pela cadeia de conexão. Mas antes de executar o aplicativo, vamos construí-lo
primeiro.

Criando o aplicativo
Para ter certeza de que todas as classes e as alterações ao seu trabalho de aplicativo da Web, você
deve compilar o aplicativo.

1. No menu depurar , selecione Build WingtipToys.


É exibida a janela de saída , e se tudo correu bem, você verá uma mensagem de êxito .

38
Se você topar com um erro, verifique novamente os passos acima. As informações na janela de
saída irão indicar que o arquivo tem um problema e onde no arquivo uma mudança é necessária.
Esta informação permitirá que você determinar que parte das etapas acima precisam ser revisto e
corrigido em seu projeto.

Resumo
Neste tutorial da série você criou o modelo de dados, bem como adicionou o código que será
usado para inicializar e propagar o banco de dados. Você também configurou o aplicativo para
usar os modelos de dados quando o aplicativo é executado.

No próximo tutorial, você vai atualizar a interface do usuário, Adicionar navegação e recuperar
dados do banco de dados. Isso resultará no banco de dados a ser criado automaticamente com
base nas classes de entidade que você criou neste tutorial.

39
04 - Interface do usuário e navegação
Neste tutorial, você irá modificar a interface do usuário do aplicativo da Web padrão para suporte
a recursos do aplicativo front loja Wingtip Toys. Além disso, você irá adicionar simples e dados
ligados a navegação. Este tutorial baseia-se no tutorial anterior "Criar a camada de acesso dados" e
é parte da série tutorial Wingtip Toys.

O que você vai aprender:


 Como alterar a interface do usuário para oferecer suporte a recursos do aplicativo front loja
Wingtip Toys.
 Como configurar um elemento HTML5 para incluir a navegação de página.

 Como criar um controle orientado a dados para navegar para dados específicos do
produto.
 Como exibir dados de um banco de dados criado usando o Entity Framework Code First.

Web Forms do ASP.NET permitem que você criar conteúdo dinâmico para seu aplicativo da Web.
Cada página da Web do ASP.NET é criada de uma forma semelhante a uma página de Web de
HTML estática (uma página que não inclui processamento baseado em servidor), mas a página da
Web ASP.NET inclui elementos extras que ASP.NET reconhece e processa para gerar HTML quando
a página é executada.

Com uma página HTML estática (arquivo. htm ou . html ), o servidor atende a uma solicitação Web
por ler o arquivo e enviá-la como-é para o navegador. Em contraste, quando alguém solicita uma
página da Web do ASP.NET (arquivo.aspx ), a página é executado como um programa no servidor
Web. Enquanto a página é executada, ela pode realizar qualquer tarefa que seu site requeira,
incluindo cálculo de valores, leitura ou gravação de informações de banco de dados ou chamada a
outros programas. Como sua saída, a página dinamicamente produz marcação (como elementos
em HTML) e envia essa dinâmica de saída para o navegador.

Modificar a interface do usuário


Você vai continuar esta série de tutoriais, modificando a página Default. aspx . Você irá modificar a
interface do usuário que já está estabelecido pelo modelo padrão usado para criar o aplicativo. O
tipo de modificações que você vai fazer são típicas ao criar qualquer aplicativo de formulários da
Web. Você vai fazer isso, alterando o título, substituindo algum conteúdo e remoção de conteúdo
padrão desnecessários.

1. Abra ou alterne para a página Default. aspx .

2. Se a página aparece na exibição Design , alterne para modo de exibição fonte .

40
3. Na parte superior da página na Directiva @Page , altere o atributo Title para "Welcome",
conforme destacado em amarelo abaixo.

<%@ Page Title="Welcome" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WingtipToys._Default"
%>

4. Também na página Default. aspx , substitua todo o conteúdo de padrão contido na tag
<asp:Content> para que a marcação aparece como abaixo.

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">


<h1><%: Title %>.</h1>
<h2>Wingtip Toys can help you find the perfect gift.</h2>
<p class="lead">We're all about transportation toys. You can order
any of our toys today. Each toy listing has detailed
information to help you choose the right toy.</p>

</asp:Content>

5. Salve a página Default. aspx , selecionando menu arquivo Salvar padrão. aspx .

A página Default. aspx resultante irá aparecer da seguinte maneira:

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WingtipToys._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">


<h1><%: Title %>.</h1>
<h2>Wingtip Toys can help you find the perfect gift.</h2>
<p class="lead">We're all about transportation toys. You can order
any of our toys today. Each toy listing has detailed
information to help you choose the right toy.</p>

</asp:Content>

No exemplo, você definiu o atributo Title da diretiva @Page. Quando o HTML é exibido em um
navegador, o código de servidor <%: Page.Title %> resolve para o conteúdo contido no atributo
de Title .

A página de exemplo inclui os elementos básicos que constituem uma página da Web do ASP.NET.
A página contém texto estático como você poderia ter em uma página HTML, além de elementos
que são específicos ao ASP.NET. O conteúdo contido na página Default. aspx será integrado com o
conteúdo de página mestra, que vai ser explicado mais adiante neste tutorial.

@Page Directiva

Web Forms do ASP.NET geralmente contêm diretivas que permitem que você especifique
informações de propriedades e configuração de página para a página. As diretivas são usadas pelo
41
ASP.NET como instruções para saber como processar a página, mas elas não são renderizadas
como parte da marcação que é enviada ao navegador.

A diretiva usada com mais frequência é a diretiva @Page, que permite que você especifique várias
opções de configuração para a página, incluindo o seguinte:

1. O servidor de programação linguagem de código na página, como c#.


2. Se a página é uma página com código de servidor diretamente na página, que é chamada
uma página de arquivo único, ou seja uma página com código em um arquivo de classe
separado, que é chamado uma página code-behind.
3. Se a página possui uma página mestra associada e, portanto, deve ser tratada como uma
página de conteúdo.
4. Opções de depuração e rastreamento.

Se você não incluir uma diretiva @Page na página, ou se a diretiva não incluir uma configuração
específica, a configuração será herdada do arquivo de configuração Web. config ou do arquivo de
configuração Machine. config. O arquivo Machine config fornece configurações adicionais para
todas as aplicações rodando em uma máquina.

Nota  

O Machine. config também fornece detalhes sobre todas as configurações possíveis.

Controles de servidor Web

Na maioria das aplicações ASP.NET Web Forms, você irá adicionar controles que permitem que o
usuário interaja com a página, tais como botões, caixas de texto, listas e assim por diante. Esses
controles de servidor Web são semelhantes aos botões HTML e elementos de entrada. No entanto,
eles são processados no servidor, permitindo que você use o código do servidor para definir suas
propriedades. Esses controles também elevar eventos que você pode manipular no código do
servidor.

Controles de servidor usam uma sintaxe especial que ASP.NET reconhece quando a página é
executada. O nome de marca para controles de servidor ASP.NET começa com um prefixo asp:.
Isso permite ao ASP.NET reconhecer e processar esses controles do servidor. O prefixo pode ser
diferente se o controle não é parte do .NET Framework. Para além da asp: prefixo, controles de
servidor ASP.NET também incluem o runat="server" atributo e um ID que você pode usar para
referenciar o controle no código do servidor.

Quando a página é executada, o ASP.NET identifica os controles de servidor e executa o código


que está associado esses controles. Muitos controles processam algum HTML ou outra marcação
para a página quando ela é exibida em um navegador.

Código do servidor

42
A maioria dos aplicativos de formulários da Web ASP.NET incluir o código que é executado no
servidor quando a página é processada. Como mencionado acima, o código do servidor pode ser
usado para fazer uma variedade de coisas, como adicionar dados a um controle ListView. ASP.NET
oferece suporte a vários idiomas para executar no servidor, incluindo c#, Visual Basic, j# e outros.

ASP.NET suporta dois modelos para escrever código de servidor para uma página da Web. No
modelo de arquivo único, o código para a página está em um script elemento onde a tag de
abertura inclui o runat="server" atributo. Como alternativa, você pode criar o código para a
página em um arquivo de classe separado, que é conhecido como o modelo code-behind. Neste
caso, a página de Web Forms do ASP.NET geralmente não contém nenhum código de servidor. Em
vez disso, a directiva @Page inclui informações que vincula a página. aspx com seu arquivo code-
behind associado.

O atributo CodeBehind contido na Directiva @Page especifica o nome do arquivo de classe separado,
e o atributo Inherits especifica o nome da classe no arquivo code-behind que corresponde à
página.

Atualizando a página mestra

No Web Forms do ASP.NET, páginas mestras permitem que você crie um layout consistente para as
páginas em seu aplicativo. Uma única página mestra define a aparência e comportamento padrão
que você deseja para todas as páginas (ou um grupo de páginas) em seu aplicativo. Você pode
criar páginas de conteúdo individuais que contêm o conteúdo que você deseja exibir, como
explicado acima. Quando os usuários solicitam as páginas de conteúdo, o ASP.NET mescla-as com
a página mestra para gerar uma saída que combine o layout da página mestra com o conteúdo da
página de conteúdo.

O novo site precisa de um logotipo único para exibir em cada página. Para adicionar este logotipo,
você pode modificar o HTML na página mestra.

1. No Solution Explorer, localize e abra a página mestra .

2. Se a página estiver no modo de exibição Design , alterne para modo de exibição fonte .

3. Atualize a página-mestre, modificando ou adicionando a marcação realçada em amarelo:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs"


Inherits="WingtipToys.SiteMaster" %>

<!DOCTYPE html>

<html lang="en">
<head runat="server">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%: Page.Title %> - Wingtip Toys</title>

43
<asp:PlaceHolder runat="server">
<%: Scripts.Render("~/bundles/modernizr") %>
</asp:PlaceHolder>
<webopt:bundlereference runat="server" path="~/Content/css" />
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />

</head>
<body>
<form runat="server">
<asp:ScriptManager runat="server">
<Scripts>
<%--To learn more about bundling scripts in ScriptManager see
http://go.microsoft.com/fwlink/?LinkID=301884 --%>
<%--Framework Scripts--%>
<asp:ScriptReference Name="MsAjaxBundle" />
<asp:ScriptReference Name="jquery" />
<asp:ScriptReference Name="bootstrap" />
<asp:ScriptReference Name="respond" />
<asp:ScriptReference Name="WebForms.js" Assembly="System.Web"
Path="~/Scripts/WebForms/WebForms.js" />
<asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web"
Path="~/Scripts/WebForms/WebUIValidation.js" />
<asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web"
Path="~/Scripts/WebForms/MenuStandards.js" />
<asp:ScriptReference Name="GridView.js" Assembly="System.Web"
Path="~/Scripts/WebForms/GridView.js" />
<asp:ScriptReference Name="DetailsView.js" Assembly="System.Web"
Path="~/Scripts/WebForms/DetailsView.js" />
<asp:ScriptReference Name="TreeView.js" Assembly="System.Web"
Path="~/Scripts/WebForms/TreeView.js" />
<asp:ScriptReference Name="WebParts.js" Assembly="System.Web"
Path="~/Scripts/WebForms/WebParts.js" />
<asp:ScriptReference Name="Focus.js" Assembly="System.Web"
Path="~/Scripts/WebForms/Focus.js" />
<asp:ScriptReference Name="WebFormsBundle" />
<%--Site Scripts--%>
</Scripts>
</asp:ScriptManager>

<div class="navbar navbar-inverse navbar-fixed-top">


<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" runat="server" href="~/">Wingtip Toys</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">

44
<li><a runat="server" href="~/">Home</a></li>
<li><a runat="server" href="~/About">About</a></li>
<li><a runat="server" href="~/Contact">Contact</a></li>
</ul>
<asp:LoginView runat="server" ViewStateMode="Disabled">
<AnonymousTemplate>
<ul class="nav navbar-nav navbar-right">
<li><a runat="server"
href="~/Account/Register">Register</a></li>
<li><a runat="server" href="~/Account/Login">Log
in</a></li>
</ul>
</AnonymousTemplate>
<LoggedInTemplate>
<ul class="nav navbar-nav navbar-right">
<li><a runat="server" href="~/Account/Manage"
title="Manage your account">Hello, <%: Context.User.Identity.GetUserName() %> !
</a></li>
<li>
<asp:LoginStatus runat="server"
LogoutAction="Redirect" LogoutText="Log off" LogoutPageUrl="~/"
OnLoggingOut="Unnamed_LoggingOut" />
</li>
</ul>
</LoggedInTemplate>
</asp:LoginView>
</div>
</div>
</div>
<div id="TitleContent" style="text-align: center">
<a runat="server" href="~/">
<asp:Image ID="Image1" runat="server" ImageUrl="~/Images/logo.jpg"
BorderStyle="None" />
</a>
<br />
</div>
<div class="container body-content">
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
<hr />
<footer>
<p>&copy; <%: DateTime.Now.Year %> - Wingtip Toys</p>
</footer>
</div>
</form>
</body>

</html>

Este HTML irá exibir a imagem chamada logo. jpg da pasta imagens do aplicativo da Web, o que
você vai adicionar mais tarde. Quando uma página que usa a página mestra é exibida em um
45
navegador, o logotipo será exibido. Se um usuário clica no logotipo, o usuário irá navegar de volta
para a página Default. aspx . A marca de âncora HTML <a> envolve o controle de servidor de
imagem e permite que a imagem seja incluída como parte do link. O atributo href para a marca de
âncora especifica a raiz " ~/" do site da Web como o local de ligação. Por padrão, a página Default.
aspx é exibida quando o usuário navega para a raiz do site. O controle de servidor <asp:Image>
imagem inclui propriedades de adição, como BorderStyle, que processam como HTML quando
exibido em um navegador.

Páginas mestras
Uma página mestra é um arquivo do ASP.NET com a extensão .master (por exemplo, site.Master)
com um layout predefinido que pode incluir texto estático, elementos HTML e controles de
servidor. A página mestra é identificada por uma diretiva especial @Master que substitui a diretiva
@Page que é usada para páginas . aspx comuns.

Além da diretiva @Master , a página mestra também contém todos os elementos HTML de nível
superior de uma página, como html, head e form. Por exemplo, na página mestra que você
adicionou acima, você usou um table HTML para o layout, um elemento img para o logotipo da
empresa, texto estático e controles de servidor para manipular a associação comum para seu site.
Você pode usar qualquer HTML e quaisquer elementos do ASP.NET como parte de sua página
mestra.

Além de texto estático e controles que serão exibidos em todas as páginas, a página mestra
também inclui um ou mais controles ContentPlaceHolder . Esses controles de espaço reservado
definem regiões onde aparecerá conteúdo substituível. Por sua vez, o conteúdo substituível é
definido em páginas de conteúdo, tais como Default. aspx, usando o controle de servidor de
conteúdo .

Adicionando arquivos de imagem

A imagem do logotipo referenciado acima, juntamente com todas as imagens de produto, deve ser
adicionada para o aplicativo da Web para que eles podem ser vistos quando o projeto é exibido
em um navegador.

Baixe do site de exemplos do MSDN:


Introdução ao ASP.NET 4.5 Web Forms e Visual Studio 2013 - Wingtip Toys (C#)

O download inclui recursos na pasta WingtipToys-ativos que são usados para criar o aplicativo de
exemplo.

1. Se você não tiver feito isso, baixe os arquivos de amostra de comprimido usando o link
acima do site exemplos do MSDN.
2. Uma vez baixado, abra o arquivo. zip e copie o conteúdo para uma pasta local no seu
computador.

3. Localize e abra a pasta WingtipToys-ativos .

46
4. Arrastando e soltando, copie a pasta do Catálogo de sua pasta local para a raiz do projeto
de aplicativo da Web no Solution Explorer do Visual Studio.

5. Em seguida, crie uma nova pasta denominada imagens clicando com o projeto
WingtipToys no Solution Explorer e selecionando Add -> Nova pasta.

6. Copie o arquivo logo. jpg da pasta WingtipToys-ativos em File Explorer para a pasta de
imagens do projeto de aplicativo da Web no Solution Explorer do Visual Studio.

7. Clique na opção de Mostrar todos os arquivos na parte superior do Solution Explorer


para atualizar a lista de arquivos se você não vê os novos arquivos.

Solution Explorer agora mostra os arquivos de projeto atualizado.

47
Adicionando páginas

Antes de adicionar a navegação para o aplicativo da Web, você primeiramente vai adicionar duas
novas páginas que você vai navegar para. No final desta série de tutoriais, você vai exibir produtos
e detalhes do produto nestas novas páginas.

1. No Gerenciador de Soluções, clique com botão direito em WingtipToys, clique em


Adicionar e, em seguida, clique em Novo Item.
Caixa de diálogo Add New Item é exibida.

2. Selecione o Visual c# -> grupo de modelos Web à esquerda. Em seguida, selecione o


Formulário da Web com a página mestra da lista média e denomine ProductList.

48
3. Selecione site. Master para anexar a página mestra para a página. aspx de recém-criado.

4. Adicione uma página adicional chamada ProductDetails.aspx , seguindo os mesmos passos.

Atualizando o Bootstrap
Os modelos de projeto Visual Studio 2013 usam Bootstrap, um layout e temas quadro criado pelo
Twitter. Bootstrap usa CSS3 para fornecer design responsivo, que significa layouts dinamicamente
podem adaptar-se aos tamanhos de janela de navegador diferente. Você também pode usar o

49
recurso de temas do Bootstrap para facilmente efetuar uma mudança na aparência do aplicativo.
Por padrão, o modelo de aplicativo da Web do ASP.NET no Visual Studio 2013 inclui Bootstrap
como um pacote NuGet.

Neste tutorial, você irá alterar a aparência do aplicativo Wingtip Toys, substituindo os arquivos CSS
de Bootstrap.

1. No Solution Explorer, abra a pasta de conteúdo .

2. Botão direito do mouse no arquivo bootstrap.css e renomeá-lo para bootstrap-original.css.

3. Renomear o bootstrap.min.css para bootstrap-original.min.css.

4. No Solution Explorer, botão direito do mouse a pasta de conteúdo e selecione Abrir pasta
no Explorer arquivo.
O File Explorer será exibido. Você vai salvar um carregar ficheiros CSS bootstrap para este local.

5. Em seu navegador, vá para http://Bootswatch.com.

6. Role a janela do navegador até você ver o tema celeste.

7. Baixe o arquivo bootstrap.css e o arquivo bootstrap.min.css para a pasta de conteúdo . Use o


caminho para a pasta de conteúdo que é exibida na janela do Explorador de arquivos que você
abriu anteriormente.

8. No Visual Studio , no topo do Solution Explorer, selecione a opção Mostrar todos os


arquivos para exibir os novos arquivos na pasta conteúda.

50
Você verá os dois novos arquivos CSS na pasta , mas observe que o ícone ao lado de cada nome
de arquivo é acinzentado. Isto significa que o arquivo não ainda foi adicionado para o projeto.

9. Botão direito do mouse o bootstrap.css e os bootstrap.min.css de arquivos e selecione


Incluir no projeto.
Quando você executar o aplicativo Wingtip Toys no final deste tutorial, a nova interface do usuário
será exibida.

Nota  

O modelo de aplicativo da Web ASP.NET usa o arquivo Bundle.config na raiz do projeto para
armazenar o caminho dos arquivos CSS de Bootstrap.

Modificando o padrão de navegação


A navegação padrão para cada página no aplicativo pode ser modificada alterando o elemento
lista não ordenada de navegação que está na página mestra .

1. No Solution Explorer, localize e abra a página mestra .

2. Adicione o link de navegação adicional realçado em amarelo à lista não-ordenada,


mostrado abaixo:

<ul class="nav navbar-nav">


<li><a runat="server" href="~/">Home</a></li>
<li><a runat="server" href="~/About">About</a></li>
<li><a runat="server" href="~/Contact">Contact</a></li>
<li><a runat="server" href="~/ProductList">Products</a></li>

51
</ul>

Como você pode ver no HTML acima, você modificou a cada item de linha <li> contendo uma
âncora tag <a> com um atributo href do link. Cada href aponta para uma página no aplicativo da
Web. No navegador, quando um usuário clica em um desses links (tais como produtos), eles vão
navegar para a página contida na href (tais como ProductList). Você executará o aplicativo no
final deste tutorial.

Nota  

O caractere til (~) é usado para especificar que o caminho href começa na raiz do projeto.

Adicionando um controle de dados para exibir dados de navegação


Em seguida, você adicionará um controle para exibir todas as categorias do banco de dados. Cada
categoria vai agir como um link para a página de ProductList . Quando um usuário clica em um link
de categoria no navegador, eles vão navegar para a página de produtos e ver apenas os produtos
associados a categoria selecionada.

Você usará um ListView controle para exibir todas as categorias contidas no banco de dados. Para
adicionar um ListView controle para a página mestra:

1. Na página mestra , adicione o seguinte realçada <div> elemento após o elemento de <div>
que contém o id="TitleContent" que você adicionou anteriormente:

<div id="TitleContent" style="text-align: center">


<a runat="server" href="~/">
<asp:Image ID="Image1" runat="server" ImageUrl="~/img/logo.jpg"
BorderStyle="None" />
</a>
<br />
</div>
<div id="CategoryMenu" style="text-align: center">
<asp:ListView ID="categoryList"
ItemType="WingtipToys.Models.Category"
runat="server"
SelectMethod="GetCategories" >
<ItemTemplate>
<b style="font-size: large; font-style: normal">
<a href="/ProductList.aspx?id=<%#: Item.CategoryID %>">
<%#: Item.CategoryName %>
</a>
</b>
</ItemTemplate>
<ItemSeparatorTemplate> | </ItemSeparatorTemplate>
</asp:ListView>
</div>

52
Este código irá exibir todas as categorias do banco de dados. O controle ListView exibe o nome de
cada categoria como o texto do link e inclui um link para a página ProductList.aspx com um valor
de cadeia de consulta contendo a ID da categoria. Definindo a propriedade ItemType no controle
ListView , a expressão de vinculação de dados Item está disponível dentro do nó de ItemTemplate
e o controle torna-se fortemente tipado. Você pode selecionar detalhes do objeto Item usando o
IntelliSense, como especificar o CategoryName. Este código está contido dentro do recipiente <%#:
%> que marca uma expressão de ligação de dados. Adicionando o (:) a fim do <%# prefixo, o
resultado da expressão de ligação de dados é codificado em HTML. Quando o resultado é
codificado em HTML, seu aplicativo está melhor protegido contra cross site script de injeção (XSS)
e ataques de injeção de HTML.

Dica  

Quando você adiciona código digitando durante o desenvolvimento, você pode estar certo de que
um membro válido de um objeto é encontrado porque altamente digitado dados controles
mostram os membros disponíveis com base no IntelliSense. IntelliSense oferece opções de código
apropriado contexto conforme você digita o código, como propriedades, métodos e objetos.

O próximo passo, você implementará o método GetCategories para recuperar dados.

Vinculando o controle de dados para o banco de dados


Antes que você pode exibir dados no controle de dados, você precisa vincular o controle de dados
para o banco de dados. Para fazer o link, você pode modificar o código-behind do arquivo
Site.Master.cs .

1. No Solution Explorer, botão direito do mouse a página mestra e, em seguida, clique em


Exibir código. O arquivo Site.Master.cs é aberto no editor.

2. Próximo ao início do arquivo Site.Master.cs , adicione dois namespaces adicionais para que
todos os namespaces incluídos aparecem da seguinte maneira:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Linq;

using WingtipToys.Models;

3. Adicione o método GetCategories realçado após o manipulador de eventos Page_Load ,


como segue:

protected void Page_Load(object sender, EventArgs e)


{

53
}

public IQueryable<Category> GetCategories()


{
var _db = new WingtipToys.Models.ProductContext();
IQueryable<Category> query = _db.Categories;
return query;

4. }

O código acima é executado quando qualquer página que usa a página mestra é carregada no
navegador. O controle ListView (chamado "categoryList") que você adicionou anteriormente neste
tutorial usa a vinculação do modelo para selecionar dados. Na marcação do controle ListView,
você define a propriedade SelectMethod do controle para o método GetCategories, mostrado
acima. O ListView controle chama o método GetCategories no momento apropriado do ciclo de
vida de página e vincula automaticamente os dados retornados. Você aprenderá mais sobre
vinculação de dados no próximo tutorial.

Executando o aplicativo e criando o banco de dados


Anteriormente nesta série de tutoriais, você criou um classe de inicializador (chamada
"ProductDatabaseInitializer") e especificou essa classe no arquivo global.asax.cs. O Entity
Framework irá gerar o banco de dados quando o aplicativo é executado pela primeira vez, porque
o método Application_Start contido no arquivo global.asax.cs será chamada de classe de
inicializador. A classe de inicializador vai usar as classes de modelo ( Category e Product) que você
adicionou no início desta série de tutoriais para criar o banco de dados.

1. No Solution Explorer, botão direito do mouse a página Default. aspx e selecione Definir
como página inicial.

2. Em Visual Studio, pressione F5.


Vai demorar um pouco para configurar tudo durante este primeiro executar.

54
Quando você executar o aplicativo, o aplicativo será ser compilado e banco de dados chamado
wingtiptoys.mdf será criado na pasta App_Data . No navegador, você verá um menu de navegação
da categoria. Este menu foi gerado, recuperando as categorias do banco de dados. No próximo
tutorial, você irá implementar a navegação.

3. Feche o navegador para parar o aplicativo em execução.


Revendo o banco de dados
Abra o arquivo Web. config e veja a seção de seqüência de caracteres de conexão. Você pode ver
que o valor de AttachDbFilename na cadeia de conexão aponta para o DataDirectory do projeto
de aplicativo da Web. O valor de |DataDirectory| é um valor reservado que representa a pasta
App_Data do projeto. Esta pasta é onde se encontra o banco de dados que foi criado a partir de
suas classes de entidade.

<connectionStrings>
<add name="DefaultConnection"
connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-
WingtipToys-20120302100502;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="WingtipToys"
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|
DataDirectory|\wingtiptoys.mdf;Integrated Security=True"
providerName="System.Data.SqlClient " />
</connectionStrings>

Nota  

Se a pasta App_Data não estiver visível, ou se a pasta está vazia, selecione o ícone de Atualizar e,
em seguida, no ícone Mostrar todos os arquivos na parte superior da janela do Solution

55
Explorer . Expandir a largura da janela Solution Explorer pode ser necessária para mostrar todos
os ícones disponíveis.

Agora você pode inspecionar os dados contidos no arquivo de banco de dados wingtiptoys.mdf
usando a janela do Server Explorer .

1. Expanda a pasta App_Data . Se a pasta App_Data não estiver visível, consulte a nota acima.

2. Se o arquivo de banco de dados de wingtiptoys.mdf não estiver visível, selecione o ícone de


Atualizar e, em seguida, no ícone Mostrar todos os arquivos na parte superior da janela do
Solution Explorer .

3. O arquivo de banco de dados de wingtiptoys.mdf com o botão direito e selecione abrir.


Server Explorer é exibida.

4. Expanda a pasta tabelas .

5. Botão direito do mouse os produtos tabela e selecione Mostrar dados da tabela.


A tabela de produtos é exibida.

56
6. Esta visão permite ver e modificar os dados da tabela produtos à mão.

7. Feche a janela da tabela de produtos .

8. No Gerenciador de servidores, a tabela de produtos com o botão direito novamente e


selecione Abrir definição de tabela.
O design de dados para a tabela produtos é exibido.

57
9. Na aba de T-SQL , você verá a instrução SQL DDL que foi usada para criar a tabela. Você
também pode usar a interface do usuário na guia Design para modificar a esquema.

10. No Server Explorer, WingtipToys banco de dados com o botão direito e selecione a
Conexão fechada.
Com a desanexação do banco de dados do Visual Studio, o esquema de banco de dados poderá
ser modificado posteriormente nesta série de tutoriais.

11. Volte ao Solution Explorer selecionando a aba Solution Explorer na parte inferior da
janela do Gerenciador de servidores .

Resumo
Neste tutorial da série você adicionou um interface do usuário básica, gráficos, páginas e
navegação. Além disso, você executou o aplicativo da Web, que criou o banco de dados das
classes de dados que você adicionou no tutorial anterior. Você também visualizaram o conteúdo
da tabela produtos do banco de dados exibindo o banco de dados diretamente. No próximo
tutorial, você vai exibir itens de dados e detalhes do banco de dados.

58
59
05 - Exibir itens de dados e detalhes

Este tutorial descreve como exibir itens de dados e detalhes de item de dados usando Web Forms
do ASP.NET e Entity Framework Code First. Este tutorial baseia-se no tutorial anterior "UI e
navegação" e faz parte da série tutorial Wingtip Toy Store. Quando tiver completado este tutorial,
você será capaz de ver os produtos na página ProductsList.aspx e detalhes sobre um produto
individual na página ProductDetails.aspx .

O que você vai aprender:


 Como adicionar um controle de dados para exibir produtos do banco de dados.

 Como conectar um controle de dados para os dados selecionados.

 Como adicionar um controle de dados para exibir detalhes do produto do banco de dados.

 Como recuperar um valor de seqüência de consulta e usar esse valor para limitar os dados
que são recuperados do banco de dados.
Estes são os recursos introduzidos no tutorial:

 Vinculação do modelo

 Provedores de valor

Adicionando um controle de dados para exibir os


produtos
Ao vincular dados a um controle de servidor, existem algumas opções diferentes que você pode
usar. As opções mais comuns incluem adicionar um controle de fonte de dados, adicionar código
manualmente ou usar a associação de modelos.

Usando um controle de fonte de dados para vincular a dados

Adicionar um controle de fonte de dados permite que você vincule o controle de fonte de dados
ao controle que exibe os dados. Esta abordagem permite conectar declarativamente controles do
lado do servidor diretamente para fontes de dados, em vez de usar uma abordagem programática.

Codificação manual para vincular dados

Adicionar código à mão envolve ler o valor, à procura de um valor nulo, tentando convertê-lo para
o tipo apropriado, verificando se a conversão teve êxito e finalmente, usando o valor na consulta.
Você usaria esta abordagem quando você precisa manter o controle total sobre sua lógica de
acesso a dados.
60
Usando o modelo de ligação para ligar dados

Usar vinculação de modelo permite que você vincule os resultados usando muito menos código e
lhe dá a capacidade de reutilizar a funcionalidade em todo o aplicativo. Vinculação de modelo visa
simplificar o trabalho com a lógica de acesso a dados focados no código, mantendo ainda os
benefícios de um quadro rico, ligação de dados.

Exibindo produtos
Neste tutorial, você usará a vinculação do modelo para vincular a dados. Para configurar um
controle de dados para usar a vinculação do modelo para selecionar dados, você pode definir
SelectMethod Propriedade o controle para o nome de um método no código da página. O controle
de dados chama o método no momento apropriado do ciclo de vida de página e vincula
automaticamente os dados retornados. Não há nenhuma necessidade de chamar explicitamente o
DataBind método.

Usando as etapas abaixo, você vai modificar a marcação na página ProductList para que a página
possa exibir produtos.

1. No Solution Explorer, abra a página de ProductList .

2. Substitua a marcação existente com a seguinte marcação:

<%@ Page Title="Products" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup="true"
CodeBehind="ProductList.aspx.cs" Inherits="WingtipToys.ProductList" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<section>
<div>
<hgroup>
<h2><%: Page.Title %></h2>
</hgroup>

<asp:ListView ID="productList" runat="server"


DataKeyNames="ProductID" GroupItemCount="4"
ItemType="WingtipToys.Models.Product" SelectMethod="GetProducts">
<EmptyDataTemplate>
<table >
<tr>
<td>No data was returned.</td>
</tr>
</table>
</EmptyDataTemplate>
<EmptyItemTemplate>
<td/>
</EmptyItemTemplate>
<GroupTemplate>
<tr id="itemPlaceholderContainer" runat="server">

61
<td id="itemPlaceholder" runat="server"></td>
</tr>
</GroupTemplate>
<ItemTemplate>
<td runat="server">
<table>
<tr>
<td>
<a href="ProductDetails.aspx?productID=<
%#:Item.ProductID%>">
<img src="/Catalog/Images/Thumbs/<
%#:Item.ImagePath%>"
width="100" height="75" style="border:
solid" /></a>
</td>
</tr>
<tr>
<td>
<a href="ProductDetails.aspx?productID=<
%#:Item.ProductID%>">
<span>
<%#:Item.ProductName%>
</span>
</a>
<br />
<span>
<b>Price: </b><%#:String.Format("{0:c}",
Item.UnitPrice)%>
</span>
<br />
</td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table>
</p>
</td>
</ItemTemplate>
<LayoutTemplate>
<table style="width:100%;">
<tbody>
<tr>
<td>
<table id="groupPlaceholderContainer"
runat="server" style="width:100%">
<tr id="groupPlaceholder"></tr>
</table>
</td>
</tr>
<tr>
<td></td>
</tr>
62
<tr></tr>
</tbody>
</table>
</LayoutTemplate>
</asp:ListView>
</div>
</section>

</asp:Content>

Esse código usa um controle ListView chamado "lista de produtos" para exibir os produtos.

<asp:ListView ID="productList" runat="server"

O controle ListView exibe dados em um formato que você define usando modelos e estilos. É útil
para dados em qualquer estrutura de repetição. Este exemplo ListView simplesmente mostra
dados de banco de dados, no entanto, você pode habilitar os usuários para editar, inserir e excluir
dados e para classificar e dados da página, tudo sem código.

Definindo a propriedade ItemType no controle ListView , a expressão de vinculação de dados Item


está disponível e o controle torna-se fortemente tipado. Como mencionado no tutorial anterior,
você pode selecionar detalhes do objeto Item usando o IntelliSense, como especificar o
ProductName:

Além disso, você está usando a associação de modelo para especificar um valor SelectMethod. Este
valor (GetProducts) corresponderá ao método que você adicionará ao code-behind para exibir
produtos na próxima etapa.

Adicionar código para exibir os produtos


Nesta etapa, você adicionará código para preencher o controle ListView com dados do banco de
dados do produto. O código irá apoiar apresentando produtos por categoria individual, bem como
mostrar todos os produtos.

63
1. No Solution Explorer, clique com botão direito ProductList e clique em Exibir código.

2. Substitua o código existente no arquivo ProductList.aspx.cs com o seguinte código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;
using System.Web.ModelBinding;

namespace WingtipToys
{
public partial class ProductList : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

public IQueryable<Product> GetProducts([QueryString("id")] int? categoryId)


{
var _db = new WingtipToys.Models.ProductContext();
IQueryable<Product> query = _db.Products;
if (categoryId.HasValue && categoryId > 0)
{
query = query.Where(p => p.CategoryID == categoryId);
}
return query;
}
}

Este código mostra o método GetProducts que é referenciado pela propriedade ItemType do
controle ListView na página ProductList.aspx. Para limitar os resultados de uma categoria específica
no banco de dados, o código define o valor de categoryId do valor de seqüência de caracteres de
consulta passado para a página de ProductList quando ProductList página é navegada. A classe
QueryStringAttribute no namespace System.Web.ModelBinding é usada para recuperar o valor da
id de variável de seqüência de caracteres de consulta. Isso instrui a vinculação do modelo para
tentar associar um valor da cadeia de caracteres de consulta para o parâmetro categoryId em
tempo de execução.

Quando uma categoria válida é passada como uma seqüência de caracteres de consulta para a
página, os resultados da consulta são limitados a esses produtos no banco de dados que
64
correspondem ao valor de categoryId . Por exemplo, se a URL para a página de ProductsList.aspx é
o seguinte:

http://localhost/ProductList.aspx?id=1

A página exibe apenas os produtos onde a category é igual a 1.

Se nenhuma seqüência de caracteres de consulta é incluída quando navegar para a página de


ProductList , todos os produtos serão exibidos.

As fontes de valores para esses métodos são chamadas de provedores de valor (como QueryString),
e os atributos de parâmetro que indicam qual provedor de valor para usar são referidos como
atributos de provedor de valor (por exemplo, "id"). O ASP.NET inclui provedores de valor e
atributos correspondentes para todas as fontes típicas de entrada do usuário em um aplicativo de
formulários da Web, como a seqüência de caracteres de consulta, cookies, valores de formulário,
controles, estado de exibição, estado de sessão e propriedades de perfil. Você também pode
escrever os provedores de valor personalizado.

Executando o aplicativo

Execute o aplicativo agora para ver como você pode ver todos os produtos ou apenas um conjunto
de produtos limitada pela categoria.

1. No Solution Explorer, botão direito do mouse a página Default. aspx e selecione Exibir no
navegador.
O navegador irá abrir e mostrar a página Default. aspx .

2. Selecione carros no menu de navegação de categoria de produto.


A página de ProductList é exibida mostrando apenas os produtos incluídos na categoria "Carros".
No final deste tutorial, você irá exibir detalhes do produto.

65
3. Selecione produtos do menu de navegação no topo.
Novamente, a página ProductList é exibida, no entanto desta vez mostra toda a lista de produtos.

66
4. Feche o navegador e retorne ao Visual Studio.
Adicionando um controle de dados para exibir detalhes do produto
Em seguida, você vai modificar a marcação na página de ProductDetails.aspx que você adicionou
no tutorial anterior para que a página possa exibir informações sobre um determinado produto.

1. No Solution Explorer, abra a página ProductDetails.aspx .

2. Substitua a marcação existente com a seguinte marcação:

<%@ Page Title="Product Details" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup="true"
CodeBehind="ProductDetails.aspx.cs" Inherits="WingtipToys.ProductDetails" %>

67
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<asp:FormView ID="productDetail" runat="server"
ItemType="WingtipToys.Models.Product" SelectMethod ="GetProduct"
RenderOuterTable="false">
<ItemTemplate>
<div>
<h1><%#:Item.ProductName %></h1>
</div>
<br />
<table>
<tr>
<td>
<img src="/Catalog/Images/<%#:Item.ImagePath %>"
style="border:solid; height:300px" alt="<%#:Item.ProductName %>"/>
</td>
<td>&nbsp;</td>
<td style="vertical-align: top; text-align:left;">
<b>Description:</b><br /><%#:Item.Description %>
<br />
<span><b>Price:</b>&nbsp;<%#: String.Format("{0:c}",
Item.UnitPrice) %></span>
<br />
<span><b>Product Number:</b>&nbsp;<%#:Item.ProductID %></span>
<br />
</td>
</tr>
</table>
</ItemTemplate>
</asp:FormView>

</asp:Content>

Esse código usa um controle FormView para exibir detalhes sobre um determinado produto. Essa
marcação usa métodos como aqueles que são usados para exibir os dados na página ProductList .
O controle FormView é usado para exibir um único registro em um tempo de uma fonte de dados.
Quando você usar o controle FormView , você cria modelos para exibir e editar os valores ligados
a dados. Os modelos contêm controles, expressões de vinculação e formatação que definem a
aparência e funcionalidade do formulário.

Para conectar-se a marcação acima no banco de dados, você deve adicionar código adicional para
o código ProductDetails.aspx .

1. No Solution Explorer, botão direito do mouse ProductDetails.aspx e, em seguida, clique


Exibir código.
O arquivo ProductDetails.aspx.cs será exibido.

2. Substitua o código existente com o seguinte código:

using System;

68
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;
using System.Web.ModelBinding;

namespace WingtipToys
{
public partial class ProductDetails : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

public IQueryable<Product> GetProduct([QueryString("productID")] int?


productId)
{
var _db = new WingtipToys.Models.ProductContext();
IQueryable<Product> query = _db.Products;
if (productId.HasValue && productId > 0)
{
query = query.Where(p => p.ProductID == productId);
}
else
{
query = null;
}
return query;
}
}

Este código verifica para um valor de seqüência de consulta " productID". Se um valor de cadeia de
caracteres de consulta válida for encontrado, o produto correspondente é exibido. Se nenhuma
seqüência de consulta for encontrada, ou o valor de seqüência de consulta não é válido, nenhum
produto é exibido sobre o ProductDetails.aspx página.

Executando o aplicativo

Agora você pode executar o aplicativo para ver um produto individual exibido com base no id do
produto.

1. Pressione F5 no Visual Studio para executar o aplicativo.


O navegador irá abrir e mostrar a página Default. aspx .
69
2. Selecione o menu de navegação da categoria "Barcos".
A página de ProductList é exibida.

3. Selecione o produto de "Paper Boat" a lista de produtos.


A página ProductDetails.aspx é exibida.

4. Feche o navegador.

Resumo
Neste tutorial da série você tem adicionar marcação e código para exibir uma lista de produtos e
para exibir detalhes do produto. Durante esse processo, você aprendeu sobre os controles de
dados com rigidez de tipos, vinculação do modelo e os provedores de valor. No próximo tutorial,
você vai adicionar um carrinho de compras para o aplicativo de exemplo do Wingtip Toys.

70
06 - Carrinho de compras
Este tutorial descreve a lógica de negócios necessária para adicionar um carrinho de compras ao
aplicativo de exemplo Wingtip Toys do ASP.NET Web Forms. Este tutorial baseia-se no tutorial
anterior "Exibir dados itens e detalhes" e faz parte da série tutorial Wingtip Toy Store. Quando tiver
completado este tutorial, os usuários do seu aplicativo de amostra será capazes de adicionar,
remover e modificar os produtos em seu carrinho de compras.

O que você vai aprender:


1. Como criar um carrinho de compras para o aplicativo da web.
2. Como habilitar usuários adicionar itens ao carrinho de compras.

3. Como adicionar um controle GridView para exibir detalhes de carrinho de compras.

4. Como calcular e exibir o total do pedido.


5. Como remover e atualizar itens no carrinho de compras.
6. Como incluir um contador de carrinho de compras.

Características do código neste tutorial:


1. Entity Framework Code First
2. Anotações de dados
3. Controles de dados fortemente tipados
4. Vinculação do modelo

Criando um carrinho de compras


No início desta série de tutoriais, você adicionou páginas e código para ver os dados do produto
de um banco de dados. Neste tutorial, você criará um carrinho de compras para gerenciar os
produtos que os usuários estão interessados em comprar. Os usuários poderão procurar e
adicionar itens ao carrinho de compras, mesmo que não estejam registrados ou conectados. Para
gerenciar o acesso de carro comercial, você atribuirá aos usuários um único ID usando um
identificador globalmente exclusivo (GUID) quando o usuário acessa o carrinho pela primeira vez.
Você vai armazenar este ID usando o estado de sessão do ASP.NET.

Nota  

O estado de sessão do ASP.NET é um local conveniente para armazenar informações específicas do


usuário que irão expirar depois que o usuário deixa o site. Enquanto o uso indevido do estado de
sessão pode ter implicações de desempenho em sites maiores, seu uso moderado funciona bem
para fins de demonstração. O projeto de amostra do Wingtip Toys mostra como usar estado de
sessão sem um provedor externo, onde o estado da sessão é armazenado em processo no servidor
da web que hospeda o site. Para maiores sites que fornecem várias instâncias de um aplicativo ou
71
para sites que executar várias instâncias de um aplicativo em diferentes servidores, considere o uso
de Serviço de Cache do Windows Azure. Este serviço de Cache fornece um serviço de cache
distribuído externo para o site que resolve o problema de usar estado de sessão em processo. Para
mais informações, consulte como usar estado de sessão ASP.NET com Sites da Web do Windows
Azure.

Adicionar CartItem como uma classe de modelo


No início desta série de tutoriais, você definiu o esquema dos dados de produto e categoria,
criando as classes de Category e Product na pasta modelos . Agora, adicione uma nova classe para
definir o esquema para o carrinho de compras. Mais tarde neste tutorial, você irá adicionar uma
classe para manipular o acesso a dados para a tabela CartItem . Essa classe irá fornecer a lógica de
negócios para adicionar, remover e atualizar itens no carrinho de compras.

1. A pasta de modelos com o botão direito e selecione Add -> New Item.

2. Caixa de diálogo Add New Item é exibida. Selecione Código e depois Classe.

72
3. Nomeie esta nova classe CartItem.cs.

4. Clique em Adicionar.
O novo arquivo de classe é exibido no editor.

5. Substitua o código padrão com o seguinte código:

using System.ComponentModel.DataAnnotations;

namespace WingtipToys.Models
{
public class CartItem
{
[Key]
public string ItemId { get; set; }

public string CartId { get; set; }

public int Quantity { get; set; }

public System.DateTime DateCreated { get; set; }

public int ProductId { get; set; }

public virtual Product Product { get; set; }

73
}

A classe CartItem contém o esquema que define cada produto que um usuário adiciona ao
carrinho de compras. Essa classe é semelhante para as outras classes de esquema que você criou
anteriormente nesta série de tutoriais. Por convenção, Entity Framework Code First espera que a
chave primária para a tabela CartItem será CartItemId ou ID. No entanto, o código substitui o
comportamento padrão usando o atributo [Key] anotação de dados. O atributo de Key da
propriedade ItemId especifica que a propriedade ItemID é a chave primária.

A propriedade CartId especifica a ID do usuário que está associado com o item para comprar.
Você adicionará código para criar esta 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 do ASP.NET.

Atualizar o contexto do produto


Além de adicionar a classe CartItem , você precisará atualizar a classe de contexto de banco de
dados que gerencia as classes de entidade e que fornece acesso a dados no banco de dados. Para
fazer isso, você irá adicionar a classe de modelo recém-criado CartItem à classe ProductContext .

1. No Solution Explorer, localizar e abrir o arquivo ProductContext.cs na pasta modelos .

2. Adicione o código realçado para o arquivo ProductContext.cs como segue:

using System.Data.Entity;

namespace WingtipToys.Models
{
public class ProductContext : DbContext
{
public ProductContext()
: base("WingtipToys")
{
}

public DbSet<Category> Categories { get; set; }


public DbSet<Product> Products { get; set; }
public DbSet<CartItem> ShoppingCartItems { get; set; }
}

Como mencionado anteriormente nesta série tutorial, o código no arquivo ProductContext.cs


adiciona o namespace System.Data.Entity para que você tenha acesso a toda a funcionalidade de
núcleo do Entity Framework. Essa funcionalidade inclui a capacidade de consultar, inserir, atualizar

74
e excluir dados ao trabalhar com objetos com rigidez de tipos. A classe ProductContext adiciona o
acesso para a classe de modelo CartItem recém-adicionado.

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


Em seguida, você criará a classe ShoppingCart em uma nova pasta lógica . A classe ShoppingCart
lida com acesso a dados para a tabela CartItem . A classe também irá incluir a lógica de negócios
para adicionar, remover e atualizar 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:

1. Adicionar itens ao carrinho de compras


2. Remover itens do carrinho de compras
3. Obtendo o ID de carrinho compras
4. Recuperando itens do carrinho de compras
5. Totalizando o valor de todos os itens do carrinho de compras
6. Atualizando os dados de carrinho de compras

Uma página de carrinho de compras (ShoppingCart.aspx) e classe-carrinho de compras serão


usados juntos para acessar dados de 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 classe, você criará uma página (AddToCart.aspx) para adicionar produtos ao carrinho
de compras. Você também irá adicionar código para a página de ProductList e a
ProductDetails.aspx que irá fornecer um link para a página AddToCart.aspx , para que o usuário
pode adicionar produtos ao carrinho de compras.

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

75
Quando o usuário clicar no link Adicionar ao carrinho na página ProductList.aspx ou
ProductDetails.aspx, o aplicativo navegará para a página AddToCart.aspx e depois automaticamente
para a página ShoppingCart.aspx. A página AddToCart.aspx adicionará o produto selecionado ao
carrinho de compras chamando um método na classe ShoppingCart. A página de
ShoppingCart.aspx irá exibir os produtos que foram adicionados ao carrinho de compras.

Criando a classe carrinho de compras


Classe ShoppingCart será adicionado a uma pasta separada no aplicativo para que vai haver uma
clara distinção entre o modelo (pasta de modelos), as páginas (pasta raiz) e a lógica (pasta lógica).

1. No Solution Explorer, botão direito do mouse o WingtipToys de projeto e selecione


Adicionar --> nova pasta. Nomeie a nova pasta lógica.

2. Botão direito do mouse a pasta lógica e em seguida selecione Add -> New Item.

3. Adicionar um novo arquivo de classe chamado ShoppingCartActions.cs.

4. Substitua o código padrão com o seguinte código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WingtipToys.Models;

namespace WingtipToys.Logic
{
public class ShoppingCartActions : IDisposable
{
public string ShoppingCartId { get; set; }

private ProductContext _db = new ProductContext();

public const string CartSessionKey = "CartId";

public void AddToCart(int id)


{
// Retrieve the product from the database.
ShoppingCartId = GetCartId();

var cartItem = _db.ShoppingCartItems.SingleOrDefault(


c => c.CartId == ShoppingCartId
&& c.ProductId == id);
if (cartItem == null)
{
// Create a new cart item if no cart item exists.
cartItem = new CartItem
{
ItemId = Guid.NewGuid().ToString(),

76
ProductId = id,
CartId = ShoppingCartId,
Product = _db.Products.SingleOrDefault(
p => p.ProductID == id),
Quantity = 1,
DateCreated = DateTime.Now
};

_db.ShoppingCartItems.Add(cartItem);
}
else
{
// If the item does exist in the cart,
// then add one to the quantity.
cartItem.Quantity++;
}
_db.SaveChanges();
}

public void Dispose()


{
if (_db != null)
{
_db.Dispose();
_db = null;
}
}

public string GetCartId()


{
if (HttpContext.Current.Session[CartSessionKey] == null)
{
if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
{
HttpContext.Current.Session[CartSessionKey] =
HttpContext.Current.User.Identity.Name;
}
else
{
// Generate a new random GUID using System.Guid class.
Guid tempCartId = Guid.NewGuid();
HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString();
}
}
return HttpContext.Current.Session[CartSessionKey].ToString();
}

public List<CartItem> GetCartItems()


{
ShoppingCartId = GetCartId();

77
return _db.ShoppingCartItems.Where(
c => c.CartId == ShoppingCartId).ToList();
}
}

O método de AddToCart permite que produtos individuais a serem incluídos no carrinho de


compras com base no produto ID. O produto é adicionado para o carrinho, ou se o carrinho já
contém um item para que o produto, a quantidade é incrementada.

O método GetCartId retorna o carrinho ID para o usuário. O carrinho ID é usado para controlar os
itens que um usuário tem em seu carrinho de compras. Se o usuário não tem um carrinho existente
ID, um carrinho novo ID é criado para eles. Se o usuário é logado como um usuário registrado, o
carrinho ID é definido como seu nome de usuário. No entanto, se o usuário não está assinado, o
carrinho ID é definido como um valor exclusivo (um GUID). Um GUID garante que apenas um
carrinho é criado para cada usuário, com base na sessão.

O método GetCartItems retorna uma lista de compras de itens do carrinho para o usuário. Mais
tarde neste tutorial, você verá que a vinculação do modelo é usada para exibir os itens do carrinho
no carrinho de compras, usando o método GetCartItems .

Criando a funcionalidade de adicionar ao carrinho


Como mencionado anteriormente, você irá criar uma página de processamento chamada
AddToCart.aspx que será usado para adicionar novos produtos ao carrinho de compras do usuário.
Esta página irá chamar o método de AddToCart na classe ShoppingCart que você acabou de criar. A
página AddToCart.aspx esperam que um produto ID é passado para ele. Este produto ID será
usado ao chamar o método AddToCart na classe ShoppingCart .

Nota  

Você vai estar modificando o código-behind (AddToCart.aspx.cs) para esta página, não o interface
do usuário (AddToCart.aspx).

Para criar o Add To Cart funcionalidade:


1. No Solution Explorer, botão direito do mouse o WingtipToys do projeto, clique em
Adicionar -> Novo Item.
Caixa de diálogo Add New Item é exibida.

2. Adicionar uma nova página padrão (Web Form) para o aplicativo chamado AddToCart.aspx.

78
3. No Solution Explorer, botão direito do mouse a página AddToCart.aspx e clique em Exibir
código. O arquivo de code-behind AddToCart.aspx.cs é aberto no editor.

4. Substitua o código existente no code-behind AddToCart.aspx.cs com o seguinte:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Diagnostics;
using WingtipToys.Logic;

namespace WingtipToys
{
public partial class AddToCart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string rawId = Request.QueryString["ProductID"];
int productId;
if (!String.IsNullOrEmpty(rawId) && int.TryParse(rawId, out productId))
{
using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
{
usersShoppingCart.AddToCart(Convert.ToInt16(rawId));
}

79
else
{
Debug.Fail("ERROR : We should never get to AddToCart.aspx without a
ProductId.");
throw new Exception("ERROR : It is illegal to load AddToCart.aspx without
setting a ProductId.");
}
Response.Redirect("ShoppingCart.aspx");
}
}

Quando a página AddToCart.aspx é carregada, o ID do produto é obtido a seqüência de caracteres


de consulta. Em seguida, uma instância da classe carrinho de compras é criada e usada para
chamar o método AddToCart que você adicionou anteriormente neste tutorial. O método de
AddToCart , contido no arquivo ShoppingCartActions.cs , inclui a lógica para adicionar o produto
selecionado ao carrinho de compras ou incrementar a quantidade de produto do produto
selecionado. Se o produto não foi adicionado ao carrinho de compras, o produto é adicionado à
tabela CartItem do banco de dados. Se o produto já foi adicionado ao carrinho de compras e o
usuário adiciona um item adicional do mesmo produto, a quantidade de produto é incrementada
na tabela CartItem . Finalmente, a página redireciona para a página de ShoppingCart.aspx que você
vai adicionar na próxima etapa, onde o usuário vê uma lista atualizada dos itens no carrinho.

Como mencionado anteriormente, um usuário ID é usado para identificar os produtos que estão
associados um usuário específico. Este ID é adicionado a uma linha na tabela CartItem cada vez
que o usuário adiciona um produto ao carrinho de compras.

Criando a interface do usuário do carrinho de compras


A página de ShoppingCart.aspx irá exibir os produtos que o usuário tenha adicionado ao seu
carrinho de compras. Fornecerá também a capacidade de adicionar, remover e atualizar itens no
carrinho de compras.

1. No Solution Explorer, botão direito do mouse WingtipToys, clique em Adicionar ->


Novo Item.
Caixa de diálogo Add New Item é exibida.

2. Adicione uma nova página (formulário Web) que inclui uma página-mestre, selecionando o
formulário da Web usando a página mestra. Nomeie a nova página ShoppingCart.aspx.

3. Selecione site. Master para anexar a página mestra para a página. aspx de recém-criado.

4. Na página ShoppingCart.aspx , substitua a marcação existente com a seguinte marcação:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"


CodeBehind="ShoppingCart.aspx.cs" Inherits="WingtipToys.ShoppingCart" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

80
<div id="ShoppingCartTitle" runat="server" class="ContentHead"><h1>Shopping
Cart</h1></div>
<asp:GridView ID="CartList" runat="server" AutoGenerateColumns="False"
ShowFooter="True" GridLines="Vertical" CellPadding="4"
ItemType="WingtipToys.Models.CartItem" SelectMethod="GetShoppingCartItems"
CssClass="table table-striped table-bordered" >
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ID"
SortExpression="ProductID" />
<asp:BoundField DataField="Product.ProductName" HeaderText="Name" />
<asp:BoundField DataField="Product.UnitPrice" HeaderText="Price (each)"
DataFormatString="{0:c}"/>
<asp:TemplateField HeaderText="Quantity">
<ItemTemplate>
<asp:TextBox ID="PurchaseQuantity" Width="40" runat="server"
Text="<%#: Item.Quantity %>"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Item Total">
<ItemTemplate>
<%#: String.Format("{0:c}", ((Convert.ToDouble(Item.Quantity)) *
Convert.ToDouble(Item.Product.UnitPrice)))%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Remove Item">
<ItemTemplate>
<asp:CheckBox id="Remove" runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<div>
<p></p>
<strong>
<asp:Label ID="LabelTotalText" runat="server" Text="Order Total:
"></asp:Label>
<asp:Label ID="lblTotal" runat="server"
EnableViewState="false"></asp:Label>
</strong>
</div>
<br />

</asp:Content>

A página de ShoppingCart.aspx inclui um GridView o controle chamado CartList. Esse controle


usa a vinculação do modelo para vincular os dados de carrinho de compras do banco de dados
para o GridView de controle. Quando você definir a propriedade ItemType do controle GridView ,
a expressão de vinculação de dados Item está disponível na marcação do controle e o controle
torna-se fortemente tipado. Como mencionado no início desta série de tutoriais, você pode
selecionar detalhes do objeto Item usando o IntelliSense. Para configurar um controle de dados
81
para usar a vinculação do modelo para selecionar dados, você pode definir a propriedade
SelectMethod do controle. Na marcação acima, você pode definir o SelectMethod , usar o método
GetShoppingCartItems que retorna uma lista de objetos CartItem . O controle de dados de
GridView chama o método no momento apropriado do ciclo de vida de página e vincula
automaticamente os dados retornados. O método de GetShoppingCartItems ainda deve ser
adicionado.

Recuperando os itens do carrinho de compras


Em seguida, você pode adicionar código para o ShoppingCart.aspx.cs code-behind para recuperar e
preencher o UI de carrinho de compras.

1. No Solution Explorer, botão direito do mouse a página ShoppingCart.aspx e clique em


Exibir código. O arquivo de code-behind ShoppingCart.aspx.cs é aberto no editor.

2. Substitua o código existente com o seguinte:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;
using WingtipToys.Logic;

namespace WingtipToys
{
public partial class ShoppingCart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

public List<CartItem> GetShoppingCartItems()


{
ShoppingCartActions actions = new ShoppingCartActions();
return actions.GetCartItems();
}
}

Como mencionado acima, o controle de dados de GridView chama o método


GetShoppingCartItems no momento apropriado do ciclo de vida de página e vincula
automaticamente os dados retornados. O método GetShoppingCartItems cria uma instância do

82
objeto ShoppingCartActions . Em seguida, o código usa essa instância para retornar os itens no
carrinho, chamando o método GetCartItems .

Adicionando produtos ao carrinho de compras


Quando o ProductList ou a página de ProductDetails.aspx é exibida, o usuário será capaz de
adicionar o produto ao carrinho de compras usando um link. Quando eles clicarem no link, o
aplicativo navega para a página de processamento chamada AddToCart.aspx. A página
AddToCart.aspx chamará o método AddToCart na classe ShoppingCart que você adicionou
anteriormente neste tutorial.

Agora, você adicionará um link Adicionar ao carrinho para a página de ProductList e a página
ProductDetails.aspx . Este link irá incluir o produto ID que é recuperado do banco de dados.

1. No Solution Explorer, localize e abra a página chamada ProductList.

2. Adicione a marcação destacada em amarelo para a página de ProductList para que a página
inteira aparece da seguinte maneira:

<%@ Page Title="Products" Language="C#" MasterPageFile="~/Site.Master"


AutoEventWireup="true"
CodeBehind="ProductList.aspx.cs" Inherits="WingtipToys.ProductList" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<section>
<div>
<hgroup>
<h2><%: Page.Title %></h2>
</hgroup>

<asp:ListView ID="productList" runat="server"


DataKeyNames="ProductID" GroupItemCount="4"
ItemType="WingtipToys.Models.Product" SelectMethod="GetProducts">
<EmptyDataTemplate>
<table runat="server">
<tr>
<td>No data was returned.</td>
</tr>
</table>
</EmptyDataTemplate>
<EmptyItemTemplate>
<td runat="server" />
</EmptyItemTemplate>
<GroupTemplate>
<tr id="itemPlaceholderContainer" runat="server">
<td id="itemPlaceholder" runat="server"></td>
</tr>
</GroupTemplate>
<ItemTemplate>
<td runat="server">
<table>

83
<tr>
<td>
<a href="ProductDetails.aspx?productID=<
%#:Item.ProductID%>">
<img src="/Catalog/Images/Thumbs/<
%#:Item.ImagePath%>"
width="100" height="75" style="border:
solid" /></a>
</td>
</tr>
<tr>
<td>
<a href="ProductDetails.aspx?productID=<
%#:Item.ProductID%>">
<span>
<%#:Item.ProductName%>
</span>
</a>
<br />
<span>
<b>Price: </b><%#:String.Format("{0:c}",
Item.UnitPrice)%>
</span>
<br />
<a href="/AddToCart.aspx?productID=<
%#:Item.ProductID %>">
<span class="ProductListItem">
<b>Add To Cart<b>
</span>
</a>
</td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table>
</p>
</td>
</ItemTemplate>
<LayoutTemplate>
<table runat="server" style="width:100%;">
<tbody>
<tr runat="server">
<td runat="server">
<table id="groupPlaceholderContainer"
runat="server" style="width:100%">
<tr id="groupPlaceholder" runat="server"></tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server"></td>
</tr>

84
<tr></tr>
</tbody>
</table>
</LayoutTemplate>
</asp:ListView>
</div>
</section>

</asp:Content>

Teste do carrinho de compras

Execute o aplicativo para ver como você adicionar produtos ao carrinho de compras.

1. Pressione F5 para executar o aplicativo.


Depois que o projeto recria o banco de dados, o navegador irá abrir e mostrar a página Default.
aspx .

2. Selecione o menu de navegação da categoria carros .


A página de ProductList é exibida mostrando apenas os produtos incluídos na categoria "Carros".

85
3. Clique no link Adicionar ao carrinho , ao lado do primeiro produto listado (o carro
conversível).
A página de ShoppingCart.aspx é exibida, mostrando a seleção em seu carrinho de compras.

4. Ver os produtos adicionais, selecionando o menu de navegação categoria aviões .

5. Clique no link Adicionar ao carrinho , ao lado do primeiro produto listado.


A página da ShoppingCart.aspx é exibida com o item adicional.

6. Feche o navegador.
Calcular e exibir o Total do pedido
Além de adicionar produtos ao carrinho de compras, você adicionará um método GetTotal à classe
ShoppingCart e exibir a quantidade total da encomenda na página de carrinho de compras.

1. No Solution Explorer, abra o arquivo ShoppingCartActions.cs na pasta lógica .

2. Adicione o seguinte método de GetTotal destacado em amarelo para a classe


ShoppingCart , para que a classe aparece da seguinte maneira:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WingtipToys.Models;

86
namespace WingtipToys.Logic
{
public class ShoppingCartActions : IDisposable
{
public string ShoppingCartId { get; set; }

private ProductContext _db = new ProductContext();

public const string CartSessionKey = "CartId";

public void AddToCart(int id)


{
// Retrieve the product from the database.
ShoppingCartId = GetCartId();

var cartItem = _db.ShoppingCartItems.SingleOrDefault(


c => c.CartId == ShoppingCartId
&& c.ProductId == id);
if (cartItem == null)
{
// Create a new cart item if no cart item exists.
cartItem = new CartItem
{
ItemId = Guid.NewGuid().ToString(),
ProductId = id,
CartId = ShoppingCartId,
Product = _db.Products.SingleOrDefault(
p => p.ProductID == id),
Quantity = 1,
DateCreated = DateTime.Now
};

_db.ShoppingCartItems.Add(cartItem);
}
else
{
// If the item does exist in the cart,
// then add one to the quantity.
cartItem.Quantity++;
}
_db.SaveChanges();
}

public void Dispose()


{
if (_db != null)
{
_db.Dispose();
_db = null;

87
}
}

public string GetCartId()


{
if (HttpContext.Current.Session[CartSessionKey] == null)
{
if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
{
HttpContext.Current.Session[CartSessionKey] =
HttpContext.Current.User.Identity.Name;
}
else
{
// Generate a new random GUID using System.Guid class.
Guid tempCartId = Guid.NewGuid();
HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString();
}
}
return HttpContext.Current.Session[CartSessionKey].ToString();
}

public List<CartItem> GetCartItems()


{
ShoppingCartId = GetCartId();

return _db.ShoppingCartItems.Where(
c => c.CartId == ShoppingCartId).ToList();
}

public decimal GetTotal()


{
ShoppingCartId = GetCartId();
// Multiply product price by quantity of that product to get
// the current price for each of those products in the cart.
// Sum all product price totals to get the cart total.
decimal? total = decimal.Zero;
total = (decimal?)(from cartItems in _db.ShoppingCartItems
where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Quantity *
cartItems.Product.UnitPrice).Sum();
return total ?? decimal.Zero;
}
}

88
Primeiro, o método de GetTotal Obtém o ID do carrinho de compras para o usuário. Em seguida, o
método obtém o carrinho total multiplicando a quantidade de produto para cada produto listado
no carrinho o preço do produto.

Nota  

O código acima usa o tipo anulável " int?". Tipos anuláveis podem representar todos os valores de
um tipo subjacente e também como um valor nulo. Para mais informações, consulte Usando tipos
anulável.

Modificar a exibição de carrinho compras


Em seguida você vai modificar o código para a página ShoppingCart.aspx chamar o método
GetTotal e exibir o total na página de ShoppingCart.aspx quando a página for carregada.

1. No Solution Explorer, botão direito do mouse a página ShoppingCart.aspx e selecione


Exibir código.

2. No arquivo ShoppingCart.aspx.cs , atualize o manipulador Page_Load , adicionando o


seguinte código realçado em amarelo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;
using WingtipToys.Logic;

namespace WingtipToys
{
public partial class ShoppingCart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
{
decimal cartTotal = 0;
cartTotal = usersShoppingCart.GetTotal();
if (cartTotal > 0)
{
// Display Total.
lblTotal.Text = String.Format("{0:c}", cartTotal);
}
else
{
LabelTotalText.Text = "";
lblTotal.Text = "";
ShoppingCartTitle.InnerText = "Shopping Cart is Empty";
}

89
}
}

public List<CartItem> GetShoppingCartItems()


{
ShoppingCartActions actions = new ShoppingCartActions();
return actions.GetCartItems();
}
}

Quando carrega a página ShoppingCart.aspx , ele carrega o objeto carrinho compras e em seguida,
recupera o total carrinho compras chamando o método GetTotal da classe ShoppingCart . Se o
carrinho de compras está vazio, uma mensagem será exibida para o efeito.

Testar o Total carrinho compras

Execute o aplicativo agora para ver como você não pode apenas adicionar um produto ao carrinho
de compras, mas você pode ver o total de carrinho compras.

1. Pressione F5 para executar o aplicativo.


O navegador irá abrir e mostrar a página Default. aspx .

2. Selecione o menu de navegação da categoria carros .

3. Clique no link Adicionar ao carrinho , ao lado do primeiro produto.


A página da ShoppingCart.aspx é exibida com o total do pedido.

90
4. Adicione alguns outros produtos (por exemplo, um avião) para o carrinho.

5. A página da ShoppingCart.aspx é exibida com um total atualizado para todos os produtos


que você adicionou.

91
6. Pare a execução app fechando a janela do navegador.
Adicionando botões de Checkout e atualização para o carrinho de compras
Para permitir que os usuários modifiquem o carrinho de compras, você adicionará um botão de
atualização e um botão Checkout para a página do carrinho de compras. Não é usado para o
botão Checkout até mais tarde na série este tutorial.

1. No Solution Explorer, abra a página de ShoppingCart.aspx na raiz do projeto de aplicativo


da web.

2. Para adicionar o botão de atualização e o botão check-out para a página


ShoppingCart.aspx , adicione a marcação realçada em amarelo a marcação existente, conforme
mostrado no código a seguir:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"


CodeBehind="ShoppingCart.aspx.cs" Inherits="WingtipToys.ShoppingCart" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<div id="ShoppingCartTitle" runat="server" class="ContentHead"><h1>Shopping
Cart</h1></div>
<asp:GridView ID="CartList" runat="server" AutoGenerateColumns="False"
ShowFooter="True" GridLines="Vertical" CellPadding="4"
ItemType="WingtipToys.Models.CartItem" SelectMethod="GetShoppingCartItems"
CssClass="table table-striped table-bordered" >
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ID"
SortExpression="ProductID" />
<asp:BoundField DataField="Product.ProductName" HeaderText="Name" />
<asp:BoundField DataField="Product.UnitPrice" HeaderText="Price (each)"
DataFormatString="{0:c}"/>
<asp:TemplateField HeaderText="Quantity">
<ItemTemplate>
<asp:TextBox ID="PurchaseQuantity" Width="40" runat="server"
Text="<%#: Item.Quantity %>"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Item Total">
<ItemTemplate>
<%#: String.Format("{0:c}", ((Convert.ToDouble(Item.Quantity)) *
Convert.ToDouble(Item.Product.UnitPrice)))%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Remove Item">
<ItemTemplate>
<asp:CheckBox id="Remove" runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<div>
<p></p>
<strong>

92
<asp:Label ID="LabelTotalText" runat="server" Text="Order Total:
"></asp:Label>
<asp:Label ID="lblTotal" runat="server"
EnableViewState="false"></asp:Label>
</strong>
</div>
<br />
<table>
<tr>
<td>
<asp:Button ID="UpdateBtn" runat="server" Text="Update"
OnClick="UpdateBtn_Click" />
</td>
<td>
<!--Checkout Placeholder -->
</td>
</tr>
</table>

</asp:Content>

Quando o usuário clica no botão de atualização , será chamado o manipulador de eventos


UpdateBtn_Click . Este manipulador de eventos chamará o código que você vai adicionar na
próxima etapa.

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

1. No Solution Explorer, abra o arquivo ShoppingCart.aspx.cs na raiz do projeto de aplicativo


da web.

2. Adicione as seguintes seções de código realçadas em amarelo ao arquivo


ShoppingCart.aspx.cs :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;
using WingtipToys.Logic;
using System.Collections.Specialized;
using System.Collections;
using System.Web.ModelBinding;

namespace WingtipToys
{
public partial class ShoppingCart : System.Web.UI.Page

93
{
protected void Page_Load(object sender, EventArgs e)
{
using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
{
decimal cartTotal = 0;
cartTotal = usersShoppingCart.GetTotal();
if (cartTotal > 0)
{
// Display Total.
lblTotal.Text = String.Format("{0:c}", cartTotal);
}
else
{
LabelTotalText.Text = "";
lblTotal.Text = "";
ShoppingCartTitle.InnerText = "Shopping Cart is Empty";
UpdateBtn.Visible = false;
}
}
}

public List<CartItem> GetShoppingCartItems()


{
ShoppingCartActions actions = new ShoppingCartActions();
return actions.GetCartItems();
}

public List<CartItem> UpdateCartItems()


{
using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
{
String cartId = usersShoppingCart.GetCartId();

ShoppingCartActions.ShoppingCartUpdates[] cartUpdates = new


ShoppingCartActions.ShoppingCartUpdates[CartList.Rows.Count];
for (int i = 0; i < CartList.Rows.Count; i++)
{
IOrderedDictionary rowValues = new OrderedDictionary();
rowValues = GetValues(CartList.Rows[i]);
cartUpdates[i].ProductId = Convert.ToInt32(rowValues["ProductID"]);

CheckBox cbRemove = new CheckBox();


cbRemove = (CheckBox)CartList.Rows[i].FindControl("Remove");
cartUpdates[i].RemoveItem = cbRemove.Checked;

TextBox quantityTextBox = new TextBox();


quantityTextBox = (TextBox)CartList.Rows[i].FindControl("PurchaseQuantity");
cartUpdates[i].PurchaseQuantity =
Convert.ToInt16(quantityTextBox.Text.ToString());

94
}
usersShoppingCart.UpdateShoppingCartDatabase(cartId, cartUpdates);
CartList.DataBind();
lblTotal.Text = String.Format("{0:c}", usersShoppingCart.GetTotal());
return usersShoppingCart.GetCartItems();
}
}

public static IOrderedDictionary GetValues(GridViewRow row)


{
IOrderedDictionary values = new OrderedDictionary();
foreach (DataControlFieldCell cell in row.Cells)
{
if (cell.Visible)
{
// Extract values from the cell.
cell.ContainingField.ExtractValuesFromCell(values, cell, row.RowState,
true);
}
}
return values;
}

protected void UpdateBtn_Click(object sender, EventArgs e)


{
UpdateCartItems();
}
}

Quando o usuário clica no botão de atualização na página ShoppingCart.aspx , o método


UpdateCartItems é chamado. O UpdateCartItems método obtém os valores atualizados para cada
item no carrinho de compras. Em seguida, o método UpdateCartItems chama o método de
UpdateShoppingCartDatabase (adicionado e explicados na próxima etapa) para adicionar ou
remover itens do carrinho de compras. Uma vez que o banco de dados foi atualizado para refletir
as atualizações para o carrinho de compras, o GridView controle é atualizado na página do
carrinho de compras, chamando o método DataBind para o GridView. Além disso, o montante
total da encomenda na página de carrinho de compras é atualizado para refletir a lista atualizada
dos itens.

Atualizar e remover itens do carrinho de compras


Na página ShoppingCart.aspx , você pode ver controles foram adicionados para atualizar a
quantidade de um item e a remoção de um item. Agora, adicione o código que fará com que esses
controles funcionam.

1. No Solution Explorer, abra o arquivo ShoppingCartActions.cs na pasta lógica .


95
2. Adicione o seguinte código realçado em amarelo ao arquivo de classe
ShoppingCartActions.cs :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WingtipToys.Models;

namespace WingtipToys.Logic
{
public class ShoppingCartActions : IDisposable
{
public string ShoppingCartId { get; set; }

private ProductContext _db = new ProductContext();

public const string CartSessionKey = "CartId";

public void AddToCart(int id)


{
// Retrieve the product from the database.
ShoppingCartId = GetCartId();

var cartItem = _db.ShoppingCartItems.SingleOrDefault(


c => c.CartId == ShoppingCartId
&& c.ProductId == id);
if (cartItem == null)
{
// Create a new cart item if no cart item exists.
cartItem = new CartItem
{
ItemId = Guid.NewGuid().ToString(),
ProductId = id,
CartId = ShoppingCartId,
Product = _db.Products.SingleOrDefault(
p => p.ProductID == id),
Quantity = 1,
DateCreated = DateTime.Now
};

_db.ShoppingCartItems.Add(cartItem);
}
else
{
// If the item does exist in the cart,
// then add one to the quantity.
cartItem.Quantity++;

96
}
_db.SaveChanges();
}

public void Dispose()


{
if (_db != null)
{
_db.Dispose();
_db = null;
}
}

public string GetCartId()


{
if (HttpContext.Current.Session[CartSessionKey] == null)
{
if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
{
HttpContext.Current.Session[CartSessionKey] =
HttpContext.Current.User.Identity.Name;
}
else
{
// Generate a new random GUID using System.Guid class.
Guid tempCartId = Guid.NewGuid();
HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString();
}
}
return HttpContext.Current.Session[CartSessionKey].ToString();
}

public List<CartItem> GetCartItems()


{
ShoppingCartId = GetCartId();

return _db.ShoppingCartItems.Where(
c => c.CartId == ShoppingCartId).ToList();
}

public decimal GetTotal()


{
ShoppingCartId = GetCartId();
// Multiply product price by quantity of that product to get
// the current price for each of those products in the cart.
// Sum all product price totals to get the cart total.
decimal? total = decimal.Zero;
total = (decimal?)(from cartItems in _db.ShoppingCartItems
where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Quantity *

97
cartItems.Product.UnitPrice).Sum();
return total ?? decimal.Zero;
}

public ShoppingCartActions GetCart(HttpContext context)


{
using (var cart = new ShoppingCartActions())
{
cart.ShoppingCartId = cart.GetCartId();
return cart;
}
}

public void UpdateShoppingCartDatabase(String cartId, ShoppingCartUpdates[]


CartItemUpdates)
{
using (var db = new WingtipToys.Models.ProductContext())
{
try
{
int CartItemCount = CartItemUpdates.Count();
List<CartItem> myCart = GetCartItems();
foreach (var cartItem in myCart)
{
// Iterate through all rows within shopping cart list
for (int i = 0; i < CartItemCount; i++)
{
if (cartItem.Product.ProductID == CartItemUpdates[i].ProductId)
{
if (CartItemUpdates[i].PurchaseQuantity < 1 ||
CartItemUpdates[i].RemoveItem == true)
{
RemoveItem(cartId, cartItem.ProductId);
}
else
{
UpdateItem(cartId, cartItem.ProductId,
CartItemUpdates[i].PurchaseQuantity);
}
}
}
}
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Update Cart Database - " +
exp.Message.ToString(), exp);
}
}
}

98
public void RemoveItem(string removeCartID, int removeProductID)
{
using (var _db = new WingtipToys.Models.ProductContext())
{
try
{
var myItem = (from c in _db.ShoppingCartItems where c.CartId == removeCartID
&& c.Product.ProductID == removeProductID select c).FirstOrDefault();
if (myItem != null)
{
// Remove Item.
_db.ShoppingCartItems.Remove(myItem);
_db.SaveChanges();
}
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Remove Cart Item - " +
exp.Message.ToString(), exp);
}
}
}

public void UpdateItem(string updateCartID, int updateProductID, int quantity)


{
using (var _db = new WingtipToys.Models.ProductContext())
{
try
{
var myItem = (from c in _db.ShoppingCartItems where c.CartId == updateCartID
&& c.Product.ProductID == updateProductID select c).FirstOrDefault();
if (myItem != null)
{
myItem.Quantity = quantity;
_db.SaveChanges();
}
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Update Cart Item - " +
exp.Message.ToString(), exp);
}
}
}

public void EmptyCart()


{
ShoppingCartId = GetCartId();
var cartItems = _db.ShoppingCartItems.Where(
c => c.CartId == ShoppingCartId);
foreach (var cartItem in cartItems)
{
99
_db.ShoppingCartItems.Remove(cartItem);
}
// Save changes.
_db.SaveChanges();
}

public int GetCount()


{
ShoppingCartId = GetCartId();

// Get the count of each item in the cart and sum them up
int? count = (from cartItems in _db.ShoppingCartItems
where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Quantity).Sum();
// Return 0 if all entries are null
return count ?? 0;
}

public struct ShoppingCartUpdates


{
public int ProductId;
public int PurchaseQuantity;
public bool RemoveItem;
}
}

O método de UpdateShoppingCartDatabase , chamado de método UpdateCartItems na página


ShoppingCart.aspx.cs , contém a lógica para atualizar ou remover itens do carrinho de compras. O
método UpdateShoppingCartDatabase itera em todas as linhas dentro da lista de carrinho de
compras. Se um item de carrinho de compras foi marcado para ser removido, ou a quantidade é
menor que 1, é chamado o método RemoveItem . Caso contrário, o item de carrinho de compras
está marcado para as atualizações quando o método UpdateItem é chamado. Depois que o item de
carrinho de compras é removido ou atualizado, as alterações de banco de dados são salvos.

A estrutura ShoppingCartUpdates é usada para manter todos os itens do carrinho de compras. O


método UpdateShoppingCartDatabase usa a estrutura de ShoppingCartUpdates para determinar se
qualquer um dos itens precisam ser atualizados ou removidos.

O próximo tutorial, você usará o método EmptyCart para limpar o carrinho de compras após a
compra de produtos. Mas por agora, você usará o método de GetCount que você acabou de
adicionar para o arquivo ShoppingCartActions.cs para determinar quantos itens estão no carrinho
de compras.

Adicionar um contador de carrinho de compras

100
Para permitir que o usuário a exibir o número total de itens no carrinho de compras, você irá
adicionar um contador para a página mestra . Este contador também atuará como um link para o
carrinho de compras.

1. No Gerenciador de Soluções, abra a página Site.Master.

2. Modifique a marcação, adicionando o link de contador de carrinho compras conforme


mostrado em amarelo para a seção de navegação, então ele aparece da seguinte maneira:

<ul class="nav navbar-nav">


<li><a runat="server" href="~/">Home</a></li>
<li><a runat="server" href="~/About">About</a></li>
<li><a runat="server" href="~/Contact">Contact</a></li>
<li><a runat="server" href="~/ProductList">Products</a></li>
<li><a runat="server" href="~/ShoppingCart" ID="cartCount">&nbsp;</a></li>

</ul>

3. Em seguida, atualize o código-behind do arquivo Site.Master.cs , adicionando o código


destacado em amarelo como segue:

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Linq;
using WingtipToys.Models;
using WingtipToys.Logic;

namespace WingtipToys
{
public partial class SiteMaster : MasterPage
{
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;

protected void Page_Init(object sender, EventArgs e)


{
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out
requestCookieGuidValue))
{
// Use the Anti-XSRF token from the cookie
101
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;

var responseCookie = new HttpCookie(AntiXsrfTokenKey)


{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set(responseCookie);
}

Page.PreLoad += master_Page_PreLoad;
}

protected void master_Page_PreLoad(object sender, EventArgs e)


{
if (!IsPostBack)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ??
String.Empty;
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] !=
(Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of Anti-XSRF token
failed.");
}
}
}

protected void Page_Load(object sender, EventArgs e)


{

102
protected void Page_PreRender(object sender, EventArgs e)
{
using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
{
string cartStr = string.Format("Cart ({0})",
usersShoppingCart.GetCount());
cartCount.InnerText = cartStr;
}
}

public IQueryable<Category> GetCategories()


{
var _db = new WingtipToys.Models.ProductContext();
IQueryable<Category> query = _db.Categories;
return query;
}

protected void Unnamed_LoggingOut(object sender, LoginCancelEventArgs e)


{
Context.GetOwinContext().Authentication.SignOut();
}
}

Antes que a página é processada como o HTML, o evento Page_PreRender é gerado. No


manipulador de Page_PreRender , a contagem total de carrinho de compras é determinada
chamando o método GetCount . O valor retornado é adicionado para o span cartCount incluído na
marcação da página mestra . As tags <span> permite que os elementos internos ser processado
corretamente. Quando qualquer página do site é exibida, o total de compras carrinho será exibido.
O usuário também pode clicar o total de compras carrinho para exibir carrinho de compras.

Teste concluído o carrinho de compras


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

1. Pressione F5 para executar o aplicativo.


O navegador abre e mostra a página Default. aspx .

2. Selecione o menu de navegação da categoria carros .

3. Clique no link Adicionar ao carrinho , ao lado do primeiro produto.


A página da ShoppingCart.aspx é exibida com o total do pedido.

103
4. Selecione o menu de navegação da categoria aviões .

5. Clique no link Adicionar ao carrinho , ao lado do primeiro produto.

6. Defina a quantidade do primeiro item no carrinho de compras para 3 e selecione a caixa de


seleção Remover Item do segundo item.

7. Clique no botão Atualizar para atualizar a página do carrinho de compras e exibir o novo
total do pedido.

Resumo
Neste tutorial, você criou um carrinho de compras para o aplicativo de exemplo do Wingtip Toys
Web Forms. Durante este tutorial você usou Entity Framework Code First, anotações de dados,
controles de dados fortemente tipados e vinculação do modelo.

O carrinho de compras oferece suporte a adição, exclusão e atualizando itens que o usuário tiver
selecionado para compra. Além de implementar a funcionalidade de carrinho de compras, você
aprendeu como exibir compras carrinho itens em um controle GridView e calcular o total do
pedido.

104
07 - Check-out e pagamento com PayPal

Este tutorial descreve como modificar o aplicativo de exemplo do Wingtip Toys para incluir a
autorização do usuário, registro e pagamento através do PayPal. Somente os usuários que fizeram
logon terão autorização para comprar produtos. A funcionalidade de registro de usuário interno do
modelo de projeto do ASP.NET 4.5 Web Forms já inclui muito do que você precisa. Você irá
adicionar essa funcionalidade do PayPal Express Checkout. Neste tutorial, você estará usando o
ambiente de teste para desenvolvedores do PayPal, portanto não serão transferidos fundos reais.
Ao final do tutorial, você testará o aplicativo selecionando produtos para adicionar ao carrinho de
compras, clicando no botão de check-out e transferindo dados para o site de testes do PayPal. No
site de testes do PayPal, você confirmará suas informações de remessa e pagamento e, em
seguida, retornará ao aplicativo de exemplo Wingtip Toys local para confirmar e concluir a compra.

Existem vários processadores de pagamento de terceiros experientes que se especializam em


compras on-line, esse endereço escalabilidade e segurança. Os desenvolvedores ASP.NET devem
considerar as vantagens de utilizar uma solução de pagamento de terceiros antes de implementar
um shopping e comprar a solução.

Nota  

O aplicativo de exemplo do Wingtip Toys foi projetado para mostrados conceitos específicos do
ASP.NET e recursos disponíveis para os desenvolvedores da web ASP.NET. Este aplicativo de
exemplo não foi otimizado para todas as circunstâncias possíveis em relação à escalabilidade e
segurança.

O que você vai aprender:


 Como restringir o acesso a páginas específicas em uma pasta.

 Como criar um carrinho de compras conhecido de um carrinho de compras anônimo.

 Como usar o PayPal para comprar produtos usando o ambiente de teste do PayPal.

 Como exibir detalhes do PayPal em um DetailsView controle.


 Como atualizar o banco de dados do aplicativo Wingtip Toys com detalhes obtidos de
PayPal.

Rastreamento de ordem de adição


Neste tutorial, você criará duas novas classes para rastrear dados da ordem de que um usuário
criou. As classes controlarão os dados referentes a informações de remessa, total da compra e
confirmação do pagamento.

105
Adicionar as classes de modelo Order e OrderDetail
No início desta série de tutoriais, você definiu o esquema para categorias, produtos e itens de
carrinho de compras, criando as Category, Producte CartItem classes na pasta modelos . Agora
você irá adicionar duas novas classes para definir o esquema para a ordem do produto e os
detalhes da ordem.

1. Na pasta modelos , adicionar uma nova classe denominada Order.cs.


O novo arquivo de classe é exibido no editor.

2. Substitua o código padrão com o seguinte:

using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System.ComponentModel;

namespace WingtipToys.Models
{
public class Order
{
public int OrderId { get; set; }

public System.DateTime OrderDate { get; set; }

public string Username { get; set; }

[Required(ErrorMessage = "First Name is required")]


[DisplayName("First Name")]
[StringLength(160)]
public string FirstName { get; set; }

[Required(ErrorMessage = "Last Name is required")]


[DisplayName("Last Name")]
[StringLength(160)]
public string LastName { get; set; }

[Required(ErrorMessage = "Address is required")]


[StringLength(70)]
public string Address { get; set; }

[Required(ErrorMessage = "City is required")]


[StringLength(40)]
public string City { get; set; }

[Required(ErrorMessage = "State is required")]


[StringLength(40)]
public string State { get; set; }

106
[Required(ErrorMessage = "Postal Code is required")]
[DisplayName("Postal Code")]
[StringLength(10)]
public string PostalCode { get; set; }

[Required(ErrorMessage = "Country is required")]


[StringLength(40)]
public string Country { get; set; }

[StringLength(24)]
public string Phone { get; set; }

[Required(ErrorMessage = "Email Address is required")]


[DisplayName("Email Address")]
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}",
ErrorMessage = "Email is is not valid.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }

[ScaffoldColumn(false)]
public decimal Total { get; set; }

[ScaffoldColumn(false)]
public string PaymentTransactionId { get; set; }

[ScaffoldColumn(false)]
public bool HasBeenShipped { get; set; }

public List<OrderDetail> OrderDetails { get; set; }


}

3. Adicione uma classe OrderDetail.cs para a pasta de modelos .

4. Substitua o código padrão com o seguinte código:

using System.ComponentModel.DataAnnotations;

namespace WingtipToys.Models
{
public class OrderDetail
{
public int OrderDetailId { get; set; }

public int OrderId { get; set; }

107
public string Username { get; set; }

public int ProductId { get; set; }

public int Quantity { get; set; }

public double? UnitPrice { get; set; }

As classes de Order e OrderDetail contém o esquema para definir as informações de ordem


usadas para compra e transporte.

Além disso, você precisará atualizar a classe de contexto de banco de dados que gerencia as
classes de entidade e que fornece acesso a dados no banco de dados. Para fazer isso, você irá
adicionar as classes de modelo de ordem e OrderDetail recém-criado para ProductContext classe.

1. No Solution Explorer, localize e abra o arquivo ProductContext.cs .

2. Adicione o código realçado para o arquivo ProductContext.cs como mostrado abaixo:

using System.Data.Entity;

namespace WingtipToys.Models
{
public class ProductContext : DbContext
{
public ProductContext()
: base("WingtipToys")
{
}
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<CartItem> ShoppingCartItems { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
}

Como mencionado anteriormente nesta série tutorial, o código no arquivo ProductContext.cs


adiciona o namespace System.Data.Entity para que você tenha acesso a toda a funcionalidade de
108
núcleo do Entity Framework. Essa funcionalidade inclui a capacidade de consultar, inserir, atualizar
e excluir dados ao trabalhar com objetos com rigidez de tipos. O código acima na classe
ProductContext adiciona o Entity Framework acesso para as classes de Order e OrderDetail recém-
adicionado.

Adicionar o acesso de Checkout


O aplicativo de exemplo do Wingtip Toys permite que usuários anônimos rever e adicionar
produtos ao carrinho de compras. No entanto, quando usuários anônimos optar por adquirir os
produtos que adicionaram ao carrinho de compras, eles devem fazer logon para o site. Uma vez
que eles ligaram-se, eles podem acessar as páginas restritas do aplicativo da Web que lidar com o
check-out e o processo de compra. Estas páginas restritas estão contidas na pasta de saída do
aplicativo.

Adicionar uma pasta de Checkout e páginas


Agora você criará a pasta de saída e as páginas em que o cliente verá durante o processo de
checkout. Você irá atualizar estas páginas no final deste tutorial.

1. Botão direito do mouse no nome do projeto (Wingtip Toys) no Solution Explorer e


selecione Adicionar uma nova pasta.

2. Nomeie a nova pasta Checkout.

3. Botão direito do mouse a pasta de saída e selecione Adicionar --> Novo Item .

109
4. Caixa de diálogo Add New Item é exibida.

5. Selecione o Visual c# -> grupo de modelos Web à esquerda. Em seguida, o painel do


meio, selecione formulário da Web usando a página mestra e o nome CheckoutStart.aspx.

6. Como antes, selecione o arquivo Site.Master como a página mestra.

110
7. Adicione as seguintes páginas adicionais para a pasta de saída usando as mesmas etapas
acima:

 CheckoutReview.aspx
 CheckoutComplete.aspx
 CheckoutCancel.aspx
 CheckoutError.aspx
Adicionar um arquivo Web. config
Adicionando um novo arquivo Web. config para a pasta de saída , você será capaz de restringir o
acesso a todas as páginas contidas na pasta.

1. Clique com o botão direito do mouse na pasta Checkout e selecione Add -> New Item.
Caixa de diálogo Add New Item é exibida.

2. Selecione o Visual c# -> grupo de modelos Web à esquerda. Em seguida, o painel do


meio, selecione o Arquivo de configuração Web, aceite o nome padrão do Web. confige
selecione Adicionar.

3. Substitua o conteúdo de XML existente no arquivo Web. config com o seguinte:

<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>

</configuration>

4. Salve o arquivo Web. config .

O arquivo Web. config especifica que todos os usuários desconhecidos do aplicativo da Web
devem ser negados o acesso às páginas contidas na pasta check-out . No entanto, se o usuário
tiver registrado uma conta e fizer logon, será um usuário conhecido e terá acesso às páginas na
pasta check-out .

É importante observar que a configuração do ASP.NET segue uma hierarquia, onde cada arquivo
Web.config aplica parâmetros de configuração à pasta em que está e a todos os diretórios filho
abaixo dela.

Habilitar logons de outros Sites usando OAuth e OpenID


Web Forms do ASP.NET fornece opções avançadas para autenticação e associação. Esses
aprimoramentos incluem os novos provedores OAuth e OpenID . Usando esses provedores, você
111
pode deixar o registro de usuários em seu site usando suas credenciais existentes do Facebook,
Twitter, Windows Live e Google. Por exemplo, para fazer logon usando uma conta de Facebook, os
usuários podem escolher apenas uma opção de Facebook, que redireciona-los para a página de
login do Facebook onde entram suas credenciais de usuário. Eles então podem associar o
Facebook login com sua conta em seu site. Um realce relacionado aos recursos de associação
(ASP.NET identidade) de Web Forms do ASP.NET é que os usuários podem associar múltiplos
logons (incluindo logins de sites de redes sociais), com uma única conta em seu site.

Quando você adicionar um provedor de OAuth (Facebook, Twitter ou Windows Live) para seu
aplicativo ASP.NET Web Forms, você deve definir o valor de ID (chave) de aplicativo e um valor
secreto do aplicativo. Você pode adicionar esses valores para o arquivo Startup.Auth.cs em seu
aplicativo de formulários da Web. Além disso, você deve criar um aplicativo no site externo
(Facebook, Twitter ou Windows Live). Quando você cria o aplicativo no site externo, você pode
obter as chaves de aplicativo que você vai precisar para invocar o recurso de login para aqueles
locais.

Nota  

Aplicativos Windows Live só aceitam uma URL ao vivo para um site de trabalho, então você não
pode usar uma URL de site local para inícios de uma sessão de teste.

Para sites que usam um provedor de OpenID (Google), você não precisa criar um aplicativo no site
externo.

1. No Solution Explorer, localize e abra a pasta App_Start .

2. Abra o arquivo chamado Startup.Auth.cs.

3. Descomente a única linha de código destacado em amarelo para permitir que as contas do
Google OpenID como segue:

using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;

namespace WingtipToys
{
public partial class Startup {

// For more information on configuring authentication, please visit


http://go.microsoft.com/fwlink/?LinkId=301883
public void ConfigureAuth(IAppBuilder app)
{
// Enable the application to use a cookie to store information for the
signed in user
// and also store information about a user logging in with a third party
login provider.
// This is required if your application allows users to login

112
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

// Uncomment the following lines to enable logging in with third party


login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");

//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");

//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");

app.UseGoogleAuthentication();
}
}

4. Salve o arquivo Startup.Auth.cs .

Quando você executar o aplicativo de amostra do Wingtip Toys, você terá a opção de acessar sua
conta do Google e associar sua conta do Wingtip Toys com a conta do Google.

Modificar a funcionalidade de Login


Como mencionado anteriormente nesta série tutorial, grande parte da funcionalidade de registo
de usuário foi incluída no modelo de Web Forms do ASP.NET por padrão. Agora você modificará as
páginas de login. aspx e Register. aspx padrão para chamar o método MigrateCart . O método
MigrateCart associa um usuário recém logado com um carrinho de compras anônimo. Por associar
o usuário e carrinho de compras, o aplicativo de exemplo do Wingtip Toys será capaz de manter o
carrinho de compras do usuário entre as visitas.

1. No Solution Explorer, localize e abra a pasta da conta .

2. Modifique a página code-behind chamada Login.aspx.cs para incluir o código destacado em


amarelo, para que ele apareça da seguinte forma:

113
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using System;
using System.Linq;
using System.Web;
using System.Web.UI;
using WingtipToys.Models;

namespace WingtipToys.Account
{
public partial class Login : Page
{
protected void Page_Load(object sender, EventArgs e)
{
RegisterHyperLink.NavigateUrl = "Register";
OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"];
var returnUrl = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]);
if (!String.IsNullOrEmpty(returnUrl))
{
RegisterHyperLink.NavigateUrl += "?ReturnUrl=" + returnUrl;
}
}

protected void LogIn(object sender, EventArgs e)


{
if (IsValid)
{
// Validate the user password
var manager = new UserManager();
ApplicationUser user = manager.Find(UserName.Text, Password.Text);
if (user != null)
{
IdentityHelper.SignIn(manager, user, RememberMe.Checked);

WingtipToys.Logic.ShoppingCartActions usersShoppingCart = new


WingtipToys.Logic.ShoppingCartActions();
String cartId = usersShoppingCart.GetCartId();
usersShoppingCart.MigrateCart(cartId, UserName.Text);

IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else
{
FailureText.Text = "Invalid username or password.";
ErrorMessage.Visible = true;
}
}

114
}
}

3. Salve o arquivo Login.aspx.cs .

Por enquanto, você pode ignorar o aviso de que não há definição para o método de MigrateCart .
Você estará adicionando um pouco mais tarde neste tutorial.

O arquivo de code-behind Login.aspx.cs oferece suporte a um método de logon. Ao examinar a


página Login.aspx, você verá que essa página inclui um botão “Log in” que, quando clicado, aciona
o manipulador LogIn no code-behind.

Quando é chamado o método de Login sobre o Login.aspx.cs , uma nova instância do carrinho de
compras chamado usersShoppingCart é criada. A identificação do carrinho de compras (um GUID)
é obtida e defina a variável de cartId . Em seguida, o método MigrateCart é chamado, passando
tanto a cartId e o nome do usuário conectado a este método. Quando o carrinho de compras é
migrado, o GUID usado para identificar o carrinho de compras anônimo é substituído com o nome
de usuário.

Além de modificar o arquivo de code-behind Login.aspx.cs para migrar o carrinho de compras,


quando o usuário fizer logon, você também deve modificar o arquivo de code-behind
Register.aspx.cs para migrar o carrinho de compras, quando o usuário cria uma nova conta e
registra.

1. Na pasta de conta , abra o arquivo code-behind, chamado Register.aspx.cs.

2. Modificar o arquivo code-behind, incluindo o código em amarelo, para que ele apareça da
seguinte forma:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using System;
using System.Linq;
using System.Web;
using System.Web.UI;
using WingtipToys.Models;

namespace WingtipToys.Account
{
public partial class Register : Page
{
protected void CreateUser_Click(object sender, EventArgs e)
{
var manager = new UserManager();
var user = new ApplicationUser() { UserName = UserName.Text };

115
IdentityResult result = manager.Create(user, Password.Text);
if (result.Succeeded)
{
IdentityHelper.SignIn(manager, user, isPersistent: false);

using (WingtipToys.Logic.ShoppingCartActions usersShoppingCart = new


WingtipToys.Logic.ShoppingCartActions())
{
String cartId = usersShoppingCart.GetCartId();
usersShoppingCart.MigrateCart(cartId, user.Id);
}

IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"],
Response);
}
else
{
ErrorMessage.Text = result.Errors.FirstOrDefault();
}
}
}
}

3. Salve o arquivo Register.aspx.cs . Mais uma vez, ignore o aviso sobre o método de
MigrateCart .

Observe que o código usado no manipulador de eventos CreateUser_Click é muito semelhante ao


código que você usou o método de LogIn . Quando o usuário registra ou faz logon no site, será
feita uma chamada para o método de MigrateCart .

Migrando o carrinho de compras


Agora que você tem o processo de log-in e registro atualizado, você pode adicionar o código para
migrar o carrinho de compras — o método de MigrateCart .

1. No Solution Explorer, localize a pasta lógica e abra o arquivo de classe


ShoppingCartActions.cs .

2. Adicione o código realçado em amarelo para o código existente no arquivo


ShoppingCartActions.cs , para que o código no arquivo ShoppingCartActions.cs aparece da seguinte
maneira:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WingtipToys.Models;

namespace WingtipToys.Logic

116
{
public class ShoppingCartActions : IDisposable
{
public string ShoppingCartId { get; set; }

private ProductContext _db = new ProductContext();

public const string CartSessionKey = "CartId";

public void AddToCart(int id)


{
// Retrieve the product from the database.
ShoppingCartId = GetCartId();

var cartItem = _db.ShoppingCartItems.SingleOrDefault(


c => c.CartId == ShoppingCartId
&& c.ProductId == id);
if (cartItem == null)
{
// Create a new cart item if no cart item exists.
cartItem = new CartItem
{
ItemId = Guid.NewGuid().ToString(),
ProductId = id,
CartId = ShoppingCartId,
Product = _db.Products.SingleOrDefault(
p => p.ProductID == id),
Quantity = 1,
DateCreated = DateTime.Now
};

_db.ShoppingCartItems.Add(cartItem);
}
else
{
// If the item does exist in the cart,
// then add one to the quantity.
cartItem.Quantity++;
}
_db.SaveChanges();
}

public void Dispose()


{
if (_db != null)
{
_db.Dispose();
_db = null;
}

117
}

public string GetCartId()


{
if (HttpContext.Current.Session[CartSessionKey] == null)
{
if (!string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
{
HttpContext.Current.Session[CartSessionKey] =
HttpContext.Current.User.Identity.Name;
}
else
{
// Generate a new random GUID using System.Guid class.
Guid tempCartId = Guid.NewGuid();
HttpContext.Current.Session[CartSessionKey] = tempCartId.ToString();
}
}
return HttpContext.Current.Session[CartSessionKey].ToString();
}

public List<CartItem> GetCartItems()


{
ShoppingCartId = GetCartId();

return _db.ShoppingCartItems.Where(
c => c.CartId == ShoppingCartId).ToList();
}

public decimal GetTotal()


{
ShoppingCartId = GetCartId();
// Multiply product price by quantity of that product to get
// the current price for each of those products in the cart.
// Sum all product price totals to get the cart total.
decimal? total = decimal.Zero;
total = (decimal?)(from cartItems in _db.ShoppingCartItems
where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Quantity *
cartItems.Product.UnitPrice).Sum();
return total ?? decimal.Zero;
}

public ShoppingCartActions GetCart(HttpContext context)


{
using (var cart = new ShoppingCartActions())
{
cart.ShoppingCartId = cart.GetCartId();
return cart;
}

118
}

public void UpdateShoppingCartDatabase(String cartId, ShoppingCartUpdates[]


CartItemUpdates)
{
using (var db = new WingtipToys.Models.ProductContext())
{
try
{
int CartItemCount = CartItemUpdates.Count();
List<CartItem> myCart = GetCartItems();
foreach (var cartItem in myCart)
{
// Iterate through all rows within shopping cart list
for (int i = 0; i < CartItemCount; i++)
{
if (cartItem.Product.ProductID == CartItemUpdates[i].ProductId)
{
if (CartItemUpdates[i].PurchaseQuantity < 1 ||
CartItemUpdates[i].RemoveItem == true)
{
RemoveItem(cartId, cartItem.ProductId);
}
else
{
UpdateItem(cartId, cartItem.ProductId,
CartItemUpdates[i].PurchaseQuantity);
}
}
}
}
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Update Cart Database - " +
exp.Message.ToString(), exp);
}
}
}

public void RemoveItem(string removeCartID, int removeProductID)


{
using (var _db = new WingtipToys.Models.ProductContext())
{
try
{
var myItem = (from c in _db.ShoppingCartItems where c.CartId == removeCartID
&& c.Product.ProductID == removeProductID select c).FirstOrDefault();
if (myItem != null)
{
// Remove Item.
_db.ShoppingCartItems.Remove(myItem);

119
_db.SaveChanges();
}
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Remove Cart Item - " +
exp.Message.ToString(), exp);
}
}
}

public void UpdateItem(string updateCartID, int updateProductID, int quantity)


{
using (var _db = new WingtipToys.Models.ProductContext())
{
try
{
var myItem = (from c in _db.ShoppingCartItems where c.CartId == updateCartID
&& c.Product.ProductID == updateProductID select c).FirstOrDefault();
if (myItem != null)
{
myItem.Quantity = quantity;
_db.SaveChanges();
}
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Update Cart Item - " +
exp.Message.ToString(), exp);
}
}
}

public void EmptyCart()


{
ShoppingCartId = GetCartId();
var cartItems = _db.ShoppingCartItems.Where(
c => c.CartId == ShoppingCartId);
foreach (var cartItem in cartItems)
{
_db.ShoppingCartItems.Remove(cartItem);
}
// Save changes.
_db.SaveChanges();
}

public int GetCount()


{
ShoppingCartId = GetCartId();

// Get the count of each item in the cart and sum them up

120
int? count = (from cartItems in _db.ShoppingCartItems
where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Quantity).Sum();
// Return 0 if all entries are null
return count ?? 0;
}

public struct ShoppingCartUpdates


{
public int ProductId;
public int PurchaseQuantity;
public bool RemoveItem;
}

public void MigrateCart(string cartId, string userName)


{
var shoppingCart = _db.ShoppingCartItems.Where(c => c.CartId == cartId);
foreach (CartItem item in shoppingCart)
{
item.CartId = userName;
}
HttpContext.Current.Session[CartSessionKey] = userName;
_db.SaveChanges();
}
}

O método MigrateCart usa o cartId existente para encontrar o carrinho de compras do usuário. Em
seguida, o código percorrerá todos os itens do carrinho de compras e substitui a propriedade
CartId (conforme especificado pelo esquema CartItem ) com o nome do usuário conectado.

Atualizando a conexão de banco de dados


Se você está seguindo este tutorial usando o pré-construídos aplicativo de exemplo do Wingtip
Toys, você deve recriar o banco de dados de associação padrão. Modificando-se a seqüência de
conexão padrão, o banco de dados de associação será criado na próxima vez que o aplicativo é
executado.

1. Abra o arquivo Web. config na raiz do projeto.

2. Atualize seqüência de conexão padrão para que ele apareça da seguinte forma:

<add name="DefaultConnection" connectionString="Data


Source=(LocalDb)\v11.0;Initial Catalog=aspnet-WingtipToys;Integrated Security=True"
providerName="System.Data.SqlClient" />

Integração PayPal
121
PayPal é uma plataforma de faturamento baseado em web que aceita pagamentos por
comerciantes on-line. Neste tutorial, em seguida, explica como integrar funcionalidade de Express
Checkout do PayPal no seu aplicativo. O Express Checkout permite que seus clientes utilizem o
PayPal para pagar pelos artigos que adicionaram ao carrinho de compras.

Criar contas de teste PaylPal

Para usar o PayPal em ambiente de teste, você deve criar e verificar uma conta de teste do
desenvolvedor. Você usará a conta de teste do desenvolvedor para criar um comprador conta de
teste e uma conta de teste do vendedor. As credenciais de conta de teste do desenvolvedor
também permitirá que o aplicativo de exemplo do Wingtip Toys acessar o ambiente de teste do
PayPal.

1. Em um navegador, navegar para o desenvolvedor PayPal testando o site:


https://Developer.paypal.com

2. Se você não tiver uma conta de desenvolvedor do PayPal, criar uma nova conta clicando em
Cadastre-se e seguindo o etapas de inscrição. Se você tiver uma conta de desenvolvedor existente
do PayPal, Cadastre-se clicando em Log In. Você vai precisar de sua conta de desenvolvedor de
PayPal para testar o aplicativo de exemplo do Wingtip Toys no final deste tutorial.

3. Se você se inscreveu para sua conta de desenvolvedor do PayPal, você pode precisar
verificar a sua conta de desenvolvedor PayPal com PayPal. Você pode verificar sua conta,
seguindo os passos que o PayPal enviada para sua conta de e-mail. Uma vez que você
verificou que sua conta de desenvolvedor do PayPal, log de volta para o desenvolvedor
PayPal testando o site.

4. Depois que você está logado no site do desenvolvedor PayPal com sua conta de
desenvolvedor do PayPal que você precisa criar uma conta de teste do comprador PayPal se você
ainda não tem um. Para criar uma conta de teste do comprador, no site do PayPal clique na guia
aplicativos e em seguida, clique em contas de Sandbox.
A página de Sandbox contas de teste é mostrada.

Nota  

O site do desenvolvedor PayPal já fornece uma conta de teste mercantes.

122
5. Na caixa de areia teste página contas, clique em Criar conta.

6. Na página criar conta de teste escolha um comprador teste conta de e-mail e senha de
sua escolha.

Nota  

Você vai precisar os endereços de e-mail do comprador e a senha para testar o aplicativo de
exemplo do Wingtip Toys no final deste tutorial.

123
124
7. Crie conta de teste o comprador clicando no botão Criar conta .
A página de teste Sandbox contas é exibida.

8. Na página contas de teste Sandbox , clique na conta de e-mail do facilitador .


Opções de perfil e notificação aparecem.

9. Selecione a opção de perfil e, em seguida, clique em credenciais de API para exibir suas
credenciais de API para a conta de teste mercantes.

10. Copie as credenciais teste API para o bloco de notas.

Você precisará de suas credenciais clássico teste API exibidas (nome de usuário, senha e assinatura)
para fazer chamadas de API do aplicativo de exemplo Wingtip Toys para o PayPal, ambiente de
teste. Você adicionará as credenciais na próxima etapa.

Adicionar a classe de PayPal e credenciais de API

Você colocará a maioria do código PayPal em uma única classe. Esta classe contém os métodos
usados para se comunicar com o PayPal. Além disso, você irá adicionar suas credenciais de PayPal
para essa classe.

1. No aplicativo de amostra Wingtip Toys dentro do Visual Studio, clique com botão direito na
pasta lógica e selecione Add -> New Item.
Caixa de diálogo Add New Item é exibida.

2. No Visual c#, no painel Instalado à esquerda, selecione Código.


125
3. O painel do meio, selecione classe. Nomeie esta nova classe PayPalFunctions.cs.

4. Clique em Adicionar.
O novo arquivo de classe é exibido no editor.

5. Substitua o código padrão com o seguinte código:

using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Data;
using System.Configuration;
using System.Web;
using WingtipToys;
using WingtipToys.Models;
using System.Collections.Generic;
using System.Linq;

public class NVPAPICaller


{
//Flag that determines the PayPal environment (live or sandbox)
private const bool bSandbox = true;
private const string CVV2 = "CVV2";

// Live strings.
private string pEndPointURL = "https://api-3t.paypal.com/nvp";
private string host = "www.paypal.com";

// Sandbox strings.
private string pEndPointURL_SB = "https://api-3t.sandbox.paypal.com/nvp";
private string host_SB = "www.sandbox.paypal.com";

private const string SIGNATURE = "SIGNATURE";


private const string PWD = "PWD";
private const string ACCT = "ACCT";

//Replace <Your API Username> with your API Username


//Replace <Your API Password> with your API Password
//Replace <Your Signature> with your Signature
public string APIUsername = "<Your API Username>";
private string APIPassword = "<Your API Password>";
private string APISignature = "<Your Signature>";
private string Subject = "";
private string BNCode = "PP-ECWizard";

126
//HttpWebRequest Timeout specified in milliseconds
private const int Timeout = 15000;
private static readonly string[] SECURED_NVPS = new string[] { ACCT, CVV2,
SIGNATURE, PWD };

public void SetCredentials(string Userid, string Pwd, string Signature)


{
APIUsername = Userid;
APIPassword = Pwd;
APISignature = Signature;
}

public bool ShortcutExpressCheckout(string amt, ref string token, ref string retMsg)
{
if (bSandbox)
{
pEndPointURL = pEndPointURL_SB;
host = host_SB;
}

string returnURL = "http://localhost:1234/Checkout/CheckoutReview.aspx";


string cancelURL = "http://localhost:1234/Checkout/CheckoutCancel.aspx";

NVPCodec encoder = new NVPCodec();


encoder["METHOD"] = "SetExpressCheckout";
encoder["RETURNURL"] = returnURL;
encoder["CANCELURL"] = cancelURL;
encoder["BRANDNAME"] = "Wingtip Toys Sample Application";
encoder["PAYMENTREQUEST_0_AMT"] = amt;
encoder["PAYMENTREQUEST_0_ITEMAMT"] = amt;
encoder["PAYMENTREQUEST_0_PAYMENTACTION"] = "Sale";
encoder["PAYMENTREQUEST_0_CURRENCYCODE"] = "USD";

// Get the Shopping Cart Products


using (WingtipToys.Logic.ShoppingCartActions myCartOrders = new
WingtipToys.Logic.ShoppingCartActions())
{
List<CartItem> myOrderList = myCartOrders.GetCartItems();

for (int i = 0; i < myOrderList.Count; i++)


{
encoder["L_PAYMENTREQUEST_0_NAME" + i] =
myOrderList[i].Product.ProductName.ToString();
encoder["L_PAYMENTREQUEST_0_AMT" + i] =
myOrderList[i].Product.UnitPrice.ToString();
encoder["L_PAYMENTREQUEST_0_QTY" + i] = myOrderList[i].Quantity.ToString();
}
}

string pStrrequestforNvp = encoder.Encode();

127
string pStresponsenvp = HttpCall(pStrrequestforNvp);

NVPCodec decoder = new NVPCodec();


decoder.Decode(pStresponsenvp);

string strAck = decoder["ACK"].ToLower();


if (strAck != null && (strAck == "success" || strAck == "successwithwarning"))
{
token = decoder["TOKEN"];
string ECURL = "https://" + host + "/cgi-bin/webscr?cmd=_express-checkout" +
"&token=" + token;
retMsg = ECURL;
return true;
}
else
{
retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" +
"Desc=" + decoder["L_SHORTMESSAGE0"] + "&" +
"Desc2=" + decoder["L_LONGMESSAGE0"];
return false;
}
}

public bool GetCheckoutDetails(string token, ref string PayerID, ref NVPCodec


decoder, ref string retMsg)
{
if (bSandbox)
{
pEndPointURL = pEndPointURL_SB;
}

NVPCodec encoder = new NVPCodec();


encoder["METHOD"] = "GetExpressCheckoutDetails";
encoder["TOKEN"] = token;

string pStrrequestforNvp = encoder.Encode();


string pStresponsenvp = HttpCall(pStrrequestforNvp);

decoder = new NVPCodec();


decoder.Decode(pStresponsenvp);

string strAck = decoder["ACK"].ToLower();


if (strAck != null && (strAck == "success" || strAck == "successwithwarning"))
{
PayerID = decoder["PAYERID"];
return true;
}
else
{

128
retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" +
"Desc=" + decoder["L_SHORTMESSAGE0"] + "&" +
"Desc2=" + decoder["L_LONGMESSAGE0"];

return false;
}
}

public bool DoCheckoutPayment(string finalPaymentAmount, string token, string


PayerID, ref NVPCodec decoder, ref string retMsg)
{
if (bSandbox)
{
pEndPointURL = pEndPointURL_SB;
}

NVPCodec encoder = new NVPCodec();


encoder["METHOD"] = "DoExpressCheckoutPayment";
encoder["TOKEN"] = token;
encoder["PAYERID"] = PayerID;
encoder["PAYMENTREQUEST_0_AMT"] = finalPaymentAmount;
encoder["PAYMENTREQUEST_0_CURRENCYCODE"] = "USD";
encoder["PAYMENTREQUEST_0_PAYMENTACTION"] = "Sale";

string pStrrequestforNvp = encoder.Encode();


string pStresponsenvp = HttpCall(pStrrequestforNvp);

decoder = new NVPCodec();


decoder.Decode(pStresponsenvp);

string strAck = decoder["ACK"].ToLower();


if (strAck != null && (strAck == "success" || strAck == "successwithwarning"))
{
return true;
}
else
{
retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" +
"Desc=" + decoder["L_SHORTMESSAGE0"] + "&" +
"Desc2=" + decoder["L_LONGMESSAGE0"];

return false;
}
}

public string HttpCall(string NvpRequest)


{
string url = pEndPointURL;

129
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);

HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);


objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;

try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost);
}
}
catch (Exception)
{
// No logging for this tutorial.
}

//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}

return result;
}

private string buildCredentialsNVPString()


{
NVPCodec codec = new NVPCodec();

if (!IsEmpty(APIUsername))
codec["USER"] = APIUsername;

if (!IsEmpty(APIPassword))
codec[PWD] = APIPassword;

if (!IsEmpty(APISignature))
codec[SIGNATURE] = APISignature;

if (!IsEmpty(Subject))
codec["SUBJECT"] = Subject;

codec["VERSION"] = "88.0";

130
return codec.Encode();
}

public static bool IsEmpty(string s)


{
return s == null || s.Trim() == string.Empty;
}
}

public sealed class NVPCodec : NameValueCollection


{
private const string AMPERSAND = "&";
private const string EQUALS = "=";
private static readonly char[] AMPERSAND_CHAR_ARRAY = AMPERSAND.ToCharArray();
private static readonly char[] EQUALS_CHAR_ARRAY = EQUALS.ToCharArray();

public string Encode()


{
StringBuilder sb = new StringBuilder();
bool firstPair = true;
foreach (string kv in AllKeys)
{
string name = HttpUtility.UrlEncode(kv);
string value = HttpUtility.UrlEncode(this[kv]);
if (!firstPair)
{
sb.Append(AMPERSAND);
}
sb.Append(name).Append(EQUALS).Append(value);
firstPair = false;
}
return sb.ToString();
}

public void Decode(string nvpstring)


{
Clear();
foreach (string nvp in nvpstring.Split(AMPERSAND_CHAR_ARRAY))
{
string[] tokens = nvp.Split(EQUALS_CHAR_ARRAY);
if (tokens.Length >= 2)
{
string name = HttpUtility.UrlDecode(tokens[0]);
string value = HttpUtility.UrlDecode(tokens[1]);
Add(name, value);
}
}
}

131
public void Add(string name, string value, int index)
{
this.Add(GetArrayName(index, name), value);
}

public void Remove(string arrayName, int index)


{
this.Remove(GetArrayName(index, arrayName));
}

public string this[string name, int index]


{
get
{
return this[GetArrayName(index, name)];
}
set
{
this[GetArrayName(index, name)] = value;
}
}

private static string GetArrayName(int index, string name)


{
if (index < 0)
{
throw new ArgumentOutOfRangeException("index", "index cannot be negative : " +
index);
}
return name + index;
}

6. Adicione as credenciais de comerciante API (nome de usuário, senha e assinatura) que você
exibido anteriormente neste tutorial para que você possa fazer chamadas de função para
o ambiente de teste do PayPal.

public string APIUsername = "<Your API Username>";


private string APIPassword = "<Your API Password>";

private string APISignature = "<Your Signature>";

Nota  

132
Neste aplicativo de exemplo você está simplesmente adicionando credenciais em um arquivo c# (.
cs). No entanto, em uma solução implementada, você deve considerar criptografar suas credenciais
em um arquivo de configuração.

A classe NVPAPICaller contém a maioria da funcionalidade do PayPal. O código na classe fornece


os métodos necessários para fazer um teste de compra a partir do ambiente de teste do PayPal. As
três seguintes funções do PayPal são usadas para fazer compras:

 Função SetExpressCheckout
 Função GetExpressCheckoutDetails
 Função DoExpressCheckoutPayment

O método ShortcutExpressCheckout recolhe os detalhes de informações e o produto de compra


do teste de carrinho de compras e chama a função de PayPal de SetExpressCheckout . O método
GetCheckoutDetails confirma detalhes da compra e chama a função de PayPal de
GetExpressCheckoutDetails antes de fazer o teste de compra. O método de DoCheckoutPayment
completa a compra de teste do ambiente de teste, chamando a função DoExpressCheckoutPayment
PayPal. O restante do código suporta os métodos de PayPal e processo, tais como seqüências de
caracteres de codificação, decodificação seqüências de caracteres, matrizes de transformação e
determinar as credenciais.

Nota  

PayPal permite que você inclua detalhes de compra opcional, com base na especificação da API do
PayPal. Estendendo o código no aplicativo de amostra Wingtip Toys, você pode incluir detalhes de
localização, descrições de produto, imposto, um número de serviço ao cliente, bem como muitos
outros campos opcionais.

Observe que o retorno e cancelar URLs que são especificados no método


ShortcutExpressCheckout usam um número de porta.

string returnURL = "http://localhost:1234/Checkout/CheckoutReview.aspx";


string cancelURL = "http://localhost:1234/Checkout/CheckoutCancel.aspx";

Quando o Visual Web Developer executa um projeto web, uma porta aleatória é usada para o
servidor web. Como mostrado acima, o número da porta é 1234. Quando você executar o
aplicativo, você provavelmente verá um número de porta diferente. Seu número de porta precisa
ser definido no código acima para que você possa executar com êxito o aplicativo de exemplo
Wingtip Toys ao final deste tutorial. A próxima seção deste tutorial explica como recuperar o
número da porta do host local e atualizar a classe PayPal.

Atualizar o número da porta de LocalHost na classe de PayPal

O aplicativo de exemplo do Wingtip Toys compra produtos navegando no site de teste de PayPal e
retornando a sua instância local do aplicativo de exemplo Wingtip Toys. Para ter PayPal retornar

133
para a URL correta, você precisa especificar o número da porta da executando localmente amostra
de aplicativo no código PayPal acima mencionado.

1. Botão direito do mouse no nome do projeto (WingtipToys) no Solution Explorer e


selecione Propriedades.

2. Na coluna da esquerda, selecione a guia da Web .

3. Recupere o número da porta na caixa Url do projeto .

4. Atualize o returnURL e cancelURL na classe de PayPal (NVPAPICaller) no arquivo


PayPalFunctions.cs para usar o número da porta de seu aplicativo da web:

string returnURL = "http://localhost:<Your Port


Number>/Checkout/CheckoutReview.aspx";

string cancelURL = "http://localhost:<Your Port


Number>/Checkout/CheckoutCancel.aspx";

Agora o código que você adicionou corresponderá a porta esperada para seu aplicativo da Web
local. PayPal será capaz de retornar para a URL correta na sua máquina local.

Adicione o botão do PayPal Checkout

Agora que as principais funções do PayPal foram adicionadas para o aplicativo de exemplo, você
pode começar adicionando a marcação e o código necessário para chamar essas funções. Primeiro,
você deve adicionar o botão checkout que o usuário verá na página de carrinho de compras.

1. Abra o arquivo ShoppingCart.aspx .

2. Vá até o final do arquivo e encontrar o <!--Checkout Placeholder --> comentário.

3. Substitua o comentário com um ImageButton controle para que a marca se é ter a seguinte
redacção:

<asp:ImageButton ID="CheckoutImageBtn" runat="server"

ImageUrl="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"
Width="145" AlternateText="Check out with PayPal"
OnClick="CheckoutBtn_Click"

BackColor="Transparent" BorderWidth="0" />

4. No ShoppingCart.aspx.cs Lima, após o manipulador de eventos UpdateBtn_Click perto do


final do arquivo, adicione o manipulador de eventos CheckOutBtn_Click :

protected void CheckoutBtn_Click(object sender, ImageClickEventArgs e)


{

134
using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
{
Session["payment_amt"] = usersShoppingCart.GetTotal();
}
Response.Redirect("Checkout/CheckoutStart.aspx");

5. Também no arquivo ShoppingCart.aspx.cs , adicione uma referência para o CheckoutBtn,


para que o novo botão de imagem é referenciado como segue:

protected void Page_Load(object sender, EventArgs e)


{
using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions())
{
decimal cartTotal = 0;
cartTotal = usersShoppingCart.GetTotal();
if (cartTotal > 0)
{
// Display Total.
lblTotal.Text = String.Format("{0:c}", cartTotal);
}
else
{
LabelTotalText.Text = "";
lblTotal.Text = "";
ShoppingCartTitle.InnerText = "Shopping Cart is Empty";
UpdateBtn.Visible = false;
CheckoutImageBtn.Visible = false;
}
}

6. Salve as alterações para o arquivo ShoppingCart.aspx e o arquivo de ShoppingCart.aspx.cs .

7. No menu, selecione Debug --> Build WingtipToys .


O projeto será reconstruído com o ImageButton controle recém-adicionado.

Envie informações de compra para o PayPal


Quando o usuário clica no botão Checkout na página do carrinho de compras (ShoppingCart.aspx),
eles começará o processo de compra. O código a seguir chama a função de PayPal primeira
necessária para comprar produtos.

1. Da pasta de saída , abra o arquivo code-behind, chamado CheckoutStart.aspx.cs.


Não se esqueça de abrir o arquivo code-behind.

2. Substitua o código existente com o seguinte:

135
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WingtipToys.Checkout
{
public partial class CheckoutStart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
NVPAPICaller payPalCaller = new NVPAPICaller();
string retMsg = "";
string token = "";

if (Session["payment_amt"] != null)
{
string amt = Session["payment_amt"].ToString();

bool ret = payPalCaller.ShortcutExpressCheckout(amt, ref token, ref retMsg);


if (ret)
{
Session["token"] = token;
Response.Redirect(retMsg);
}
else
{
Response.Redirect("CheckoutError.aspx?" + retMsg);
}
}
else
{
Response.Redirect("CheckoutError.aspx?ErrorCode=AmtMissing");
}
}
}

Quando o usuário do aplicativo clica no botão Checkout na página de carrinho de compras, o


navegador irá navegar para a página CheckoutStart.aspx . Quando carrega a página
CheckoutStart.aspx , o método ShortcutExpressCheckout é chamado. Neste ponto, o usuário é
transferido para o site PayPal teste. No site do PayPal, o usuário insere suas credenciais de PayPal,
os detalhes de compra de clientes, aceita o acordo de PayPal e retorna para o aplicativo de
amostra do Wingtip Toys onde o método de ShortcutExpressCheckout completa. Quando o

136
método ShortcutExpressCheckout é completo, ele irá redirecionar o usuário para a página
CheckoutReview.aspx especificada no método ShortcutExpressCheckout . Isto permite ao usuário
examinar os detalhes da ordem de dentro do aplicativo de amostra do Wingtip Toys.

Detalhes do pedido de revisão


Depois de retornar do PayPal, a página CheckoutReview.aspx do aplicativo de exemplo Wingtip
Toys exibe os detalhes do pedido. Esta página permite ao usuário examinar os detalhes do pedido
antes de comprar os produtos. A página de CheckoutReview.aspx deve ser criada da seguinte
maneira:

1. Na caixa pasta, abra a página chamada CheckoutReview.aspx.

2. Substitua a marcação existente com o seguinte:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"


CodeBehind="CheckoutReview.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutReview" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Order Review</h1>
<p></p>
<h3 style="padding-left: 33px">Products:</h3>
<asp:GridView ID="OrderItemList" runat="server" AutoGenerateColumns="False"
GridLines="Both" CellPadding="10" Width="500" BorderColor="#efeeef" BorderWidth="33">
<Columns>
<asp:BoundField DataField="ProductId" HeaderText=" Product ID" />
<asp:BoundField DataField="Product.ProductName" HeaderText=" Product Name"
/>
<asp:BoundField DataField="Product.UnitPrice" HeaderText="Price (each)"
DataFormatString="{0:c}"/>
<asp:BoundField DataField="Quantity" HeaderText="Quantity" />
</Columns>
</asp:GridView>
<asp:DetailsView ID="ShipInfo" runat="server" AutoGenerateRows="false"
GridLines="None" CellPadding="10" BorderStyle="None" CommandRowStyle-
BorderStyle="None">
<Fields>
<asp:TemplateField>
<ItemTemplate>
<h3>Shipping Address:</h3>
<br />
<asp:Label ID="FirstName" runat="server" Text='<%#: Eval("FirstName")
%>'></asp:Label>
<asp:Label ID="LastName" runat="server" Text='<%#: Eval("LastName")
%>'></asp:Label>
<br />
<asp:Label ID="Address" runat="server" Text='<%#: Eval("Address")
%>'></asp:Label>
<br />
<asp:Label ID="City" runat="server" Text='<%#: Eval("City")
%>'></asp:Label>
<asp:Label ID="State" runat="server" Text='<%#: Eval("State")
%>'></asp:Label>

137
<asp:Label ID="PostalCode" runat="server" Text='<%#:
Eval("PostalCode") %>'></asp:Label>
<p></p>
<h3>Order Total:</h3>
<br />
<asp:Label ID="Total" runat="server" Text='<%#: Eval("Total", "{0:C}")
%>'></asp:Label>
</ItemTemplate>
<ItemStyle HorizontalAlign="Left" />
</asp:TemplateField>
</Fields>
</asp:DetailsView>
<p></p>
<hr />
<asp:Button ID="CheckoutConfirm" runat="server" Text="Complete Order"
OnClick="CheckoutConfirm_Click" />

</asp:Content>

3. Abra a página code-behind, chamada CheckoutReview.aspx.cs e substitua o código existente


com o seguinte:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;

namespace WingtipToys.Checkout
{
public partial class CheckoutReview : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
NVPAPICaller payPalCaller = new NVPAPICaller();

string retMsg = "";


string token = "";
string PayerID = "";
NVPCodec decoder = new NVPCodec();
token = Session["token"].ToString();

bool ret = payPalCaller.GetCheckoutDetails(token, ref PayerID, ref decoder,


ref retMsg);

138
if (ret)
{
Session["payerId"] = PayerID;

var myOrder = new Order();


myOrder.OrderDate = Convert.ToDateTime(decoder["TIMESTAMP"].ToString());
myOrder.Username = User.Identity.Name;
myOrder.FirstName = decoder["FIRSTNAME"].ToString();
myOrder.LastName = decoder["LASTNAME"].ToString();
myOrder.Address = decoder["SHIPTOSTREET"].ToString();
myOrder.City = decoder["SHIPTOCITY"].ToString();
myOrder.State = decoder["SHIPTOSTATE"].ToString();
myOrder.PostalCode = decoder["SHIPTOZIP"].ToString();
myOrder.Country = decoder["SHIPTOCOUNTRYCODE"].ToString();
myOrder.Email = decoder["EMAIL"].ToString();
myOrder.Total = Convert.ToDecimal(decoder["AMT"].ToString());

// Verify total payment amount as set on CheckoutStart.aspx.


try
{
decimal paymentAmountOnCheckout =
Convert.ToDecimal(Session["payment_amt"].ToString());
decimal paymentAmoutFromPayPal =
Convert.ToDecimal(decoder["AMT"].ToString());
if (paymentAmountOnCheckout != paymentAmoutFromPayPal)
{
Response.Redirect("CheckoutError.aspx?" + "Desc=Amount%20total
%20mismatch.");
}
}
catch (Exception)
{
Response.Redirect("CheckoutError.aspx?" + "Desc=Amount%20total
%20mismatch.");
}

// Get DB context.
ProductContext _db = new ProductContext();

// Add order to DB.


_db.Orders.Add(myOrder);
_db.SaveChanges();

// Get the shopping cart items and process them.


using (WingtipToys.Logic.ShoppingCartActions usersShoppingCart = new
WingtipToys.Logic.ShoppingCartActions())
{
List<CartItem> myOrderList = usersShoppingCart.GetCartItems();

// Add OrderDetail information to the DB for each product purchased.

139
for (int i = 0; i < myOrderList.Count; i++)
{
// Create a new OrderDetail object.
var myOrderDetail = new OrderDetail();
myOrderDetail.OrderId = myOrder.OrderId;
myOrderDetail.Username = User.Identity.Name;
myOrderDetail.ProductId = myOrderList[i].ProductId;
myOrderDetail.Quantity = myOrderList[i].Quantity;
myOrderDetail.UnitPrice = myOrderList[i].Product.UnitPrice;

// Add OrderDetail to DB.


_db.OrderDetails.Add(myOrderDetail);
_db.SaveChanges();
}

// Set OrderId.
Session["currentOrderId"] = myOrder.OrderId;

// Display Order information.


List<Order> orderList = new List<Order>();
orderList.Add(myOrder);
ShipInfo.DataSource = orderList;
ShipInfo.DataBind();

// Display OrderDetails.
OrderItemList.DataSource = myOrderList;
OrderItemList.DataBind();
}
}
else
{
Response.Redirect("CheckoutError.aspx?" + retMsg);
}
}
}

protected void CheckoutConfirm_Click(object sender, EventArgs e)


{
Session["userCheckoutCompleted"] = "true";
Response.Redirect("~/Checkout/CheckoutComplete.aspx");
}
}

O DetailsView controle é usado para exibir os detalhes do pedido que retornaram do PayPal.
Também, o código acima salva os detalhes do pedido no banco de dados do Wingtip Toys como

140
um objeto OrderDetail . Quando o usuário clica no botão Ordem completa , eles são
redirecionados para a página CheckoutComplete.aspx .

Dica  

Na marcação da página CheckoutReview.aspx , observe que a tag <ItemStyle> é usada para alterar
o estilo dos itens dentro do controle DetailsView na parte inferior da página. Exibindo a página no
Modo de exibição Design (selecionando Design no canto inferior esquerdo do Visual Studio),
então selecionando o controle DetailsView , e selecionando a Marca inteligente (o ícone de seta
no canto superior direito do controle), você será capaz de ver o DetailsView Tasks.

Selecionando Editar campos, irá aparecer a caixa de diálogo campos . Nesta caixa de diálogo,
você pode facilmente controlar as propriedades visuais, como ItemStyle, do controle
DetailsView .

141
Concluir compra
Página de CheckoutComplete.aspx faz a compra do PayPal. Como mencionado acima, o usuário
deve clicar no botão Ordem completa antes que o aplicativo será navegar para a página
CheckoutComplete.aspx .

1. Na caixa pasta, abra a página chamada CheckoutComplete.aspx.

2. Substitua a marcação existente com o seguinte:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"


CodeBehind="CheckoutComplete.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutComplete"
%>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Checkout Complete</h1>
<p></p>
<h3>Payment Transaction ID:</h3> <asp:Label ID="TransactionId"
runat="server"></asp:Label>
<p></p>
<h3>Thank You!</h3>
<p></p>
<hr />
<asp:Button ID="Continue" runat="server" Text="Continue Shopping"
OnClick="Continue_Click" />

142
</asp:Content>

3. Abra a página code-behind, chamada CheckoutComplete.aspx.cs e substitua o código


existente com o seguinte:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;

namespace WingtipToys.Checkout
{
public partial class CheckoutComplete : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Verify user has completed the checkout process.
if ((string)Session["userCheckoutCompleted"] != "true")
{
Session["userCheckoutCompleted"] = string.Empty;
Response.Redirect("CheckoutError.aspx?" + "Desc=Unvalidated%20Checkout.");
}

NVPAPICaller payPalCaller = new NVPAPICaller();

string retMsg = "";


string token = "";
string finalPaymentAmount = "";
string PayerID = "";
NVPCodec decoder = new NVPCodec();

token = Session["token"].ToString();
PayerID = Session["payerId"].ToString();
finalPaymentAmount = Session["payment_amt"].ToString();

bool ret = payPalCaller.DoCheckoutPayment(finalPaymentAmount, token, PayerID,


ref decoder, ref retMsg);
if (ret)
{
// Retrieve PayPal confirmation value.
string PaymentConfirmation =
decoder["PAYMENTINFO_0_TRANSACTIONID"].ToString();

143
TransactionId.Text = PaymentConfirmation;

ProductContext _db = new ProductContext();


// Get the current order id.
int currentOrderId = -1;
if (Session["currentOrderId"] != string.Empty)
{
currentOrderId = Convert.ToInt32(Session["currentOrderID"]);
}
Order myCurrentOrder;
if (currentOrderId >= 0)
{
// Get the order based on order id.
myCurrentOrder = _db.Orders.Single(o => o.OrderId == currentOrderId);
// Update the order to reflect payment has been completed.
myCurrentOrder.PaymentTransactionId = PaymentConfirmation;
// Save to DB.
_db.SaveChanges();
}

// Clear shopping cart.


using (WingtipToys.Logic.ShoppingCartActions usersShoppingCart =
new WingtipToys.Logic.ShoppingCartActions())
{
usersShoppingCart.EmptyCart();
}

// Clear order id.


Session["currentOrderId"] = string.Empty;
}
else
{
Response.Redirect("CheckoutError.aspx?" + retMsg);
}
}
}

protected void Continue_Click(object sender, EventArgs e)


{
Response.Redirect("~/Default.aspx");
}
}

Quando a página CheckoutComplete.aspx é carregada, o método DoCheckoutPayment é chamado.


Como mencionado anteriormente, o método de DoCheckoutPayment completa a compra do
144
ambiente de teste de PayPal. Uma vez que o PayPal foi concluída a aquisição da ordem, a página
de CheckoutComplete.aspx exibe uma transação de pagamento ID ao comprador.

Segurar cancelar compra


Se o usuário decidir cancelar a compra, eles serão dirigidos para a página CheckoutCancel.aspx
onde eles vão ver que sua ordem foi cancelada.

1. Abra a página chamada CheckoutCancel.aspx na pasta check-out .

2. Substitua a marcação existente com o seguinte:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"


CodeBehind="CheckoutCancel.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutCancel" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Checkout Cancelled</h1>
<p></p>
<h3>Your purchase has been cancelled.</h3>

</asp:Content>

Manipular erros de compra


Erros durante o processo de compra serão tratados pela página CheckoutError.aspx . O code-
behind da página CheckoutStart.aspx , a página CheckoutReview.aspx e a página de
CheckoutComplete.aspx será cada redirecionamento para a página de CheckoutError.aspx se ocorrer
um erro.

1. Abra a página chamada CheckoutError.aspx na pasta check-out .

2. Substitua a marcação existente com o seguinte:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"


CodeBehind="CheckoutError.aspx.cs" Inherits="WingtipToys.Checkout.CheckoutError" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Checkout Error</h1>
<p></p>
<table id="ErrorTable">
<tr>
<td class="field"></td>
<td><%=Request.QueryString.Get("ErrorCode")%></td>
</tr>
<tr>
<td class="field"></td>
<td><%=Request.QueryString.Get("Desc")%></td>
</tr>
<tr>
<td class="field"></td>
<td><%=Request.QueryString.Get("Desc2")%></td>
</tr>
145
</table>
<p></p>

</asp:Content>

A página da CheckoutError.aspx é exibida com os detalhes do erro quando ocorre um erro durante
o processo de checkout.

Executando o aplicativo
Execute o aplicativo para ver como a aquisição de produtos. Note que você estará executando no
PayPal ambiente de teste. Nenhum dinheiro real está sendo trocado.

1. Verifique se todos os seus arquivos estão salvos no Visual Studio.

2. Abra um navegador da Web e navegue para https://developer.paypal.com.

3. Faça o login com sua conta de desenvolvedor do PayPal que você criou anteriormente
neste tutorial.
Para sandbox de desenvolvedores do PayPal, você precisa estar logado no
https://developer.paypal.com para testar o check-out expresso. Isso só se aplica à proteção do
PayPal, testes, não para viver ambiente do PayPal.

4. Em Visual Studio, pressione F5 para executar o aplicativo de exemplo do Wingtip Toys.


Depois que recria o banco de dados, o navegador irá abrir e mostrar a página Default. aspx .

5. Adicione três produtos diferentes para o carrinho de compras, selecionando a categoria do


produto, tais como "Carros" e, em seguida, clicando em Adicionar ao carrinho ao lado de cada
produto.
O carrinho de compras irá exibir o produto que você selecionou.

6. Clique no botão do PayPal para check-out.

146
7. Check-out vai exigir que você tem uma conta de usuário para o aplicativo de exemplo do
Wingtip Toys.

8. Clique no link do Google à direita da página para fazer login com uma conta de e-mail
existente do gmail.com.
Se você não tiver uma conta do gmail.com, você pode criar um para testes em www.gmail.com.
Você também pode usar uma conta local padrão clicando em "Register".

147
9. Inscreva-se com sua conta do gmail e senha.

148
10. Clique no botão Log in para registrar sua conta do gmail com seu nome de usuário do
aplicativo de amostra Wingtip Toys.

149
11. No site de teste do PayPal, adicionar o seu endereço de e-mail do comprador e a senha
que você criou anteriormente neste tutorial e, em seguida, clique no botão Log In .

12. Concordo para a política do PayPal e clique no botão concordo e continuar .


Note que esta página só é exibida a primeira vez que você usar essa conta de PayPal. Novamente,
note que esta é uma conta de teste, nenhum dinheiro real é trocado.

150
13. Revisar as informações de ordem sobre o PayPal página de revisão do ambiente de teste e
clique em continuar.

151
14. Na página CheckoutReview.aspx , verifique se o valor do pedido e ver o endereço de
entrega gerado. Em seguida, clique no botão Ordem completa .

15. A página da CheckoutComplete.aspx é exibida com uma ID de transação de pagamento.

152
Revendo o banco de dados
Revendo os dados atualizados do banco de dados do aplicativo de amostra Wingtip Toys depois
de executar o aplicativo, você pode ver que o aplicativo gravado com êxito a compra dos produtos.

Você pode inspecionar os dados contidos no arquivo de banco de dados Wingtiptoys.mdf usando a
janela de Banco de dados Explorer (janelaServer Explorer no Visual Studio), como você fez no
início desta série de tutoriais.

1. Feche a janela do navegador se ainda está em aberto.

2. No Visual Studio, selecione o ícone Mostrar todos os arquivos na parte superior do


Solution Explorer para permitir que você expanda a pasta App_Data .

3. Expanda a pasta App_Data .


Você pode precisar selecionar o ícone de Mostrar todos os arquivos para a pasta.

4. O arquivo de banco de dados de Wingtiptoys.mdf com o botão direito e selecione abrir.


Server Explorer é exibida.

5. Expanda a pasta tabelas .

6. Botão direito do mouse as ordens tabela e selecione Mostrar dados da tabela.


A tabela Orders é exibida.

7. Examine a coluna PaymentTransactionID para confirmar transações bem sucedidas.

153
8. Feche a janela da tabela de pedidos .

9. No Server Explorer, clique com botão direito a tabela DetalhesDoPedido e selecione


Mostrar dados da tabela.

10. Rever os valores OrderId e Username na tabela detalhes do pedido . Observe que esses
valores correspondem aos valores de OrderId e Username incluídos na tabela Orders .

11. Feche a janela da tabela detalhes do pedido .

12. Botão direito do mouse o arquivo de banco de dados do Wingtip Toys (Wingtiptoys.mdf) e
selecione a Conexão fechada.

13. Se você não vir a janela Solution Explorer , clique em Gerenciador de soluções na parte
inferior da janela do Server Explorer para mostrar o Solution Explorer novamente.

Resumo
Neste tutorial você adicionou a ordem e ordem detalhe esquemas para controlar a compra de
produtos. Você também integrado a funcionalidade do PayPal no aplicativo de amostra do Wingtip
Toys.

Recursos adicionais
Visão geral de configuração do ASP.NET
Criar um aplicativo ASP.NET MVC 5 com Facebook e Google OAuth2 e OpenID Sign-on (c#)

Resumo
Este tutorial contém código de exemplo. Tal código de exemplo é fornecido "como está" sem
garantia de qualquer tipo. Nesse sentido, a Microsoft não garante a exatidão, integridade ou
qualidade de código de exemplo. Você concorda em usar o código de exemplo em seu próprio
risco. Sob nenhuma circunstância a Microsoft será responsável de qualquer forma por qualquer
código de amostra, conteúdo, incluindo mas não limitado a, quaisquer erros ou omissões em
qualquer código de amostra, conteúdo, ou qualquer perda ou dano de qualquer tipo incorrido
154
como resultado do uso de qualquer código de amostra. Você é notificado por este meio e
concorda em indenizar, salvar e Microsoft de e contra todas e quaisquer perdas, sinistros de perda,
lesão ou danos de qualquer tipo, incluindo, sem limitação, aqueles resultantes ou decorrentes de
material que você postar, transmite, utilizar ou contar com incluindo, mas não limitado a, as
opiniões expressas nele.

155
08 - Associação e administração

Este tutorial mostra como atualizar o aplicativo de exemplo do Wingtip Toys para adicionar uma
função de administrador e usar a identidade do ASP.NET. Ele também mostra como implementar
uma página de administração do qual o administrador pode adicionar e remover produtos do site.

Identidade do ASP.NET é o sistema de associação usado para construir o aplicativo da web


ASP.NET e está disponível no ASP.NET 4.5. Identidade do ASP.NET é usada no modelo de projeto
Visual Studio 2013 Web Forms, bem como os modelos para ASP.NET MVC, ASP.NET Web APIe
aplicação de página ASP.NET Single. Também, especificamente, você pode instalar o sistema de
identidade do ASP.NET usando o NuGet, quando você começar com um aplicativo da Web vazio.
No entanto, nesta série tutorial você usa os Web Forms projeto modelo, que inclui o sistema de
identidade do ASP.NET. Identidade do ASP.NET facilita a integrar dados de perfil de usuário
específico com dados do aplicativo. Também, identidade do ASP.NET permite que você escolha o
modelo de persistência para perfis de usuário em seu aplicativo. Você pode armazenar os dados
em um banco de dados SQL Server ou outro armazenamento de dados, incluindo lojas de dados
NoSQL como tabelas de armazenamento do Windows Azure.

Este tutorial baseia-se no tutorial anterior, intitulado "Checkout e pagamento com PayPal" na série
tutorial Wingtip Toys.

O que você vai aprender:

 Como usar o código para adicionar uma função de administrador e um usuário para o
aplicativo.
 Como restringir o acesso para a pasta de administração e a página.

 Como fornecer navegação para o papel de administrador.

 Como usar a vinculação do modelo para preencher um controle DropDownList com


categorias de produto.
 Como fazer upload de um arquivo para o aplicativo da web usando o controle FileUpload .
 Como usar controles de validação para implementar a validação de entrada.

 Como adicionar e remover produtos do aplicativo.

Esses recursos estão incluídos no tutorial:


 Identidade do ASP.NET

 Configuração e autorização

 Vinculação do modelo
156
 Validação discreta

Web Forms do ASP.NET fornece recursos de associação. Usando o modelo padrão, você tem a
funcionalidade de associação interna que você pode usar imediatamente quando o aplicativo é
executado. Este tutorial mostra como usar a identidade do ASP.NET para adicionar uma função de
administrador e atribuir um usuário a esse papel. Você vai aprender como restringir o acesso para
a pasta de administração. Você adicionará uma página para a pasta de administração que permite
que um administrador para adicionar e remover produtos e para visualizar um produto depois que
ele foi adicionado.

Adicionar um administrador

Usando a identidade do ASP.NET, você pode adicionar uma função de administrador e atribuir um
usuário a esse papel usando código.

1. No Solution Explorer, clique com botão direito na pasta lógica e criar uma nova classe.

2. Nomeie a nova classe RoleActions.cs.

3. Modificar o código para que ele apareça da seguinte forma:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WingtipToys.Logic
{
internal class RoleActions
{
}

4. No Solution Explorer, abra o arquivo Global.asax.cs .

5. Abrir e modificar o Global.asax.cs ficheiro por adicionado o código destacado em amarelo,


para que ele apareça da seguinte forma:

using System;
using System.Collections.Generic;

157
using System.Linq;
using System.Web;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;
using System.Data.Entity;
using WingtipToys.Models;
using WingtipToys.Logic;

namespace WingtipToys
{
public class Global : HttpApplication
{

void Application_Start(object sender, EventArgs e)

{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

// Initialize the product database.

Database.SetInitializer(new ProductDatabaseInitializer());

// Create the administrator role and user.

RoleActions roleActions = new RoleActions();

roleActions.createAdmin();
}
}

6. Observe que createAdmin é sublinhada em vermelho. Clique duas vezes o código


createAdmin.
A letra "c", no método realçado irá ser sublinhada.

158
7. Em seguida, passe o mouse sobre a letra "c" para exibir a interface do usuário que permite
que você gere um esboço do método para o método createAdmin .

8. Clique o comprados intitulado:


Generate method stub for ‘createAdmin’ in “WingtipToys.Logic.RoleActions’

9. Abra o arquivo RoleActions.cs na pasta lógica .


O método createAdmin foi adicionado ao arquivo de classe.

10. Modifique o arquivo RoleActions.cs , removendo o NotImplementedeException e


adicionando o código destacado em amarelo, para que ele apareça da seguinte forma:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WingtipToys.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace WingtipToys.Logic
{
internal class RoleActions
{
internal void createAdmin()
{
// Access the application context and create result variables.

Models.ApplicationDbContext context = new ApplicationDbContext();

IdentityResult IdRoleResult;
IdentityResult IdUserResult;

// Create a RoleStore object by using the ApplicationDbContext object.


// The RoleStore is only allowed to contain IdentityRole objects.

159
var roleStore = new RoleStore<IdentityRole>(context);

// Create a RoleManager object that is only allowed to contain IdentityRole


objects.
// When creating the RoleManager object, you pass in (as a parameter) a new
RoleStore object.

var roleMgr = new RoleManager<IdentityRole>(roleStore);

// Then, you create the "Administrator" role if it doesn't already exist.

if (!roleMgr.RoleExists("Administrator"))

IdRoleResult = roleMgr.Create(new IdentityRole("Administrator"));


if (!IdRoleResult.Succeeded)

{
// Handle the error condition if there's a problem creating the
RoleManager object.
}
}

// Create a UserManager object based on the UserStore object and the


ApplicationDbContext
// object. Note that you can create new objects and use them as parameters in
// a single line of code, rather than using multiple lines of code, as you did
// for the RoleManager object.

var userMgr = new UserManager<ApplicationUser>(new


UserStore<ApplicationUser>(context));
var appUser = new ApplicationUser()

{
UserName = "Admin",
};
IdUserResult = userMgr.Create(appUser, "Pa$$word");

// If the new "Admin" user was successfully created,


// add the "Admin" user to the "Administrator" role.
160
if (IdUserResult.Succeeded)

{
IdUserResult = userMgr.AddToRole(appUser.Id, "Administrator");

if (!IdUserResult.Succeeded)

{
// Handle the error condition if there's a problem adding the user to the
role.
}
}

else

{
// Handle the error condition if there's a problem creating the new user.
}
}
}

O código acima, primeiro, estabelece um contexto de banco de dados para o banco de dados de
associação. O banco de dados de associação também é armazenado como um arquivo. MDF na
pasta App_Data . Você será capaz de ver os este banco de dados, uma vez que o primeiro usuário
assinou para esse aplicativo web.

Nota  

Se você deseja armazenar os dados de associação juntamente com os dados do produto, você
pode considerar usando a mesma DbContext usado para armazenar os dados de produto no
código acima.

A palavra-chave interno é um modificador de acesso para membros do tipo (por exemplo,


métodos ou Propriedades) e tipos (tais como classes). Tipos internos ou membros são acessíveis
somente dentro de arquivos contidos no mesmo assembly (. dll arquivo). Quando você compilar
seu aplicativo, um arquivo de assembly (. dll) é criado que contém o código que é executado
quando você executa o aplicativo.

Um objeto RoleStore , que fornece gerenciamento de função, é criado com base no contexto do
banco de dados.

Nota  

161
Observe que, quando o RoleStore objeto é criado ele usa um tipo genérico IdentityRole . Isto
significa que o RoleStore só é permitido para conter objetos IdentityRole . Também usando
Generics, recursos na memória são tratados melhor.

Em seguida, o objeto de RoleManager , é criado com base no objeto RoleStore que você acabou de
criar. o RoleManager objeto expõe papel relacionado API que pode ser usado para salvar
automaticamente as alterações para o RoleStore. O RoleManager só é permitido para conter
objetos de IdentityRole , porque o código usa o tipo genérico <IdentityRole> .

Você chamar o método RoleExists para determinar se a função de "Administrador" está presente
no banco de dados de associação. Se não for, você cria o papel.

Criar o objeto UserManager parece ser mais complicado do que o RoleManager controle, no
entanto, é quase o mesmo. Só está codificado em uma linha, em vez de vários. Aqui, o parâmetro
que você está passando é instanciar como um novo objeto contido no parêntese.

Em seguida, você criar o usuário "Admin", criando um novo objeto ApplicationUser . Então, se
você criar o usuário, com êxito, você adicionar o usuário à nova função.

Nota  

A manipulação de erro será atualizada durante o tutorial de "Manipulação de erro ASP.NET" no


final desta série de tutoriais.

Da próxima vez que o aplicativo for iniciado, o usuário chamado "Admin" será adicionado como a
função denominada "Administrador" do aplicativo. No final deste tutorial, você irá login como o
usuário "Admin" para exibir recursos adicionais que você será adicionado durante este tutorial.
Para API detalhes sobre a identidade do ASP.NET, consulte o Namespace Microsoft.AspNet.Identity.
Para obter detalhes adicionais sobre a inicialização do sistema de identidade do ASP.NET, consulte
o AspnetIdentitySample.

Restringir o acesso para a página de administração


O aplicativo de exemplo do Wingtip Toys permite que usuários anônimos e usuários registrados
ver e comprar produtos. No entanto, o administrador logados pode acessar uma página restrita
para adicionar e remover produtos.

Adicionar uma pasta de administração e a página


Em seguida, você irá criar uma pasta chamada Admin para o administrador do aplicativo de
exemplo Wingtip Toys.

1. Botão direito do mouse no nome do projeto (Wingtip Toys) no Solution Explorer e


selecione Add -> Nova pasta.

2. Nomeie a nova pasta Admin.

3. Botão direito do mouse a pasta Admin e em seguida selecione Add -> New Item.
Caixa de diálogo Add New Item é exibida.

4. Selecione o Visual c# -> grupo de modelos Web à esquerda. Médio na lista, selecione O
formulário da Web com a página mestra, nome AdminPage.aspx, e selecione Adicionar .
162
5. Selecione o arquivo site Master como a página mestra e em seguida, escolha OK.

Adicionar um arquivo Web. config


Adicionando um arquivo Web. config para a pasta Admin , você pode restringir o acesso à página
contida na pasta.

1. Botão direito do mouse a pasta Admin e selecione Add -> New Item.
Caixa de diálogo Add New Item é exibida.

2. Na lista de modelos de web do Visual translation from VPE for Csharp, selecione o Arquivo
de configuração Web lista média, aceite o nome padrão do Web. config,, e selecione Adicionar.

3. Substitua o conteúdo de XML existente no arquivo Web. config com o seguinte:

<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<allow roles="Administrator"/>
<deny users="*"/>
</authorization>
</system.web>

</configuration>

Salve o arquivo Web. config . O arquivo Web. config especifica que somente os administradores do
aplicativo podem acessar a página contida na pasta Admin .

Incluindo navegação do administrador


Para habilitar o administrador navegar para a secção de administração do aplicativo, você deve
adicionar um link para a página mestra . Apenas os usuários que pertencem à função de
administrador será capazes de ver o Admin link e acessar a seção de administração.

1. No Solution Explorer, localize e abra a página mestra .

2. Para criar um link para os administradores, adicione a marcação destacada em amarelo para
o seguinte elemento <ul> lista não ordenada para que a lista aparece da seguinte maneira:

<ul class="nav navbar-nav">


<li><a runat="server" id="adminLink" visible="false"
href="~/Admin/AdminPage">Admin</a></li>
<li><a runat="server" href="~/">Home</a></li>

163
<li><a runat="server" href="~/About">About</a></li>
<li><a runat="server" href="~/Contact">Contact</a></li>
<li><a runat="server" href="~/ProductList">Products</a></li>
<li><a runat="server" href="~/ShoppingCart"
ID="cartCount">&nbsp;</a></li>

</ul>

3. Abra o arquivo Site.Master.cs . Fazer o link Admin visível apenas para o usuário "Admin",
adicionando o código destacado em amarelo para o manipulador Page_Load . O manipulador
Page_Load aparecerá como segue:

protected void Page_Load(object sender, EventArgs e)


{
if (HttpContext.Current.User.IsInRole("Administrator"))
{
adminLink.Visible = true;
}

Quando a página for carregada, o código verifica se o usuário conectado tem o papel de
"Administrador". Se o usuário for um administrador, o span elemento, que contém o link para a
página de AdminPage.aspx (e, consequentemente, o link dentro do intervalo) é tornado visível.

Habilitando a administração de produtos


Até agora, você criou o papel de administrador e adicionei um usuário administrador, uma pasta
de administração e uma página de administração. Você definiu os direitos de acesso para a pasta
de administração e a página e adicionou um link de navegação para o administrador para o
aplicativo. Em seguida, você irá adicionar marcação para a página AdminPage.aspx e o código para
o arquivo de code-behind AdminPage.aspx.cs que permitirá ao administrador adicionar e remover
produtos.

1. No Solution Explorer, abra o arquivo AdminPage.aspx na pasta Admin .

2. Substitua a marcação existente com o seguinte:

164
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master"
AutoEventWireup="true" CodeBehind="AdminPage.aspx.cs"
Inherits="WingtipToys.Admin.AdminPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Administration</h1>
<hr />
<h3>Add Product:</h3>
<table>
<tr>
<td><asp:Label ID="LabelAddCategory"
runat="server">Category:</asp:Label></td>
<td>
<asp:DropDownList ID="DropDownAddCategory" runat="server"
ItemType="WingtipToys.Models.Category"
SelectMethod="GetCategories" DataTextField="CategoryName"
DataValueField="CategoryID" >
</asp:DropDownList>
</td>
</tr>
<tr>
<td><asp:Label ID="LabelAddName" runat="server">Name:</asp:Label></td>
<td>
<asp:TextBox ID="AddProductName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" Text="* Product name required." ControlToValidate="AddProductName"
SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td><asp:Label ID="LabelAddDescription"
runat="server">Description:</asp:Label></td>
<td>
<asp:TextBox ID="AddProductDescription"
runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2"
runat="server" Text="* Description required."
ControlToValidate="AddProductDescription" SetFocusOnError="true"
Display="Dynamic"></asp:RequiredFieldValidator>
</td>

165
</tr>
<tr>
<td><asp:Label ID="LabelAddPrice" runat="server">Price:</asp:Label></td>
<td>
<asp:TextBox ID="AddProductPrice" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator3"
runat="server" Text="* Price required." ControlToValidate="AddProductPrice"
SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1"
runat="server" Text="* Must be a valid price without $."
ControlToValidate="AddProductPrice" SetFocusOnError="True" Display="Dynamic"
ValidationExpression="^[0-9]*(\.)?[0-9]?[0-9]?$"></asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td><asp:Label ID="LabelAddImageFile" runat="server">Image
File:</asp:Label></td>
<td>
<asp:FileUpload ID="ProductImage" runat="server" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator4"
runat="server" Text="* Image path required." ControlToValidate="ProductImage"
SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
</td>
</tr>
</table>
<p></p>
<p></p>
<asp:Button ID="AddProductButton" runat="server" Text="Add Product"
OnClick="AddProductButton_Click" CausesValidation="true"/>
<asp:Label ID="LabelAddStatus" runat="server" Text=""></asp:Label>
<p></p>
<h3>Remove Product:</h3>
<table>
<tr>
<td><asp:Label ID="LabelRemoveProduct"
runat="server">Product:</asp:Label></td>
<td><asp:DropDownList ID="DropDownRemoveProduct" runat="server"
ItemType="WingtipToys.Models.Product"
SelectMethod="GetProducts" AppendDataBoundItems="true"

166
DataTextField="ProductName" DataValueField="ProductID" >
</asp:DropDownList>
</td>
</tr>
</table>
<p></p>
<asp:Button ID="RemoveProductButton" runat="server" Text="Remove Product"
OnClick="RemoveProductButton_Click" CausesValidation="false"/>
<asp:Label ID="LabelRemoveStatus" runat="server" Text=""></asp:Label>

</asp:Content>

3. Em seguida, abra o arquivo code-behind AdminPage.aspx.cs o AdminPage.aspx botão


direito do mouse e clicando em Exibir código.

4. Substitua o código existente no arquivo code-behind AdminPage.aspx.cs com o seguinte


código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;
using WingtipToys.Logic;

namespace WingtipToys.Admin
{
public partial class AdminPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

string productAction = Request.QueryString["ProductAction"];


if (productAction == "add")

{
LabelAddStatus.Text = "Product added!";

167
}

if (productAction == "remove")

{
LabelRemoveStatus.Text = "Product removed!";
}
}

protected void AddProductButton_Click(object sender, EventArgs e)


{

Boolean fileOK = false;

String path = Server.MapPath("~/Catalog/Images/");

if (ProductImage.HasFile)

{
String fileExtension =
System.IO.Path.GetExtension(ProductImage.FileName).ToLower();
String[] allowedExtensions = { ".gif", ".png", ".jpeg", ".jpg" };

for (int i = 0; i < allowedExtensions.Length; i++)

if (fileExtension == allowedExtensions[i])

fileOK = true;

}
}
}

if (fileOK)

try

{
168
// Save to Images folder.
ProductImage.PostedFile.SaveAs(path + ProductImage.FileName);
// Save to Images/Thumbs folder.
ProductImage.PostedFile.SaveAs(path + "Thumbs/" + ProductImage.FileName);
}

catch (Exception ex)

{
LabelAddStatus.Text = ex.Message;
}

// Add product data to DB.

AddProducts products = new AddProducts();


bool addSuccess = products.AddProduct(AddProductName.Text,
AddProductDescription.Text,

AddProductPrice.Text, DropDownAddCategory.SelectedValue,
ProductImage.FileName);

if (addSuccess)

{
// Reload the page.

string pageUrl = Request.Url.AbsoluteUri.Substring(0,


Request.Url.AbsoluteUri.Count() - Request.Url.Query.Count());

Response.Redirect(pageUrl + "?ProductAction=add");
}

else

{
LabelAddStatus.Text = "Unable to add new product to database.";
}
}

else

{
LabelAddStatus.Text = "Unable to accept file type.";
}

169
}

public IQueryable GetCategories()


{

var _db = new WingtipToys.Models.ProductContext();

IQueryable query = _db.Categories;

return query;

public IQueryable GetProducts()


{

var _db = new WingtipToys.Models.ProductContext();

IQueryable query = _db.Products;

return query;

protected void RemoveProductButton_Click(object sender, EventArgs e)


{

using (var _db = new WingtipToys.Models.ProductContext())

int productId = Convert.ToInt16(DropDownRemoveProduct.SelectedValue);


var myItem = (from c in _db.Products where c.ProductID == productId select
c).FirstOrDefault();
if (myItem != null)

{
_db.Products.Remove(myItem);
_db.SaveChanges();

// Reload the page.

string pageUrl = Request.Url.AbsoluteUri.Substring(0,


Request.Url.AbsoluteUri.Count() - Request.Url.Query.Count());

170
Response.Redirect(pageUrl + "?ProductAction=remove");
}

else

{
LabelRemoveStatus.Text = "Unable to locate product.";
}
}
}
}

No código que você digitou para o arquivo de code-behind AdminPage.aspx.cs , uma classe
chamada AddProducts faz o trabalho real de adicionar produtos no banco de dados. Essa classe
ainda não existe, então você irá criá-lo agora.

1. No Solution Explorer, clique com botão direito na pasta lógica e em seguida selecione
Add -> New Item.
Caixa de diálogo Add New Item é exibida.

2. Selecione o Visual c# -> grupo de modelos de código do lado esquerdo. Em seguida,


selecione a classe do meio lista e o nome AddProducts.cs.
O novo arquivo de classe é exibido.

3. Substitua o código existente com o seguinte:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WingtipToys.Models;

namespace WingtipToys.Logic
{
public class AddProducts
{
public bool AddProduct(string ProductName, string ProductDesc, string ProductPrice,
string ProductCategory, string ProductImagePath)
{

171
var myProduct = new Product();

myProduct.ProductName = ProductName;
myProduct.Description = ProductDesc;
myProduct.UnitPrice = Convert.ToDouble(ProductPrice);
myProduct.ImagePath = ProductImagePath;
myProduct.CategoryID = Convert.ToInt32(ProductCategory);

using (ProductContext _db = new ProductContext())

{
// Add product to DB.
_db.Products.Add(myProduct);
_db.SaveChanges();
}
// Success.

return true;

}
}

A página de AdminPage.aspx permite ao administrador adicionar e remover produtos. Quando é


adicionado um novo produto, os detalhes sobre o produto são validados e, em seguida, entrou no
banco de dados. O novo produto está imediatamente disponível para todos os usuários do
aplicativo da web.

Validação discreta
Os detalhes do produto que o usuário fornece na página AdminPage.aspx são validados usando
controles de validação (RequiredFieldValidator e RegularExpressionValidator). Esses controles
automaticamente usam a validação de discreta. Discreta validação permite que os controles de
validação usar JavaScript para lógica de validação do lado do cliente, o que significa que a página
não requer uma viagem para o servidor para ser validado. Por padrão, validação discreta está
incluída no arquivo Web. config baseado a definição de configuração a seguir:

<add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" />

Expressões regulares

172
O preço do produto na página AdminPage.aspx é validado usando um controle
RegularExpressionValidator . Este controle valida se o valor do Controlarar de entrada associado
(a caixa de texto "AddProductPrice") coincide com o padrão de expressão regular. Uma expressão
regular é uma notação de correspondência de padrões que permite que você rapidamente
encontrar e combinar padrões de caracteres específicos. O controle RegularExpressionValidator
inclui uma propriedade chamada ValidationExpression que contém a expressão regular usada
para validar a entrada do preço, como mostrado abaixo:

<asp:RegularExpressionValidator
ID="RegularExpressionValidator1" runat="server"
Text="* Must be a valid price without $." ControlToValidate="AddProductPrice"
SetFocusOnError="True" Display="Dynamic"
ValidationExpression="^[0-9]*(\.)?[0-9]?[0-9]?$">

</asp:RegularExpressionValidator>

Controle fileUpload
Além dos controles de entrada e validação, você adicionou o FileUpload controle para a página
AdminPage.aspx . Esse controle fornece a capacidade de fazer upload de arquivos. Neste caso, você
só permite que arquivos de imagem a ser carregada. No arquivo code-behind (AdminPage.aspx.cs),
quando o AddProductButton for clicado, o código verifica a propriedade HasFile do controle
FileUpload . Se o controle tem um arquivo e o tipo de arquivo (com base na extensão de arquivo)
é permitido, a imagem é salva a pasta de imagens e a pasta de Imagens/Thumbs do aplicativo.

Vinculação do modelo
No início desta série de tutoriais você usou a vinculação do modelo para preencher um controle
ListView , um FormsView controle, um controle GridView e um controle DetailView . Neste
tutorial, você pode usar vinculação do modelo para preencher um controle DropDownList com
uma lista de categorias de produtos.

A marcação que você adicionou o arquivo AdminPage.aspx contém um DropDownList controle


chamado DropDownAddCategory:

<asp:DropDownList ID="DropDownAddCategory" runat="server"

ItemType="WingtipToys.Models.Category"
SelectMethod="GetCategories" DataTextField="CategoryName"
DataValueField="CategoryID" >

1. </asp:DropDownList>

173
Você pode usar vinculação do modelo para preencher o DropDownList por configuração o
atributo ItemType e o atributo SelectMethod . O atributo ItemType especifica que você use o tipo
de WingtipToys.Models.Category ao preencher o controle. Você definiu este tipo no início desta
série tutorial Criando a classe de Category (mostrado abaixo). A classe de Category está na pasta
de modelos dentro do arquivo Category.cs .

public class Category


{

[ScaffoldColumn(false)]
public int CategoryID { get; set; }

[Required, StringLength(100), Display(Name = "Name")]


public string CategoryName { get; set; }

[Display(Name = "Product Description")]


public string Description { get; set; }

public virtual ICollection<Product> Products { get; set; }

O atributo SelectMethod do controle DropDownList especifica que você use o método


GetCategories (mostrado abaixo) que é incluído no arquivo code-behind (AdminPage.aspx.cs).

public IQueryable GetCategories()


{
var _db = new WingtipToys.Models.ProductContext();
IQueryable query = _db.Categories;
return query;

Este método especifica que um IQueryable interface é usado para avaliar uma consulta contra um
tipo de Category . O valor retornado é usado para preencher o DropDownList na marcação da
página (AdminPage.aspx).

174
O texto exibido para cada item na lista é especificado, definindo o atributo DataTextField . O
atributo DataTextField usa o CategoryName da classe Category (mostrado acima) para exibir cada
categoria no controle DropDownList . O real valor que é passado quando um item é selecionado
no controle DropDownList é baseado no atributo DataValueField . O DataValueField atributo
está definido como o CategoryID como definir a classe de Category (mostrado acima).

Como o aplicativo funcionará


Quando o administrador navega para a página pela primeira vez, o controle DropDownList
DropDownAddCategory é preenchido conforme descrito acima. O controle DropDownList
DropDownRemoveProduct também é preenchido com produtos usando a mesma abordagem. O
administrador seleciona o tipo de categoria e adiciona detalhes do produto (nome, Descrição,
preçoe Arquivo de imagem). Quando o administrador clica no botão de Adicionar o produto , o
manipulador de evento AddProductButton_Click é disparado. O manipulador de eventos
AddProductButton_Click localizado no arquivo code-behind (AdminPage.aspx.cs) verifica o arquivo
de imagem para verificar se combina com os tipos de arquivos permitidos (. gif, . jpg, . jpegou .
png). Em seguida, o arquivo de imagem é salvo em uma pasta do aplicativo de exemplo Wingtip
Toys. Em seguida, o novo produto é adicionado ao banco de dados. Para realizar a adição de um
novo produto, uma nova instância da classe AddProducts é criada e chamada produtos. A classe
AddProducts tem um método chamado AddProduct, e o objeto produtos chama esse método para
adicionar produtos no banco de dados.

// Add product data to DB.


AddProducts products = new AddProducts();
bool addSuccess = products.AddProduct(AddProductName.Text,
AddProductDescription.Text,

AddProductPrice.Text, DropDownAddCategory.SelectedValue,
ProductImage.FileName);

Se com êxito, o código adiciona o novo produto no banco de dados, a página será recarregada
com o valor de seqüência de caracteres de consulta ProductAction=add.

Response.Redirect(pageUrl + "?ProductAction=add");

Quando recarrega a página, a seqüência de caracteres de consulta está incluída na URL.


Recarregando a página, o administrador pode ver imediatamente as atualizações no
DropDownList controles na página AdminPage.aspx . Também, incluindo a seqüência de
caracteres de consulta com a URL, a página pode exibir uma mensagem de sucesso para o
administrador.

Quando recarrega a página de AdminPage.aspx , o evento Page_Load é chamado.

protected void Page_Load(object sender, EventArgs e)


{

175
string productAction = Request.QueryString["ProductAction"];
if (productAction == "add")
{

LabelAddStatus.Text = "Product added!";

}
if (productAction == "remove")
{

LabelRemoveStatus.Text = "Product removed!";

O manipulador de eventos Page_Load verifica o valor de seqüência de caracteres de consulta e


determina se deve mostrar uma mensagem de sucesso.

Executando o aplicativo
Você pode executar o aplicativo agora para ver como você pode adicionar, excluir e atualizar itens
no carrinho de compras. O total de carrinho compras irá refletir o custo total de todos os itens no
carrinho de compras.

1. No Solution Explorer, pressione F5 para executar o aplicativo de exemplo do Wingtip Toys.


O navegador abre e mostra a página Default. aspx .

2. Clique no link efetuar login no topo da página.

176
A página login. aspx é exibida.

3. Use o seguinte nome de usuário de administrador e senha:


Nome de usuário: Admin
Senha: Pa$ $word

4. Clique no botão Log in na parte inferior da página.

5. Na parte superior da próxima página, selecione o link Admin para navegar para a página
AdminPage.aspx .

177
6. Para testar a validação de entrada, clique no botão Adicionar produto sem adição de
quaisquer detalhes do produto.

Observe que são exibidas as mensagens de campo obrigatório.

7. Adicione os detalhes de um novo produto e, em seguida, clique no botão de Adicionar o


produto .

178
8. Selecione produtos do menu de navegação superior para ver o novo produto que você
adicionou.

9. Clique no link de Admin para retornar para a página de administração.

179
10. Na seção Remover produto da página, selecione o novo produto que você adicionou no
DropDownListBox.

11. Clique no botão Remover produto para remover o novo produto da aplicação.

12. Selecione os produtos no menu de navegação superior para confirmar que o produto foi
removido.

13. Clique em fazer logoff para existir modo de administração.


Observe que o painel de navegação superior não mostra mais o item de menu de Admin .

Resumo
Neste tutorial, você acrescentou uma função de administrador e um usuário administrativo, acesso
restrito para a pasta de administração e a página e fornecido a navegação para o papel de
administrador. Você usou a vinculação do modelo para preencher um controle DropDownList
com os dados. Você implementou o controle FileUpload e controles de validação. Além disso,
você aprendeu como adicionar e remover produtos de um banco de dados. No próximo tutorial,
você aprenderá como implementar roteamento do ASP.NET.

180
09 - Roteamento de URL

Neste tutorial, você modificará o aplicativo de exemplo do Wingtip Toys para oferecer suporte a
roteamento de URL. Roteamento permite que seu aplicativo da web usar URLs que são melhor
suportados pelos motores de busca, amigável e mais fácil de lembrar. Este tutorial baseia-se no
tutorial anterior "Associação e administração" e faz parte da série tutorial Wingtip Toys.

O que você vai aprender:

 Como registrar rotas para um aplicativo ASP.NET Web Forms.

 Como adicionar rotas para uma página da web.

 Como selecionar dados de um banco de dados para oferecer suporte a rotas.

Visão geral de roteamento do ASP.NET


Roteamento de URL permite que você configure um aplicativo aceitar solicitar URLs que não são
mapeadas para arquivos físicos. Um URL de solicitação é simplesmente a URL que o usuário entra
no seu navegador para encontrar uma página no seu site. Você usa o roteamento para definir URLs
que são semanticamente significativos para os usuários e que pode ajudar com a otimização de
motor de busca (SEO).

Por padrão, o modelo de formulários da Web inclui URLs amigáveis do ASP.NET. Grande parte do
trabalho básico de roteamento irão ser implementado usando URLs amigáveis. No entanto, neste
tutorial, você irá adicionar capacidades de roteamento personalizadas.

Antes de personalizar o roteamento de URL, o aplicativo de exemplo do Wingtip Toys pode


vincular a um produto usando a seguinte URL:

http://localhost:1234/ProductDetails.aspx?ProductID=2

Personalizando o roteamento de URL, o aplicativo de exemplo do Wingtip Toys vai ligar para o
mesmo produto utilizando uma maneira mais fácil de ler a URL:

http://localhost:1234/Product/Convertible%20Car

Rotas

Uma rota é um padrão de URL que é mapeado para um manipulador. O manipulador pode ser um
arquivo físico, como um arquivo. aspx em um aplicativo de formulários da Web. Um manipulador
também pode ser uma classe que processa a solicitação. Para definir uma rota, você deve criar uma

181
instância da classe Route especificando o padrão de URL, o manipulador e, opcionalmente, um
nome para a rota.

Você pode adicionar a rota para o aplicativo, adicionando o objeto de Route para a propriedade de
Routes estática da classe RouteTable . A propriedade de rotas é RouteCollection .

Padrões de URL

Um padrão de URL pode conter valores literais e variáveis espaços reservados (referidos como
parâmetros de URL). Os literais e espaços reservados estão localizados em segmentos da URL que
são delimitados por um caractere de barra (/).

Quando é feita uma solicitação para seu aplicativo da web, o URL é analisada em segmentos e
espaços reservados, e os valores de variáveis são fornecidos para o manipulador de solicitações.
Este processo é semelhante à maneira como os dados em uma seqüência de caracteres de consulta
são analisados e passados para o manipulador de solicitações. Em ambos os casos, informações de
variável são incluídas na URL e passadas para o manipulador na forma de pares chave-valor. Para
seqüências de caracteres de consulta, tanto as chaves e os valores estão na URL. Para rotas, as
chaves são os nomes de placeholder definidos no padrão de URL, e apenas os valores são na URL.

Em um padrão de URL, você definir espaços reservados, colocando-os entre chaves ( { e } ). Você
pode definir mais de um espaço reservado em um segmento, mas os espaços reservados devem
ser separados por um valor literal. Por exemplo, {language}-{country}/{action} é um padrão de
rota válida. No entanto, {language}{country}/{action} não é um padrão válido, porque não há
nenhum valor literal ou delimitador entre os espaços reservados. Portanto, roteamento não pode
determinar onde separar o valor para o espaço reservado de linguagem de valor para o espaço
reservado do país.

Mapeamento e registro de rotas

Antes que você pode incluir rotas para páginas do aplicativo de exemplo Wingtip Toys, você deve
registrar as rotas quando o aplicativo for iniciado. Para registrar as rotas, você modificará o
manipulador de evento Application_Start .

1. No Solution Explorer do Visual Studio, localize e abra o arquivo Global.asax.cs .

2. Adicione o código realçado em amarelo ao arquivo Global.asax.cs como segue:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Optimization;

182
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;
using System.Data.Entity;
using WingtipToys.Models;
using WingtipToys.Logic;

namespace WingtipToys
{
public class Global : HttpApplication
{

void Application_Start(object sender, EventArgs e)

{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

// Initialize the product database.

Database.SetInitializer(new ProductDatabaseInitializer());

// Create administrator role and user.

RoleActions roleActions = new RoleActions();

roleActions.createAdmin();

// Add Routes.
RegisterCustomRoutes(RouteTable.Routes);
}

void RegisterCustomRoutes(RouteCollection routes)

{
routes.MapPageRoute(
"ProductsByCategoryRoute",
"Category/{categoryName}",
"~/ProductList.aspx"
183
);
routes.MapPageRoute(
"ProductByNameRoute",
"Product/{productName}",
"~/ProductDetails.aspx"
);
}
}

Quando começa a aplicação da amostra a Wingtip Toys, ele chama o manipulador de evento
Application_Start . No final deste manipulador de evento, o método RegisterCustomRoutes é
chamado. O método RegisterCustomRoutes adiciona cada rota, chamando o método MapPageRoute
do objeto RouteCollection . Rotas são definidas usando um nome de rota, uma URL de rota e um
URL de física.

O primeiro parâmetro ("ProductsByCategoryRoute") é o nome de rota. É usado para chamar a rota


quando necessário. O segundo parâmetro ("Category/{categoryName}") define a substituição
amigável URL que pode ser dinâmico com base no código. Você usar esta rota... quando você está
preenchendo um controle de dados com links que são geradas com base nos dados. Uma rota é
mostrada como segue:

routes.MapPageRoute(
"ProductsByCategoryRoute",
"Category/{categoryName}",
"~/ProductList.aspx"

);

O segundo parâmetro da rota inclui um valor dinâmico especificado por chaves ( { }). Neste caso, o
categoryName é uma variável que será usada para determinar o caminho de roteamento adequado.

Opcional  

Você pode encontrá-lo mais fácil de gerenciar o seu código, movendo o método
RegisterCustomRoutes para uma classe separada. Na pasta lógica , crie uma classe separada de
RouteActions . Mudar o método de RegisterCustomRoutes acima do arquivo Global.asax.cs para a
nova classe RoutesActions . Use a classe RoleActions e o método de createAdmin como um
exemplo de como chamar o método RegisterCustomRoutes do arquivo Global.asax.cs .

184
Você também deve ter notado o método RegisterRoutes chamar usando o objeto de RouteConfig
no início do manipulador de evento Application_Start . Essa chamada é feita para implementar
roteamento padrão. Foi incluído como código padrão quando você criou o aplicativo usando o
modelo de formulários da Web do Visual Studio.

Recuperando e usando dados de rota

Como mencionado acima, rotas podem ser definidas. O código que você adicionou ao
manipulador de evento Application_Start no arquivo Global.asax.cs carrega as rotas definíveis.

Rotas de configuração

Rotas exigem que você adicionar código adicional. Neste tutorial, você usará a vinculação do
modelo para recuperar um objeto RouteValueDictionary que é usado ao gerar as rotas usando
dados de um controle de dados. RouteValueDictionary irá conter uma lista de nomes de produtos
que pertencem a uma categoria específica de produtos. É criado um link para cada produto com
base nos dados e rota.

Habilitar rotas para categorias e produtos

Em seguida, você vai atualizar o aplicativo para usar o ProductsByCategoryRoute para determinar a
rota correta para incluir para cada link de categoria de produto. Você também vai atualizar a
página ProductList para incluir um link encaminhado para cada produto. Os links serão exibidos
como eram antes da alteração, porém os links agora irá usar o roteamento de URL.

1. No Solution Explorer, abra a página mestra se ele não já estiver aberto.

2. Atualize o ListView controle chamado "categoryList" com as alterações destacadas em


amarelo, então a marcação aparece da seguinte maneira:

<asp:ListView ID="categoryList"
ItemType="WingtipToys.Models.Category"
runat="server"
SelectMethod="GetCategories" >
<ItemTemplate>

<b style="font-size: large; font-style: normal">

<a href="<%#: GetRouteUrl("ProductsByCategoryRoute", new {categoryName =


Item.CategoryName}) %>">
<%#: Item.CategoryName %>
</a>
</b>

185
</ItemTemplate>
<ItemSeparatorTemplate> | </ItemSeparatorTemplate>

</asp:ListView>

3. No Solution Explorer, abra a página de ProductList .

4. Atualize o ItemTemplate elemento da página ProductList com as atualizações, destacadas


em amarelo, então a marcação aparece da seguinte maneira:

<ItemTemplate>
<td runat="server">
<table>
<tr>
<td>
<a href="<%#: GetRouteUrl("ProductByNameRoute", new {productName =
Item.ProductName}) %>">
<image src='/Catalog/Images/Thumbs/<%#:Item.ImagePath%>'
width="100" height="75" border="1" />
</a>
</td>
</tr>
<tr>
<td>
<a href="<%#: GetRouteUrl("ProductByNameRoute", new {productName =
Item.ProductName}) %>">
<%#:Item.ProductName%>
</a>
<br />
<span>
<b>Price: </b><%#:String.Format("{0:c}", Item.UnitPrice)%>
</span>
<br />
<a href="/AddToCart.aspx?productID=<%#:Item.ProductID %>">
<span class="ProductListItem">
<b>Add To Cart<b>
</span>
</a>

186
</td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table>
</p>
</td>

</ItemTemplate>

5. Abra o código-behind de ProductList.aspx.cs e adicionar o namespace a seguir como


destacado em amarelo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Models;
using System.Web.ModelBinding;
using System.Web.Routing;

6. Substitua o método GetProducts de code-behind (ProductList.aspx.cs) com o seguinte


código:

public IQueryable<Product> GetProducts(

[QueryString("id")] int? categoryId,


[RouteData] string categoryName)

{
var _db = new WingtipToys.Models.ProductContext();
IQueryable<Product> query = _db.Products;

if (categoryId.HasValue && categoryId > 0)


{

187
query = query.Where(p => p.CategoryID == categoryId);
}

if (!String.IsNullOrEmpty(categoryName))
{
query = query.Where(p =>
String.Compare(p.Category.CategoryName,
categoryName) == 0);
}
return query;

Adicione código para detalhes do produto

Agora, atualize o código-behind (ProductDetails.aspx.cs) para a página ProductDetails.aspx para


usar dados de rota. Observe que o novo método GetProduct também aceita um valor de seqüência
de caracteres de consulta para o caso onde o usuário tem um link marcado que usa a URL não-
amigável, não roteado mais velha.

1. Substitua o método GetProduct de code-behind (ProductDetails.aspx.cs) com o seguinte


código:

public IQueryable<Product> GetProduct(

[QueryString("ProductID")] int? productId,


[RouteData] string productName)

{
var _db = new WingtipToys.Models.ProductContext();
IQueryable<Product> query = _db.Products;
if (productId.HasValue && productId > 0)
{
query = query.Where(p => p.ProductID == productId);
}
else if (!String.IsNullOrEmpty(productName))
{
query = query.Where(p =>
String.Compare(p.ProductName, productName) == 0);

188
}
else
{
query = null;
}
return query;

Executando o aplicativo

Você pode executar o aplicativo agora para ver as rotas atualizadas.

1. Pressione F5 para executar o aplicativo de exemplo do Wingtip Toys.


O navegador abre e mostra a página Default. aspx .

2. Clique no link de produtos no topo da página.


Todos os produtos são exibidos na página ProductList . A URL a seguir (usando seu número de
porta) é exibida para o navegador:
http://localhost:1234/lista de produtos

3. Em seguida, clique no link de categoria de carros perto do topo da página.


Somente carros são exibidos na página ProductList . A URL a seguir (usando seu número de porta)
é exibida para o navegador:
http://localhost:1234/categoria/carros

4. Clique no link que contém o nome do primeiro carro listado na página ("Carro
conversível") para exibir os detalhes do produto.
A URL a seguir (usando seu número de porta) é exibida para o navegador:
http://localhost:1234/Product/Convertible%20Car

5. Em seguida, insira a seguinte URL não roteado (usando seu número da porta) no
navegador:
http://localhost:1234/ProductDetails.aspx?ProductID=2
O código ainda reconhece uma URL que inclui uma seqüência de caracteres de consulta, para o
caso em que um usuário tem um link marcado.

Resumo
Neste tutorial, você adicionou rotas para categorias e produtos. Você aprendeu como rotas podem
ser integradas com os controles de dados que usam vinculação do modelo. No próximo tutorial,
você irá implementar manipulação de erro global.

189
190
10 - Tratamento de erros do ASP.NET

Neste tutorial, você modificará o aplicativo de exemplo do Wingtip Toys para incluir a manipulação
de erro e log de erro. Tratamento de erros permite que o aplicativo graciosamente manipular erros
e exibir mensagens de erro em conformidade. Log de erro permitirá que você a localizar e corrigir
erros que ocorreram. Este tutorial baseia-se no tutorial anterior "Roteamento de URL" e faz parte
da série tutorial Wingtip Toys.

O que você vai aprender:


 Como adicionar o erro global de manipulação para a configuração do aplicativo.

 Como adicionar no aplicativo, página e níveis de código de tratamento de erros.

 Como log de erros para revisão posterior.

 Como exibir mensagens de erro que não comprometer a segurança.

 Como implementar o log de erro de módulos de log de erro e manipuladores (ELMAH).

Visão geral
Aplicativos ASP.NET devem ser capazes de manipular erros que ocorrem durante a execução de
uma maneira consistente. O ASP.NET usa o common language runtime (CLR), que fornece uma
maneira de notificar aplicativos de erros de maneira uniforme. Quando ocorre um erro, uma
exceção é Descartado. Uma exceção é qualquer erro, condição ou comportamento inesperado que
encontra um aplicativo.

No .NET Framework, uma exceção é um objeto que herda da classe System.Exception . Uma
exceção é lançada a partir de uma área de código onde ocorreu um problema. A exceção é
passada para cima na pilha de chamadas para um lugar onde o aplicativo fornece o código para
manipular a exceção. Se o aplicativo não manipula a exceção, o navegador é forçado para exibir os
detalhes do erro.

Como prática recomendada, manipular erros a nível de código em Try/Catch/Finally blocos


dentro do seu código. Tente colocar os blocos para que o usuário possa corrigir os problemas no
contexto em que ocorrem. Se os blocos de tratamento de erros estão muito longe de onde o erro
ocorreu, torna-se mais difícil fornecer aos usuários as informações necessárias corrigir o problema.

Classe de exceção
A classe de exceção é a classe base da qual exceções herdam. A maioria dos objetos de exceção
são instâncias de uma classe derivada da classe de exceção, como a classe
ArgumentNullException , IndexOutOfRangeException classe ou classe SystemException . A classe

191
de exceção tem propriedades, como a propriedade StackTrace , a InnerException Propriedade e a
propriedade de Message , que fornecem informações específicas sobre o erro que ocorreu.

Hierarquia de herança de exceção


O tempo de execução tem um conjunto básico de exceções derivar da classe SystemException que
o runtime lança uma exceção é encontrada. A maioria das classes que herdam a classe de exceção,
tais como a classe IndexOutOfRangeException e classe ArgumentNullException , não implementar
membros adicionais. Portanto, a informação mais importante para uma exceção pode ser
encontrada na hierarquia de exceções, o nome da exceção e as informações contidas na exceção.

Hierarquia de manipulação de exceção

Em um aplicativo de formulários da Web ASP.NET, exceções podem ser tratadas com base em uma
hierarquia de tratamento específico. Uma exceção pode ser tratada nos seguintes níveis:

 Nível de aplicativo

 Nível de página

 Código nível

Quando um aplicativo manipula exceções, informações adicionais sobre a exceção que é herdada
da classe Exception muitas vezes podem ser recuperadas e exibidas para o usuário. Além de
aplicação, página e nível de código, você também pode tratar exceções no nível de módulo HTTP e
usando um manipulador personalizado de IIS.

Manipulação de erro de nível aplicação


Modificando a configuração do seu aplicativo ou adicionando um manipulador Application_Error
no arquivo global. asax do seu aplicativo, você pode manipular erros padrão no nível do aplicativo.

Você pode manipular erros padrão e erros HTTP, adicionando uma seção customErrors no arquivo
Web. config . A seção customErrors permite que você especifique uma página padrão que os
usuários serão redirecionados para quando ocorre um erro. Ele também permite que você
especifique as páginas individuais para erros de código de status específico.

<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="ErrorPage.aspx?handler=customErrors
%20section%20-%20Web.config">
<error statusCode="404" redirect="ErrorPage.aspx?msg=404&amp;handler=customErrors
%20section%20-%20Web.config"/>
</customErrors>
</system.web>

</configuration>

Infelizmente, quando você usar a configuração para redirecionar o usuário para uma página
diferente, você não tem os detalhes do erro que ocorreu.
192
No entanto, você pode interceptar erros que ocorrem em qualquer lugar em seu aplicativo
adicionando código para o manipulador Application_Error no arquivo global. asax .

void Application_Error(object sender, EventArgs e)


{
Exception exc = Server.GetLastError();

if (exc is HttpUnhandledException)
{
// Pass the error on to the error page.
Server.Transfer("ErrorPage.aspx?handler=Application_Error%20-%20Global.asax",
true);
}

Manipulação de eventos de erro de nível de página

Um manipulador de nível de página retorna o usuário para a página onde o erro ocorreu, mas
porque instâncias de controles não são mantidas, já não haverá nada na página. Para fornecer os
detalhes de erro para o usuário do aplicativo, você deve escrever especificamente os detalhes do
erro para a página.

Você normalmente usaria um manipulador de erro de nível de página para registrar erros não
tratados ou para levar o usuário para uma página que pode exibir informações úteis.

Este exemplo de código mostra um manipulador para o evento de erro em uma página da Web do
ASP.NET. Esse manipulador captura todas as exceções que não são manipuladas já dentro
try/catch blocos página.

private void Page_Error(object sender, EventArgs e)


{
Exception exc = Server.GetLastError();

// Handle specific exception.


if (exc is HttpUnhandledException)
{
ErrorMsgTextBox.Text = "An error occurred on this page. Please verify
your " +
"information to resolve the issue."
}
// Clear the error from the server.
Server.ClearError();
}

Depois que você lidar com um erro, você deve apagá-lo chamando o método ClearError do
objeto Server (classeHttpServerUtility ), caso contrário, você verá um erro que ocorreu
anteriormente.
193
Código manipulação de erro de nível

A instrução try-catch consiste de um bloco try, seguido por um ou mais catch cláusulas que
especificam os manipuladores para diferentes exceções. Quando uma exceção é Descartado, o
common language runtime (CLR) procura a instrução catch que manipula a exceção. Se o método
atualmente em execução não contiver um bloco catch, o CLR Olha para o método que chamou o
método atual e assim por diante, até a pilha de chamada. Não se for encontrado nenhum bloco
catch, o CLR exibe uma mensagem de exceção sem tratamento para o usuário e interrompe a
execução do programa.

O exemplo de código a seguir mostra uma maneira comum de usar try/catch/finally para
manipular erros.

try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (FileNotFoundException e)
{
Server.Transfer("NoFileErrorPage.aspx", true);
}
catch (System.IO.IOException e)
{
Server.Transfer("IOErrorPage.aspx", true);
}

finally
{
if (file != null)
{
file.Close();
}
}

No código acima, o bloco try contém o código que precisa ser protegido contra uma possível
exceção. O bloco é executado até que uma exceção é Descartado ou o bloco é concluído com
êxito. Se uma exceção IOException ou uma FileNotFoundException exceção ocorre, a execução é
transferida para uma página diferente. Em seguida, o código contido no finally bloco é executado,
se ocorreu um erro ou não.

Adicionando suporte de log de erro


Antes de adicionar o erro de manipulação para o aplicativo de exemplo do Wingtip Toys, você irá
adicionar suporte de log de erro, adicionando uma classe ExceptionUtility para a pasta de
lógica . Ao fazer isso, cada vez que o aplicativo lida com um erro, os detalhes do erro serão
adicionados para o arquivo de log de erro.

194
1. Botão direito do mouse a pasta lógica e em seguida selecione Add -> New Item.
Caixa de diálogo Add New Item é exibida.

2. Selecione o Visual c# -> grupo de modelos de código do lado esquerdo. Em seguida,


selecione a classe do meio lista e o nome ExceptionUtility.cs.

3. Escolha Adicionar. O novo arquivo de classe é exibido.

4. Substitua o código existente com o seguinte:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;

namespace WingtipToys.Logic
{
// Create our own utility for exceptions
public sealed class ExceptionUtility
{
// All methods are static, so this can be private
private ExceptionUtility()
{ }

// Log an Exception
public static void LogException(Exception exc, string source)
{
// Include logic for logging exceptions
// Get the absolute path to the log file
string logFile = "App_Data/ErrorLog.txt";
logFile = HttpContext.Current.Server.MapPath(logFile);

// Open the log file for append and write the log
StreamWriter sw = new StreamWriter(logFile, true);
sw.WriteLine("********** {0} **********", DateTime.Now);
if (exc.InnerException != null)
{
sw.Write("Inner Exception Type: ");
sw.WriteLine(exc.InnerException.GetType().ToString());
sw.Write("Inner Exception: ");
sw.WriteLine(exc.InnerException.Message);
sw.Write("Inner Source: ");
sw.WriteLine(exc.InnerException.Source);
if (exc.InnerException.StackTrace != null)
{
sw.WriteLine("Inner Stack Trace: ");
sw.WriteLine(exc.InnerException.StackTrace);
}
}

195
sw.Write("Exception Type: ");
sw.WriteLine(exc.GetType().ToString());
sw.WriteLine("Exception: " + exc.Message);
sw.WriteLine("Source: " + source);
sw.WriteLine("Stack Trace: ");
if (exc.StackTrace != null)
{
sw.WriteLine(exc.StackTrace);
sw.WriteLine();
}
sw.Close();
}
}

Quando ocorre uma exceção, a exceção pode ser escrita em um arquivo de log de exceção,
chamando o método LogException . Este método usa dois parâmetros, o objeto de exceção e uma
seqüência de caracteres que contém detalhes sobre a origem da exceção. O log da exceção é
gravado para o arquivo ErrorLog. txt na pasta App_Data .

Adicionando uma página de erro

No aplicativo de amostra Wingtip Toys, uma página será usada para exibir erros. A página de erro
é projetada para mostrar uma mensagem de erro de seguro para os usuários do site. No entanto,
se o usuário é um desenvolvedor fazendo uma solicitação HTTP que está sendo servida localmente
na máquina onde vive o código, detalhes de erro adicionais serão exibidos na página de erro.

1. Botão direito do mouse no nome do projeto (Wingtip Toys) no Solution Explorer e


selecione Add -> New Item.
Caixa de diálogo Add New Item é exibida.

2. Selecione o Visual c# -> grupo de modelos Web à esquerda. Médio na lista, selecione O
formulário da Web com a página mestra, e denomine ErrorPage. aspx.

3. Clique em Adicionar.

4. Selecione o arquivo site Master como a página mestra e em seguida, escolha OK.

5. Substitua a marcação existente com o seguinte:

<%@ Page Title="" Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.Master"


CodeBehind="ErrorPage.aspx.cs" Inherits="WingtipToys.ErrorPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h2>Error:</h2>
<p></p>
<asp:Label ID="FriendlyErrorMsg" runat="server" Text="Label" Font-Size="Large"
style="color: red"></asp:Label>

196
<asp:Panel ID="DetailedErrorPanel" runat="server" Visible="false">
<p>&nbsp;</p>
<h4>Detailed Error:</h4>
<p>
<asp:Label ID="ErrorDetailedMsg" runat="server" Font-Size="Small" /><br />
</p>

<h4>Error Handler:</h4>
<p>
<asp:Label ID="ErrorHandler" runat="server" Font-Size="Small" /><br />
</p>

<h4>Detailed Error Message:</h4>


<p>
<asp:Label ID="InnerMessage" runat="server" Font-Size="Small" /><br />
</p>
<p>
<asp:Label ID="InnerTrace" runat="server" />
</p>
</asp:Panel>

</asp:Content>

6. Substitua o código existente do code-behind (ErrorPage.aspx.cs) para que ele apareça da


seguinte forma:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WingtipToys.Logic;

namespace WingtipToys
{
public partial class ErrorPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Create safe error messages.
string generalErrorMsg = "A problem has occurred on this web site. Please try
again. " +
"If this error continues, please contact support.";
string httpErrorMsg = "An HTTP error occurred. Page Not found. Please try
again.";

197
string unhandledErrorMsg = "The error was unhandled by application code.";

// Display safe error message.


FriendlyErrorMsg.Text = generalErrorMsg;

// Determine where error was handled.


string errorHandler = Request.QueryString["handler"];
if (errorHandler == null)
{
errorHandler = "Error Page";
}

// Get the last error from the server.


Exception ex = Server.GetLastError();

// Get the error number passed as a querystring value.


string errorMsg = Request.QueryString["msg"];
if (errorMsg == "404")
{
ex = new HttpException(404, httpErrorMsg, ex);
FriendlyErrorMsg.Text = ex.Message;
}

// If the exception no longer exists, create a generic exception.


if (ex == null)
{
ex = new Exception(unhandledErrorMsg);
}

// Show error details to only you (developer). LOCAL ACCESS ONLY.


if (Request.IsLocal)
{
// Detailed Error Message.
ErrorDetailedMsg.Text = ex.Message;

// Show where the error was handled.


ErrorHandler.Text = errorHandler;

// Show local access details.


DetailedErrorPanel.Visible = true;

if (ex.InnerException != null)
{
InnerMessage.Text = ex.GetType().ToString() + "<br/>" +
ex.InnerException.Message;
InnerTrace.Text = ex.InnerException.StackTrace;
}
else

198
{
InnerMessage.Text = ex.GetType().ToString();
if (ex.StackTrace != null)
{
InnerTrace.Text = ex.StackTrace.ToString().TrimStart();
}
}
}

// Log the exception.


ExceptionUtility.LogException(ex, errorHandler);

// Clear the error from the server.


Server.ClearError();
}
}

Quando a página de erro é exibida, o Page_Load manipulador de eventos é executado. No


Page_Load manipulador, é determinado o local de onde o erro foi tratado primeiro. Então, o último
erro que ocorreu é determinado por chamar o método GetLastError do objeto do servidor. Se a
exceção não existe mais, é criada uma exceção genérica. Então, se a solicitação HTTP foi feita
localmente, são mostrados todos os detalhes do erro. Neste caso, apenas o computador local
executando o aplicativo web vai ver estes detalhes do erro. Depois que as informações de erro tem
sido exibidas, o erro é adicionado ao arquivo de log e o erro é desmarcado do servidor.

Exibindo mensagens de erro do aplicativo


Adicionando uma seção customErrors no arquivo Web. config , você pode rapidamente manipular
erros simples que ocorrem em todo o aplicativo. Você também pode especificar como manipular
erros com base no seu valor de código de status, como 404 – arquivo não encontrado.

Atualize a configuração
Atualize a configuração, adicionando uma seção customErrors no arquivo Web. config .

1. No Solution Explorer, localize e abra o arquivo Web. config na raiz do aplicativo de


exemplo Wingtip Toys.

2. Adicione a seção customErrors no arquivo Web. config dentro do nó <system.web> como


segue:

<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="ErrorPage.aspx?handler=customErrors
%20section%20-%20Web.config">

199
<error statusCode="404" redirect="ErrorPage.aspx?
msg=404&amp;handler=customErrors%20section%20-%20Web.config"/>
</customErrors>
</system.web>

</configuration>

3. Salve o arquivo Web. config .

A seção customErrors especifica o modo, que é definido como "On". Ela também especifica o
defaultRedirect, que informa o aplicativo qual página para navegar para quando um erro ocorre.
Além disso, você adicionou um elemento de erro específico que especifica como lidar com um erro
404 quando uma página não é encontrada. Mais tarde neste tutorial, você irá adicionar erro
adicional manipulação que irá capturar os detalhes de um erro no nível do aplicativo.

Executando o aplicativo

Você pode executar o aplicativo agora para ver as rotas atualizadas.

1. Pressione F5 para executar o aplicativo de exemplo do Wingtip Toys.


O navegador abre e mostra a página Default. aspx .

2. Digite a seguinte URL no navegador (certifique-se de usar seu número de porta):


http://localhost:1234/NoPage.aspx

3. Rever o ErrorPage. aspx exibida no navegador.

200
Quando você solicitar a página de NoPage.aspx , que não existe, a página de erro irá mostrar a
mensagem de erro simples e as informações de erro detalhadas se detalhes adicionais estão
disponíveis. No entanto, se o usuário solicitou uma página inexistente de um local remoto, a
página de erro só mostraria a mensagem de erro em vermelho.

Incluindo uma exceção para fins de teste

Para verificar como seu aplicativo funcionará quando um erro ocorre, você pode criar
deliberadamente as condições de erro no ASP.NET. No aplicativo de amostra Wingtip Toys, você
lançará uma exceção de teste quando a página padrão é carregada para ver o que acontece.

1. Abra o code-behind da página Default. aspx no Visual Studio.


Será exibida a página code-behind Default.aspx.cs .

2. No Page_Load manipulador, adicione código para que o manipulador aparece da seguinte


maneira:

protected void Page_Load(object sender, EventArgs e)


{
throw new InvalidOperationException("An InvalidOperationException " +
"occurred in the Page_Load handler on the Default.aspx page.");

201
É possível criar vários tipos diferentes de exceções. No código acima, você está criando um
InvalidOperationException quando a página Default. aspx é carregada.

Executando o aplicativo

Você pode executar o aplicativo para ver como o aplicativo manipula a exceção.

1. Pressione CTRL + F5 para executar o aplicativo de exemplo do Wingtip Toys.


O aplicativo lança o InvalidOperationException.

Nota  

Você deve pressionar CTRL + F5 para exibir a página, sem quebrar o código para exibir a fonte do
erro no Visual Studio.

2. Rever o ErrorPage. aspx exibida no navegador.

Como você pode ver os detalhes do erro, a exceção foi preso pela customError seção no arquivo
Web. config .

Adicionando a manipulação de erro de aplicativo-nível


Em vez de armadilha a exceção usando a seção customErrors no arquivo Web. config , onde você
ganha um pouco de informação sobre a exceção, você pode interceptar o erro no nível do
aplicativo e recuperar detalhes do erro.

1. No Solution Explorer, localize e abra o arquivo Global.asax.cs .

202
2. Adicione um manipulador Application_Error para que ele apareça da seguinte forma:

void Application_Error(object sender, EventArgs e)


{
// Code that runs when an unhandled error occurs.

// Get last error from the server


Exception exc = Server.GetLastError();

if (exc is HttpUnhandledException)
{
if (exc.InnerException != null)
{
exc = new Exception(exc.InnerException.Message);
Server.Transfer("ErrorPage.aspx?handler=Application_Error%20-%20Global.asax",
true);
}
}

Quando ocorre um erro no aplicativo, o manipulador Application_Error é chamado. Esse


manipulador, a última exceção é obtida e revisada. Se a exceção não tratada e a exceção contém
detalhes interno-exceção (ou seja, InnerException não é null), o aplicativo transfere a execução
para a página de erro onde os detalhes de exceção são exibidos.

Executando o aplicativo

Você pode executar o aplicativo para ver os detalhes de erro adicionais fornecidos pela
manipulação de exceção no nível do aplicativo.

1. Pressione CTRL + F5 para executar o aplicativo de exemplo do Wingtip Toys.


O aplicativo lança o InvalidOperationException.

2. Rever o ErrorPage. aspx exibida no navegador.

203
Adicionando a manipulação de erro de nível de página
Você pode adicionar o tratamento a uma página usando adicionando um atributo ErrorPage da
Directiva @Page da página, ou adicionando um manipulador de evento Page_Error para o code-
behind da página de erro de nível de página. Nesta seção, você irá adicionar um manipulador de
evento Page_Error que irá transferir a execução para a página ErrorPage. aspx .

1. No Solution Explorer, localize e abra o arquivo Default.aspx.cs .

2. Adicione um manipulador Page_Error para que o código-behind aparece da seguinte


maneira:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WingtipToys
{
public partial class _Default : Page

204
{
protected void Page_Load(object sender, EventArgs e)
{
throw new InvalidOperationException("An InvalidOperationException " +
"occurred in the Page_Load handler on the Default.aspx page.");
}

private void Page_Error(object sender, EventArgs e)


{
// Get last error from the server.
Exception exc = Server.GetLastError();

// Handle specific exception.


if (exc is InvalidOperationException)
{
// Pass the error on to the error page.
Server.Transfer("ErrorPage.aspx?handler=Page_Error%20-%20Default.aspx",
true);
}
}
}

Quando ocorre um erro na página, o manipulador de evento Page_Error é chamado. Esse


manipulador, a última exceção é obtida e revisada. Se um InvalidOperationException ocorre, o
manipulador de evento Page_Error transfere execução para a página de erro onde os detalhes de
exceção são exibidos.

Executando o aplicativo

Você pode executar o aplicativo agora para ver as rotas atualizadas.

1. Pressione CTRL + F5 para executar o aplicativo de exemplo do Wingtip Toys.


O aplicativo lança o InvalidOperationException.

2. Rever o ErrorPage. aspx exibida no navegador.

205
3. Feche a janela do seu navegador.
Removendo a exceção usada para testes

Para permitir que o aplicativo de exemplo do Wingtip Toys funcionar sem lançar a exceção que
você adicionou anteriormente neste tutorial, remova a exceção.

1. Abra o code-behind da página Default. aspx .

2. No Page_Load manipulador, remova o código que lança a exceção para que o manipulador
aparece da seguinte maneira:

protected void Page_Load(object sender, EventArgs e)


{
}

Adicionando o log de erro de nível de código

206
Como mencionado anteriormente neste tutorial, você pode adicionar instruções try/catch para
tentar executar uma seção de código e lidar com o primeiro erro que ocorre. Neste exemplo, você
só irá gravar os detalhes do erro para o arquivo de log de erro para que o erro pode ser revisto
posteriormente.

1. No Solution Explorer, na pasta lógica , localize e abra o arquivo PayPalFunctions.cs .

2. Atualize o método de HttpCall para que o código aparece da seguinte maneira:

public string HttpCall(string NvpRequest)


{
string url = pEndPointURL;

string strPost = NvpRequest + "&" + buildCredentialsNVPString();


strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);

HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);


objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;

try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost);
}
}
catch (Exception e)
{
// Log the exception.
WingtipToys.Logic.ExceptionUtility.LogException(e, "HttpCall in
PayPalFunction.cs");
}

//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}

return result;

207
O código acima chama o método de LogException que está contido na classe ExceptionUtility .
Você adicionou o arquivo de classe ExceptionUtility.cs para a pasta lógica no início deste tutorial. O
método LogException usa dois parâmetros. O primeiro parâmetro é o objeto de exceção. O
segundo parâmetro é uma seqüência de caracteres usada para reconhecer a origem do erro.

Inspecionando as informações de log de erro

Como mencionado anteriormente, você pode usar o log de erros para determinar quais erros em
seu aplicativo devem ser fixados primeiro. Claro, somente os erros que foram presos e gravados no
log de erro serão registrados.

1. No Solution Explorer, localizar e abrir o arquivo ErrorLog. txt na pasta App_Data .


Você pode precisar selecionar a opção "Mostrar todos os arquivos" ou a opção "Atualizar" do
topo do Solution Explorer para ver o arquivo ErrorLog. txt .

2. Revise o log de erro exibido no Visual Studio:

Mensagens de erro seguras


É importante notar que quando seu aplicativo exibe mensagens de erro, ele deve dar informações
que um usuário mal-intencionado pode achar útil para atacar seu aplicativo. Por exemplo, se seu
208
aplicativo sem sucesso tenta gravar um banco de dados, ele não deve exibir uma mensagem de
erro que inclui o nome de usuário que está usando. Por esta razão, uma mensagem de erro
genérica em vermelho é exibida ao usuário. Todos os detalhes de erro adicionais só são exibidos
para o desenvolvedor na máquina local.

Usando o ELMAH
ELMAH (manipuladores e módulos de log de erro) é um recurso de log de erro que você conecte
seu aplicativo ASP.NET como um pacote NuGet. ELMAH fornece os seguintes recursos:

 Log de exceções não tratadas.

 Uma página da web para exibir o log inteiro de recodificado exceções não tratadas.

 Uma página da web para exibir os detalhes de cada um conectado a exceção.

 Uma notificação por email de cada erro no momento em que ele ocorre.

 Um feed RSS dos últimos 15 erros do registro.

Antes que você possa trabalhar com o ELMAH, você deve instalá-lo. Isto é fácil de usar o instalador
de pacotes NuGet . Como mencionado no início desta série de tutoriais, NuGet é uma extensão do
Visual Studio que torna mais fácil para instalar e atualizar bibliotecas de código aberto e
ferramentas no Visual Studio.

1. Dentro do Visual Studio, no menu ferramentas , selecione Gerenciador de pacotes da


biblioteca -> Gerenciar pacotes de NuGet para solução.

2. A caixa de diálogo Gerenciar pacotes de NuGet é exibida dentro do Visual Studio.

3. Na caixa de diálogo Gerenciar pacotes do NuGet , expanda Online à esquerda e selecione


nuget.org. Em seguida, encontrar e instalar o pacote do ELMAH da lista de pacotes disponíveis
on-line.

209
4. Você precisará ter uma conexão de internet para baixar o pacote.

5. Na caixa de diálogo Selecionar projetos , verifique se que a seleção de WingtipToys está


selecionada e clique em OK.

6. Clique em fechar na caixa de diálogo Gerenciar pacotes NuGet se necessário.

7. Se Visual Studio solicita que você recarregar todos os arquivos abertos, selecione "Sim para
todos".

8. O pacote do ELMAH adiciona entradas por si no arquivo Web. config na raiz do seu projeto.
Se Visual Studio te perguntar se você deseja recarregar o arquivo Web. config modificado, clique
em Sim.
210
ELMAH está agora pronto para armazenar qualquer sem tratamento de erros que ocorrem.

Visualização do Log ELMAH

Exibindo o log ELMAH é fácil, mas primeiro, você criará uma exceção não tratada que será gravada
no log do ELMAH.

1. Pressione CTRL + F5 para executar o aplicativo de exemplo do Wingtip Toys.

2. Para gravar uma exceção não tratada no log ELMAH, navegue no seu navegador para o
seguinte URL (usando seu número da porta):
http://localhost:1234/NoPage.aspx
A página de erro será exibida.

3. Para exibir o log do ELMAH, navegue no seu navegador para o seguinte URL (usando seu
número da porta):
http://localhost:1234/ELMAH.axd

Resumo
Neste tutorial, você aprendeu sobre tratamento de erros no nível do aplicativo, o nível de página e
o nível de código. Você também aprendeu como log de erros manipulados e não tratados para
revisão posterior. Você adicionou o utilitário ELMAH para fornecer registro de exceção e
notificação para seu aplicativo usando o NuGet. Além disso, você aprendeu sobre a importância
das mensagens de erro seguras.
211
Conclusão
Isso completa a 4.5 ASP.NET Web Forms e Visual Studio 2013 - série de tutoriais Wingtip Toys. Para
obter mais informações sobre os novos recursos de formulários da Web disponíveis em 4.5 de
ASP.NET e Visual Studio 2013, consulte ASP.NET e Web Tools para Visual Studio 2013 notas de
lançamento.

Recursos adicionais
Detalhes de erro de log com monitoramento da integridade ASP.NET
ELMAH

Agradecimentos
Eu gostaria de agradecer as seguintes pessoas que fizeram importantes contribuições para o
conteúdo desta série de tutoriais:

 Alberto Poblacion, MVP & MCT, Espanha


 Alex Thissen, Países Baixos (twitter: @alexthissen)
 Andre Tournier, EUA
 Laercio Joshi, Microsoft
 Bojan Vrhovnik, Eslovénia
 Bruno Sonnino, Brasil (twitter: @bsonnino)
 Dos Carlos Santos, Brasil
 Dave Campbell, EUA (twitter: @windowsdevnews)
 Jon Galloway, Microsoft (twitter: @jongalloway)
 Michael farelos, EUA (twitter: @mrsharps)
 Papa Mike
 Mitchel Sellers, EUA (twitter: @MitchelSellers)
 Paul Cociuba, Microsoft
 Paulo Morgado, Portugal
 Regina Márcia Rodrigues, Microsoft
 Tim Ammann, Microsoft
 Tom Dykstra, Microsoft

Contribuições da Comunidade
 Graham Mendick (@grahammendick)
Visual Studio 2012 relacionados a amostra de código do MSDN: Navegação Wingtip Toys
212
 James Chaney (jchaney@agvance.net)
Visual Studio 2012 relacionados a amostra de código do MSDN: 4.5 ASP.NET Web Forms
Tutorial Series no Visual Basic
 Andrielle Azevedo - Microsoft técnico público contribuinte (twitter: @driazevedo)
Visual Studio 2012 Tradução: Iniciando com ASP.NET Web Forms 4.5 – Parte 1 – Introdução e
Visão Geral

Informações do autor

Erik Reitan – Erik Reitan é um escritor sênior de programação da Microsoft. Durante seu tempo
livre ele gosta de desenvolvimento de aplicativos do Windows Phone e Windows 8. Siga ele no
Twitter em @ReitanErik.

213

Você também pode gostar