0% acharam este documento útil (0 voto)
7 visualizações54 páginas

Introdução ao ASP.NET MVC 5

O documento apresenta uma introdução ao desenvolvimento de aplicações web utilizando ASP.NET MVC 5, destacando a evolução do ASP.NET WebForms e a necessidade de boas práticas de programação. Ele orienta sobre a instalação do Visual Studio 2013 e a criação de um projeto inicial, além de explicar a estrutura do MVC e a separação de responsabilidades entre Model, View e Controller. O curso também aborda a implementação de um sistema de controle de estoque, utilizando o Entity Framework para acesso a dados.

Enviado por

Antonio pedro
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato DOCX, PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
7 visualizações54 páginas

Introdução ao ASP.NET MVC 5

O documento apresenta uma introdução ao desenvolvimento de aplicações web utilizando ASP.NET MVC 5, destacando a evolução do ASP.NET WebForms e a necessidade de boas práticas de programação. Ele orienta sobre a instalação do Visual Studio 2013 e a criação de um projeto inicial, além de explicar a estrutura do MVC e a separação de responsabilidades entre Model, View e Controller. O curso também aborda a implementação de um sistema de controle de estoque, utilizando o Entity Framework para acesso a dados.

Enviado por

Antonio pedro
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato DOCX, PDF, TXT ou leia on-line no Scribd

INTRODUÇÃO

Ir para o próximo capítulo

Explicação

Downloads
Segue o link do projeto inicial: Visual Studio 2013

Existem muitos programadores que desenvolvem aplicativos web para o sistema operacional
Windows. Muitos deles já desenvolveram utilizando a linguagem ASP ou, nos útimos anos, o
famoso [Link] WebForms.

O WebForms, em sua época, revolucionou a maneira de se programar para Web. Programar com
WebForms parecia programar com Visual Basic ou Delphi! Ou seja, os componentes eram
arrastados pro formulário, e o programador podia colocar ações em eventos desses componentes,
por exemplo, imprimir uma mensagem na tela quando acontecer um click no botão.

Como muita gente na época vinha desse tipo de programação de aplicativos Desktop, aprender
WebForms não era tão difícil. Sem contar a grande sensação de produtividade, já que os
componentes que existiam faziam as mais diversas coisas, como exibir dados de um banco de
dados de maneira elegante, separando em páginas.

Mas infelizmente hoje percebemos que códigos feitos com WebForms são difíceis de manter. O
motivo? Apesar de ser altamente produtivo, não existia alguma coisa que separasse o código que
lida com interface, do código que lida com regra de negócio, do código que lida com banco de
dados, e assim por diante... Na prática, os códigos WebForms são "macarrônicos", ou seja, são
grandes e fazem muita coisa diferente.

No fim, o problema é que o WebForms não nos "obriga" a usar boas práticas de programação.
Percebendo isso, a Microsoft resolveu criar uma alternativa ao WebForms: o chamado [Link]
MVC! O MVC, um padrão de desenvolvimento muito utilizado no mundo web é conhecido por
"forçar" o programador a separar as responsabilidades. Ou seja, código de interface separado de
código de regra de negócio separado de código de banco de dados, e assim por diante. A
vantagem disso? Sua aplicação viverá por mais tempo! Você conseguirá mantê-la pra sempre!
Estudaremos mais sobre o padrão MVC no próximo capítulo.

Nesse curso estudaremos o framework [Link] MVC 5 e seus recursos!

Instalação do Visual Studio 2013


Antes de começarmos, precisamos instalar o ambiente de desenvolvimento para o [Link] MVC
5, o Visual Studio 2013. Nesse curso utilizaremos o Visual Studio Express 2013 for web
([Link] que é uma versão gratuita
da ferramenta. Ou seja, para fazer o curso você não precisará comprar a versão paga da
ferramenta (embora recomendado para empresas).

Depois de fazer o download do instalador, execute-o. Isso abrirá uma nova janela em que o
Visual Studio pergunta se aceitamos o contrato de licença. Leia os termos e depois marque a
opção I agree to the License Terms and Privacy Policy se você aceitar os termos da
Microsoft.

[Imagem [Link]]

E depois clique no botão install. Com isso o instalador começará a fazer o download dos
componentes adicionais do Visual Studio e executará a instalação em sua máquina.

[Imagem [Link]]

Quando a instação for concluída, execute o Visual Studio que acabou de ser instalado. Na
primeira execução ele perguntará se você deseja se logar na sua conta da microsoft para
compartilhar configurações entre máquinas. Se você quiser compartilhar as suas informações
com a Microsoft, faça o login em sua conta, senão clique no link Not now, maybe later. Com
isso estamos prontos para utilizar o Visual Studio para desenvolver nossas aplicações com o
[Link] MVC.

Primeiro Projeto
Vamos criar um projeto do [Link] MVC. Abra o Visual Web Developer e aperte
Ctrl+Shift+N, a janela New Project será aberta, selecione a linguagem Visual C# e [Link]
Web Application.
Na próxima janela, procure o campo Select a template e escolha a opção Empty, isso criará
um projeto web vazio. Agora para que o projeto contenha as bibliotecas do [Link] MVC,
procure o campo Add folders and core references for e nele marque a opção MVC e depois
clique no botão Ok. Isso é tudo que precisamos para criar um novo projeto [Link] MVC 5!
Após criar o projeto, abra o solution explorer (Ctrl+Alt+L), repare que diversos arquivos e pastas
foram automaticamente criados pela IDE. Essa é a estrutura de diretórios esperada de uma
aplicação [Link] MVC. É importante conhecer essa estrutura, pois você precisará sempre
seguir as convenções já pré-definidas. Essas convenções, aliás, são muito comuns ao longo do
[Link] MVC: elas lhe pouparão muito trabalho!
Entre as pastas criadas na estrutura inicial, duas são mais importantes. A pasta Controllers: é
nela que guardaremos nossas classes responsáveis por tratar as requisições que vem do browser
do usuário. É aqui que pegaremos os dados que o usuário nos envia através de formulários, por
exemplo. E a pasta Views, onde os arquivos que serão utilizados para renderizar a resposta para o
usuário são colocadas. Por exemplo, é aqui que guardaremos o HTML que renderiza o
formulário.

Primeira página do projeto


Agora que já aprendemos como criar o projeto inicial do [Link] MVC, vamos aprender como
criar a página inicial da aplicação. Para isso, criaremos uma nova classe que será responsável por
tratar todas as requisições para a página inicial. Uma classe que trata requisições web é chamada
de Controller pelo [Link] MVC e deve ser criada dentro da pasta controllers da aplicação.

Podemos utilizar o próprio Visual Studio para criar o controller. Para isso, clique com o botão
direito na pasta Controllers do projeto e selecione a opção Add > Controller:

Dentro da janela que é aberta, a Add Scaffold selecione a opção MVC 5 Controller - Empty
e depois clique no botão Add.
Na próxima janela, precisamos dar um nome para a classe que será criada. Como esse é o
controller inicial da aplicação, nós o chamaremos de Home, porém, por convenção, controllers do
[Link] MVC tem o nome terminado pela palavra Controller, então o nome final da classe
será HomeController.

Com isso, o Visual Studio criará uma nova classe na pasta Controllers do projeto com o
seguinte código:

using System;
using [Link];
using [Link];
using [Link];
using [Link];

namespace [Link]
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
}

Veja que essa classe herda de uma classe chamada Controller do namespace [Link].
Todo controller do [Link] MVC precisa herdar dessa classe.

Para atender requisições web, o [Link] MVC utiliza os métodos públicos implementados
dentro dos controllers, esses métodos são conhecidos como actions. As actions do MVC sempre
devolver um objeto do tipo ActionResult. Para decidir qual é a action que deve ser utilizada
para atender uma determinada requisição, o [Link] MVC utiliza um conjunto de regras
conhecido como Rota Padrão.

Segundo a rota padrão, quando o navegador tenta utilizar uma url da forma /Home/Index, a
primeira parte da url (Home) indica qual é o nome do controller que atenderá a requisição e a
segunda parte indica o nome da action. Então nesse exemplo, a action Index do
HomeController seria utilizada.

A rota padrão também possui valores padrão para os nomes do controller e da action. Quando
não informamos o nome da action, a action Index é utilizada e quando não informamos o nome
do controller, o HomeController é utilizado. Então podemos acessar o método Index do
HomeController através de três endereços diferentes: /Home/Index, /Home e /.

Agora que já sabemos como criar e acessar controllers, precisamos aprender como implementar
uma action e o como montar a resposta HTML que será devolvida para o navegador que acessou
a aplicação.

Na implementação das actions, precisamos colocar o código que acessa as regras de negócio
implementadas pela aplicação e, ao terminar de executar as lógicas de negócio, precisamos
avisar o [Link] MVC que queremos executar a lógica de visualização da aplicação. Fazemos
isso através do método View que é herdado da classe Controller:

public ActionResult Index()


{
// Chama a lógica de negócio da aplicação

// Depois redireciona para a visualização


return View();
}

Para implementarmos a lógica de visualização da aplicação, precisamos seguir mais uma


convenção do [Link] MVC. Arquivos de visualização possuem a extensão cshtml e devem ser
colocados dentro da pasta Views da aplicação. Todas as views de um determinado controller,
devem ficar dentro de uma subpasta de Views com o mesmo nome do controller, no caso do
HomeController, todas as views seriam colocadas dentro da pasta Views/Home. O nome do
arquivo deve ser <nome da action>.cshtml, [Link] no caso do método Index do
HomeController.

Dentro do cshtml, precisamos colocar todo o código HTML que será devolvido para o
navegador. Todo o código colocado dentro desse arquivo é interpretado por um componente do
[Link] MVC chamado Razor. Vamos então implementar o código da página inicial da
aplicação. Para isso utilizaremos novamente um assistente do Visual Studio.

Clique com o botão direito do mouse sobre o método Index e selecione a opção Add View.

Dentro da janela que é aberta pelo Visual Studio, desmarque a opção Use a layout page e
depois clique em Add.
Com isso o Visual Studio criará um novo arquivo na pasta Views/Home chamado [Link]
com o seguinte código:

@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
</div>
</body>
</html>

Vamos modificar esse arquivo para mostrar uma mensagem na página inicial da aplicação:

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
Página inicial usando [Link] MVC 5!
</body>
</html>

Agora vamos apertar o F5 para executar a aplicação no servidor do Visual Studio. Isso abrirá o
navegador do seu sistema utilizando um endereço da forma: [Link] ou
seja, não estamos informando nem o controller e nem a action nessa url, o [Link] MVC
executará a lógica do método Index do HomeController. A mesma lógica seria executada caso
acessássemos as urls [Link] ou
[Link]

Com isso terminamos a nossa primeira página de uma aplicação [Link] MVC 5!

PADRAO MVC

Ir para o próximo capítulo

Explicação
Muitos sistemas tornam-se difíceis de manter porque existem trechos de código que tem muita
responsabilidade, ou seja, fazem muita coisas. Aplicações desktop são um exemplo empírico
desse problema; muitos códigos legados em VB ou Delphi são difíceis de manter porque, um
mesmo trecho de código é responsável por capturar dados do usuário (através de caixas de texto,
botões, etc), tomar ações a partir desses dados (por exemplo, alterar uma tabela no banco de
dados), e por fim alterar a interface do usuário para mostrar que o programa reagiu da maneira
esperada (exibindo uma mensagem de sucesso).

O problema da falta de divisão de responsabilidades não ocorre apenas no desktop. Na web,


temos páginas ASP que contém, além de código HTML (para a apresentação do resultado),
código VBScript com a lógica de negócio e código SQL acessando o banco de dados. Tudo isso
é dificil de manter. O código fica espalhado e muitas vezes repetido.

Uma possível solução para o problema é tentar separar as diversas tarefas citadas acima, da
seguinte forma:
Quando um usuário interage com o sistema, ele executa uma ação e obtém visualmente o
resultado da mesma. Isto é, primeiro uma regra de negócios é executada (adicionar algo,
atualizar algo, buscar algo), e depois informações são mostradas na tela.

Isso forma três camadas: A camada chamada de Model é responsável somente pelas regras de
negócio; a camada de View é responsável unicamente por exibir os dados para o usuário final;
por fim, a camada Controller é responsável por receber as ações feitas pelos usuários na View e
convertê-las em chamadas de negócio dentro do Model. O padrão conhecido por MVC (Model-
View-Controller) sugere que o programador faça exatamente essa separação no código.

Veja o desenho abaixo:

 Todo sistema possui regras de negócios, que podem ser simples ou complexas. Todas
elas devem estar separadas em classes que tem essa regras como única responsabilidade.
Ou seja, toda e qualquer ação de regra de negócio deve ser realizada por exclusivamente
esse conjunto de classes.
 Interfaces de usuário também devem ser isoladas. Códigos de interface tendem a ser
grandes e a sofrerem mudanças constantes. Por esse motivo, toda parte responsável pela
exibição das informações para o usuário devem estar isoladas em outro ponto do sistema.
 Para conectar as ações que o usuário realiza na interface e fazer com que essas ações
resultem em execuções de regra de negócio, é necessário que uma outra camada faça essa
tarefa. Ou seja, essa camada recebe informações da camada de visualização e as
transforma em invocações de regras de negócio.

O padrão MVC tem se mostrado uma maneira educada de separar essas camadas, e por isso sua
utilização é crescente no mercado. Muitos frameworks, inclusive de outras linguagens de
programação, como é o caso do Ruby on Rails (do mundo Ruby) e VRaptor (do mundo Java),
adotam o MVC como solução para separar responsabilidades.

O [Link] MVC, como o próprio nome diz, segue o padrão MVC. Veja que os nomes
adotados pelo MVC são idênticos aos do padrão MVC. Suas regras de negócio devem ficar em
classes C# convencionais dentro da pasta /Models. O código responsável apenas pela interface
do usuário são salvas na pasta /Views. Por fim, as classes controladoras, salvas no diretório
/Controllers, conectam a view com os modelos.

Perceba a separação! Não há mistura de código! Isso faz do MVC um dos padrões mais
populares para desenvolvimento de aplicações!

Leia um pouco mais sobre o MVC no site do Martin Fowler no site


[Link]

CONTROLANDO AS REQUISIÇÕES

Ir para o próximo capítulo

Explicação
Para aprendermos o [Link] MVC, desenvolveremos um sistema de controle de estoque. Esse
sistema deve permitir o cadastro, listagem, visualização de detalhes e controle da quantidade de
produtos. Cada produto deve ter um nome, um preço, uma categoria, uma descrição e a
quantidade em estoque.

public class Produto


{
public int Id { get; set; }

public String Nome { get; set; }

public float Preco { get; set; }

public CategoriaDoProduto Categoria { get; set; }

public int CategoriaId { get; set; }

public String Descricao { get; set; }

public int Quantidade { get; set; }


}

Categorias tem apenas um nome e uma descrição.

public class CategoriaDoProduto


{
public int Id { get; set; }
public String Nome { get; set; }

public String Descricao { get; set; }


}

Para armazenarmos as informações no banco de dados, utilizaremos o Entity Framework com o


SQL Server Express Edition que é instalado junto com o Visual Studio 2013. Todo o código que
utiliza o Entity Framework pode ser encontrado dentro das classes especializadas em acesso ao
banco de dados conhecidas como DAO (Data Access Object).

O controller de produtos
Vamos inicialmente baixar o projeto inicial do curso no link [Link]
online-public/asp-net-mvc5/[Link]. Descompacte o zip e depois abra o arquivo
[Link] com o Visual Studio 2013 Express for Web. Esse arquivo irá importar um
projeto que já fornece uma implementação para os DAOs de produtos (ProdutosDAO), de
categorias (CategoriasDAO) e de usuários (UsuariosDAO).

Vamos agora desenvolver o controller para os produtos da aplicação, da mesma forma que
fizemos no capítulo inicial do curso, chamado ProdutoController:

public class ProdutoController : Controller


{
// Implementação
}

Dentro do método Index desse controller, executaremos a lógica para listar todos os produtos
cadastrados no banco de dados utilizando uma tabela do html, mas no controller que acabamos
de criar, a action Index simplesmente redireciona o usuário para a camada de visualização.

Como foi explicado na seção anterior, a camada de visualização do MVC deve conter apenas
lógica de visualização. Logo, a lista de produtos deve ser enviada do controlador para a view.

Para conseguirmos a lista de produtos, devemos acessar os dados que estão gravados no banco de
dados e, como mencionado anteriormente, o acesso ao banco é isolado dentro dos DAOs. Logo,
precisamos instanciar um DAO que saiba acessar os produtos no banco, o ProdutosDAO.

public ActionResult Index()


{
ProdutosDAO dao = new ProdutosDAO();

return View();
}

Com o DAO, podemos utilizar o auto complete (Ctrl + Espaço) oferecido pela IDE para listar os
métodos e propriedades do objeto.
Vemos que existe um método Lista que retorna um IList<Produto>. Utilizaremos esse
método para recuperar a lista de produtos do banco de dados.

public ActionResult Index()


{
ProdutosDAO dao = new ProdutosDAO();
IList<Produto> produtos = [Link]();

return View();
}

Obtivemos a lista, porém ela está visível apenas dentro do método do controlador. Para
enviarmos a lista de produtos para a camada de visualização, precisamos utilizar uma
propriedade que é herdada da classe Controller chamada ViewBag.

A ViewBag é um objeto em que podemos criar propriedades dinamicamente, para isso


precisamos apenas fazer uma atribuição dentro do código do controller:

public ActionResult Index()


{
ProdutosDAO dao = new ProdutosDAO();
IList<Produto> produtos = [Link]();
[Link] = produtos;
return View();
}

Toda informação que colocamos dentro da ViewBag pode ser acessada pela camada de
visualização, pois ela também tem acesso ao mesmo objeto ViewBag que utilizamos no
controller. Com a ViewBag, podemos enviar qualquer número de objetos para a camada de
visualização.

Com o método do controller pronto, precisamos somente criar nosso arquivo de view, esse
arquivo será o Views/Produto/[Link]

Esse arquivo será utilizado pelo [Link] MVC para apresentar o resultado da requisição.
Queremos exibir o id, o nome e o valor dos produtos de nossa lista dentro de uma tabela, ou seja,
fazer algo equivalente ao código abaixo:
<tr>
<td>[Link]</td>
<td>[Link]</td>
<td>[Link]</td>
</tr>

Não há como saber se o programador queria exibir o texto "[Link]" ou recuperar o valor
do Id da variável produto e, por esse motivo, o [Link] MVC nos obriga a colocar o prefixo @
nas variáveis:

<tr>
<td>@[Link]</td>
<td>@[Link]</td>
<td>@[Link]</td>
</tr>

O código que criamos serve para exibir um produto, porém nosso controller enviou uma lista,
logo precisamos executar o código acima para cada item da lista. Em C#, isso seria equivalente
ao código:

foreach(var produto in LISTA DE PRODUTOS)


{
<tr>
<td>@[Link]</td>
<td>@[Link]</td>
<td>@[Link]</td>
</tr>
}

Na view, o foreach é quase igual ao código em C#, precisamos apenas adicionar um @ antes do
foreach:

@foreach(var produto in LISTA DE PRODUTOS)


{
<tr>
<td>@[Link]</td>
<td>@[Link]</td>
<td>@[Link]</td>
</tr>
}

Agora podemos utilizar a ViewBag para acessar a lista de produtos que foi enviada pelo
controller:

<table>
<thead>
<tr>
<th>Id</th>
<th>Nome do Produto</th>
<th>Preco</th>
</tr>
</thead>
<tbody>
@foreach (var produto in [Link])
{
<tr>
<td>@[Link]</td>
<td>@[Link]</td>
<td>@[Link]</td>
</tr>
}
</tbody>
</table>

O código completo da view para a tabela de produtos fica da seguinte forma:

@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
<table>
<thead>
<tr>
<th>Id</th>
<th>Nome do Produto</th>
<th>Preco</th>
</tr>
</thead>
<tbody>
@foreach (var produto in [Link])
{
<tr>
<td>@[Link]</td>
<td>@[Link]</td>
<td>@[Link]</td>
</tr>
}
</tbody>
</table>
</div>
</body>
</html>

A lista está pronta!

Relembrando a primeira seção, a rota padrão do [Link] MVC faz com que requisições para
/Produto sejam tratadas pelo método Index do ProdutoController, podemos acessar a action
desenvolvida acessando a url /Produto após subir o servidor com o F5.
LIDANDO COM FORMULARIOS

Ir para o próximo capítulo

Explicação
Temos um sistema capaz de listar produtos cadastrados, vamos agora incrementá-lo com a
capacidade de cadastrar novos produtos.

Para realizar o cadastro, precisamos inicialmente de um formulário que receba os dados


necessários para se criar um novo produto.

<form action="/Produto/Adiciona">
<label for="nome">Nome:</label>
<input id="nome" name="nome" />

<label for="preco">Preço:</label>
<input id="preco" name="preco" />

<label for="quantidade">Quantidade:</label>
<input id="quantidade" name="quantidade" />

<label for="descricao">Descrição:</label>
<input id="descricao" name="descricao" />

<label for="categoria">Categoria:</label>
<input id="categoria" name="categoriaId" />

<input type="submit" />


</form>

Mas como mencionado no começo do curso, esse formulário faz parte da camada de visualização
do MVC, logo precisamos criar um método no controller que, por enquanto, não faz nada a não
ser redirecionar para a view com o formulário. Vamos então adicionar um método chamado Form
dentro do ProdutoController.

public ActionResult Form()


{
return View();
}

Podemos ver o formulário gerado acessando o endereço: /Produto/Form com o navegador.

Recebendo as informações do formulário na


action
Vamos agora criar um novo método no ProdutoController que será responsável por receber as
informações que foram enviadas pelo formulário. Como no formulário colocamos a action
/Produto/Adiciona, então os dados do formulário serão enviados para o método Adiciona do
ProdutoController:

public ActionResult Adiciona()


{
// implementação da action
}

Dentro dessa action, para utilizarmos as informações que foram enviadas pelo navegador,
precisamos declarar parâmetros no método que possuem o mesmo nome do campo de texto no
html (atributo name da tag input).

public ActionResult Adiciona(String nome, float preco, int quantidade, String


descricao, int categoriaId)

Dentro desse método, precisamos instanciar um novo produto com as informações recebidas:

Produto produto = new Produto() {


Nome = nome,
Preco = preco,
Quantidade = quantidade,
Descricao = descricao,
CategoriaId = categoriaId
};

E, por fim, utilizaremos o DAO para adicionar o produto no banco de dados:

ProdutosDAO dao = new ProdutosDAO();


[Link](produto);

O código final de nossa action fica da seguinte forma:

public ActionResult Adiciona(String nome, float preco, int quantidade, String


descricao, int categoriaId)
{
Produto produto = new Produto() {
Nome = nome,
Preco = preco,
Quantidade = quantidade,
Descricao = descricao,
CategoriaId = categoriaId
};
ProdutosDAO dao = new ProdutosDAO();
[Link](produto);
return View();
}

Repare que os parâmetros enviados pelo formulário são automaticamente convertidos para os
tipos certos. Essa conversão é realizada pelo [Link] MVC.

Envio de dados para uma action através de


model binders
Em nossa solução para o problema de cadastro de produtos, foi necessário instanciar
manualmente a classe Produto utilizando os parâmetros da requisição, porém seria muito mais
interessante se o método recebesse como argumento uma instância de Produto populada com os
parâmetros da requisição.

public ActionResult Adiciona(Produto produto)


{
ProdutosDAO dao = new ProdutosDAO();
[Link](produto);
return View();
}

Para que esse código funcione, os campos do formulário devem ter nome da forma
[Link], por exemplo, se quisermos que o atributo Nome do produto
seja preenchido automaticamente, devemos criar um formulário HTML que tenha um campo
chamado [Link]: <input name="[Link]" />.

<form action="/Produto/Adiciona">
<label for="nome">Nome:</label>
<input id="nome" name="[Link]" />

<label for="preco">Preço:</label>
<input id="preco" name="[Link]" />
<label for="quantidade">Quantidade:</label>
<input id="quantidade" name="[Link]" />

<label for="descricao">Descrição:</label>
<input id="descricao" name="[Link]" />

<label for="categoria">Categoria:</label>
<input id="categoria" name="[Link]" />

<input type="submit" />


</form>

A variável produto recebida pelo método da classe controladora é instanciada e preenchida por
um componente do [Link] MVC conhecido como Model Binder.

Os model binders do [Link] MVC são componentes que convertem os parâmetros da


requisição para objetos. Tanto no primeiro caso, em que recebíamos tipos simples, quanto no
segundo caso, em que recebemos uma instância de produto, é o model binder que realiza a
conversão de tipos.

Formulários utilizando o Post


Ao enviarmos o formulário que desenvolvemos anteriormente, podemos ver que a url mostrada
pelo navegador contem as informações preenchidas no formulário, isso acontece pois essa é a
forma de envio de informações utilizada por padrão pelo navegador, o método de envio chamado
Get.

O Get é geralmente utilizado quando desenvolvemos uma busca dentro da aplicação, pois como
todas as informações do formulário de busca estão na url do navegador, podemos facilmente
compartilhar os resultados com outras pessoas.

Mas em um cadastro de informações não queremos deixar todas as informações expostas na url,
nesses casos, podemos utilizar um outro método de envio chamado post. Para utilizarmos o post
como método de envio do formulário, precisamos apenas colocar o atributo method na
declaração da tag form:

<form action="/Produto/Adiciona" method="post">


<!-- código do formulário -->
</form>

Depois dessa modificação, se testarmos novamente o cadastro de produtos, o navegador mostrará


a url /Produto/Adiciona sem as informações que foram preenchidas no formulário.

Vimos que podemos enviar tanto requisições do tipo Get quanto do tipo Post para a action
Adiciona do ProdutoController que o cadastro continuará funcionando, porém essa action
deveria aceitar apenas requisições do tipo post, pois não estamos implementando uma busca.
Quando queremos limitar o tipo de requisição que uma action recebe para o tipo post, utilizamos
uma anotação (attribute do C#) chamada HttpPostAttribute sobre a declaração do método:
[HttpPostAttribute]
public ActionResult Adiciona(Produto produto)

Como por convenção toda anotação do C# termina com o sufixo Attribute, podemos
simplificar o código para:

[HttpPost]
public ActionResult Adiciona(Produto produto)

Da mesma forma que podemos utilizar o HttpPostAttribute para aceitar apenas requisições do
tipo post, também temos o HttpGetAttribute para aceitar apenas requisições do tipo Get.

Redirecionando para a lista de produtos


Após a execução do método Adiciona, o [Link] MVC tentará renderizar a view
Produto/[Link], porém queremos que o usuário seja redirecionado para a página de
listagem de produtos (Index). Poderíamos repetir o mesmo código que fizemos no método
Index aqui, mas isso não faz sentido.

Para contornar esse problema, utilizaremos um novo tipo de resultado definido na classe
Controller, o RedirectToAction.

public ActionResult Adiciona(Produto produto)


{
ProdutosDAO dao = new ProdutosDAO();
[Link](produto);
return RedirectToAction("Index");
}

O RedirectToAction redirecionará o usuário para o método Index do controller atual


(ProdutoController).

Melhorando a usabilidade do formulário com


o Combo Box
Repare que no formulário que criamos, o usuário precisa digitar o id de uma categoria existente
no banco de dados.

<label for="categoria">Categoria:</label>
<input id="categoria" name="categoriaId" />

Mas o id não é uma informação que o usuário deveria conhecer. Seria mais interessante se
pudéssemos selecionar o nome a partir de uma lista de categorias cadastradas.
Vamos então utilizar a tag html select para exibir os nomes das categorias existentes e enviar o
valor do Id selecionado para o servidor

<label for="categoria">Categoria:</label>
<select id="categoria" name="[Link]">
@foreach(var categoria in [Link])
{
<option value="@[Link]">@[Link]</option>
}
</select>

E agora modificar nosso formulário para utilizar a tag select:

<form action="/Produto/Adiciona">
<label for="nome">Nome:</label>
<input id="nome" name="[Link]" />

<label for="preco">Preço:</label>
<input id="preco" name="[Link]" />

<label for="quantidade">Quantidade:</label>
<input id="quantidade" name="[Link]" />

<label for="descricao">Descrição:</label>
<input id="descricao" name="[Link]" />

<label for="categoria">Categoria:</label>
<select id="categoria" name="[Link]">
@foreach(var categoria in [Link])
{
<option value="@[Link]">@[Link]</option>
}
</select>

<input type="submit" />


</form>

Agora precisamos fazer com que a variável [Link] contenha a lista de categorias.
Para isso, vamos modificar o método Form do ProdutoController:

public ActionResult Form()


{
CategoriasDAO dao = new CategoriasDAO();
IList<CategoriaDoProduto> categorias = [Link]();
[Link] = categorias;
return View();
}

Visualize seu formulário pela url /Produto/Form.


MODEL VALIDATION

Ir para o próximo capítulo

Explicação
Um problema muito comum enfrentado por desenvolvedores web é a validação dos dados.
Usuários sempre se esquecem de preencher determinados campos, preenchem e-mails inválidos,
data de nascimento incorretas, e assim por diante. A tarefa da aplicação web é perceber esses
pequenos problemas, e avisar o usuário sobre o mal entendido.

Mas o código de validação geralmente é feio e cheio de ifs. Veja o controller abaixo fazendo
validações:

[HttpPost]
public ActionResult Adiciona(Produto produto)
{
if([Link] > 0 && [Link] > 0 && [Link] < 50000 &&
![Link]([Link])) {
ProdutosDAO dao = new ProdutosDAO();
[Link](produto);
return RedirectToAction("Index");
}
else {
return RedirectToAction("erros");
}

Veja o if que escrevemos para garantir que a quantidade, preço e descrição estão dentro do
esperado. Código feio e difícil de manter.

O [Link] MVC resolve o problema da validação através dos Model Validators. Quando
definimos as classes de modelo, podemos anotar seus atributos com as regras de validação
necessárias para que o modelo seja válido. Por exemplo, para fazer com que o campo Nome
tenha no máximo 20 caracteres, devemos anotá-lo com a classe StringLengthAttribute:

class Produto
{
[StringLengthAttribute(20)]
String Nome { get; set; }

// outros atributos do produto.


}

Mas como vimos, por convenção, no C#, todas as anotações são nomeadas utilizando-se o sufixo
Attribute e quando utilizadas como anotação, o sufixo é desnecessário. Logo, podemos
simplificar o código acima para:

class Produto
{
[StringLength(20)]
String Nome { get; set; }

// outros atributos do produto.


}

Como vimos na seção anterior, quando enviamos os dados de um modelo para uma action, o
[Link] MVC utilizará os dados da requisição para preencher os campos do modelo no
processo de Model Binding. Além disso, o [Link] MVC também verifica as anotações
presentes nos atributos da classe e executa as validações necessárias. O resultado da validação
fica disponível em uma variável chamada ModelState que é herdada da classe Controller.

O ModelState guarda todas as regras de validação que foram violadas. Para verificar se todas as
regras de validação foram obedecidas utiliza-se o atributo IsValid do ModelState.

if([Link]) {
// O Modelo foi validado corretamente, então pode ser gravado no banco de
dados.
}
else
{
// O Modelo não foi validado corretamente.
}

Vamos modificar a action Adiciona do ProdutoController para que ela cadastre o novo
produto apenas se não houverem erros de validação e, caso contrário, exiba o formulário de
cadastro. Como queremos reutilizar a view da action Form, vamos utilizar uma segunda versão
do método View que recebe o nome da action cuja view queremos utilizar.

[HttpPost]
public ActionResult Adiciona(Produto produto)
{
if([Link]) {
ProdutosDAO dao = new ProdutosDAO();
[Link](produto);
return RedirectToAction("Index");
}
else
{
CategoriasDAO categoriasDAO = new CategoriasDAO();
[Link] = [Link]();
return View("Form");
}
}

Agora precisamos apenas mostrar os erros de validação na View.

Mensagens de Validação e o HtmlHelper


Agora que sabemos como verificar os erros de validação, vamos exibir as mensagens geradas.
Para isso, utilizaremos a classe HtmlHelper.
O [Link] MVC disponibiliza em todas as views uma instância de HtmlHelper na variável
Html. Essa variável é capaz de gerar pedaços de código HTML. Para exibir as mensagens de
validação utilizaremos o método ValidationMessage da classe HtmlHelper.

O ValidationMessage recebe como argumento o nome da mensagem de validação que deve ser
gerada. As mensagens de validação geradas durante o processo de model binding tem nome da
forma [Link], logo devemos utilizar [Link]
para recuperar as mensagens referentes ao campo Nome do produto.

@[Link]("[Link]")

Vamos modificar o formulário de cadastro de produtos para exibir a mensagem de validação:

<form action="/Produto/Adiciona" method="post">


<label for="nome">Nome:</label>
<input id="nome" name="[Link]" />
@[Link]("[Link]")

<label for="preco">Preço:</label>
<input id="preco" name="[Link]" />

<label for="quantidade">Quantidade:</label>
<input id="quantidade" name="[Link]" />

<label for="descricao">Descrição:</label>
<input id="descricao" name="[Link]" />

<label for="categoria">Categoria:</label>
<select id="categoria" name="[Link]">
@foreach(var categoria in [Link])
{
<option value="@[Link]">@[Link]</option>
}
</select>

<input type="submit" />


</form>

Tente cadastrar um produto sem preencher o campo nome e veja as mensagens de validação
geradas.

Implementando regras de validação


complexas
Suponha que produtos da categoria Informática (categoria de id 1) devem custar pelo menos 100
reais, nesse caso as anotações definidas pelo [Link] MVC não conseguem resolver o
problema. Temos que realizar a validação manualmente.

Em casos em que as anotações não resolvem o problema, devemos utilizar o método


AddModelError do ModelState. Esse método recebe como argumento duas strings, a primeira
indica o nome do erro de validação e a segunda a mensagem de erro que deve ser exibida.

[Link](String nomeDoErro, String mensagem)

O nome do erro pode ser utilizado na view para se recuperar a mensagem de erro através do
método ValidationMessage do HtmlHelper.

@[Link](nomeDoErro)

Então a implementação de nossa regra de validação complexa fica da seguinte forma:

int idDaInformatica = 1;
if([Link](idDaInformatica) && [Link] < 100)
{
[Link]("[Link]", "Produtos
da categoria informática devem ter preço maior do que 100");
}

Logo nossa action Adiciona com a regra complexa fica da seguinte forma:

[HttpPost]
public ActionResult Adiciona(Produto produto)
{
int idDaInformatica = 1;
if([Link](idDaInformatica) && [Link] < 100)
{
[Link]("[Link]",
"Produtos da categoria informática devem ter preço maior do que 100");
}
if([Link]) {
ProdutosDAO dao = new ProdutosDAO();
[Link](produto);
return RedirectToAction("Index");
}
else
{
CategoriasDAO categoriasDAO = new CategoriasDAO();
[Link] = [Link]();
return View("Form");
}
}

Agora precisamos apenas modificar o código do formulário de cadastro:

<form action="/Produto/Adiciona" method="post">


@[Link]("[Link]")
<label for="nome">Nome:</label>
<input id="nome" name="[Link]" />
@[Link]("[Link]")

<label for="preco">Preço:</label>
<input id="preco" name="[Link]" />

<label for="quantidade">Quantidade:</label>
<input id="quantidade" name="[Link]" />

<label for="descricao">Descrição:</label>
<input id="descricao" name="[Link]" />

<label for="categoria">Categoria:</label>
<select id="categoria" name="[Link]">
@foreach(var categoria in [Link])
{
<option value="@[Link]">@[Link]</option>
}
</select>

<input type="submit" />


</form>

Acesse novamente o formulário de cadastro de produtos e teste a nova validação.

Mantendo os valores preenchidos em caso de


erro de validação
No exemplo, exibimos as mensagens de erro de validação na view, porém deixamos o formulário
de cadastro em branco novamente. Para fazer com que o formulário exiba os dados que foram
enviados para a action de cadastro, precisamos fazer com que esses dados sejam reenviados para
a view [Link]. Para isso utilizaremos novamente a ViewBag.

Se os dados do formulário forem inválidos, queremos armazenar o produto recebido na ViewBag

if([Link])
{
// produto válido
}
else
{
// produto inválido então vamos guardá-lo na ViewBag
[Link] = produto;
// redireciona para o [Link]
}

Com essa modificação, a action Adiciona fica da seguinte forma:


[HttpPost]
public ActionResult Adiciona(Produto produto)
{
int idDaInformatica = 1;
if([Link](idDaInformatica) && [Link] < 100)
{
[Link]("[Link]",
"Produtos da categoria informática devem ter preço maior do que 100");
}
if([Link]) {
ProdutosDAO dao = new ProdutosDAO();
[Link](produto);
return RedirectToAction("Index");
}
else
{
[Link] = produto;
CategoriasDAO categoriasDAO = new CategoriasDAO();
[Link] = [Link]();
return View("Form");
}
}

Falta apenas modificar a view [Link] para exibir os dados do produto. Para isso,
acessaremos os dados armazenados na ViewBag. Por exemplo, para preencher o nome do
produto, preencheremos o atributo value da tag input:

<input name="[Link]" value="@[Link]" />

Para o caso da tag select, precisamos indicar qual option deve ser inicialmente selecionado.
Para decidir qual categoria deve ser selecionada, iremos, dentro do @foreach, comparar cada
categoria com a categoria do produto da ViewBag. Se as categorias forem iguais, marcaremos a
opção como selecionada.

@foreach(var categoria in [Link]) {


if([Link]([Link]))
{
<option value="@[Link]"
selected="selected">@[Link]</option>
}
else
{
<option value="@[Link]">@[Link]</option>
}
}

Veja que o atributo selected da tag option funciona como um valor booleano indicando se a
opção está ou não selecionada. Quando temos um atributo no Html que funciona como um valor
booleano, no Razor, podemos atribuir diretamente uma expressão booleana (condição) para esse
atributo. Se a expressão for true, o Razor inclui o atributo no Html gerado, senão o atributo é
ignorado. Vamos então utilizar essa característica do Razor para marcar a categoria que foi
selecionada:
<option value="@[Link]"
selected="@[Link]([Link])">
@[Link]
</option>

O formulário final fica da seguinte forma:

<form action="/Produto/Adiciona">
@[Link]("[Link]")

<label for="nome">Nome:</label>
<input id="nome" name="[Link]" value="@[Link]" />
@[Link]("[Link]")

<label for="preco">Preco:</label>
<input id="preco" name="[Link]" value="@[Link]" />
@[Link]("[Link]")

<label for="quantidade">Quantidade:</label>
<input id="quantidade" name="[Link]"
value="@[Link]" />

<label for="descricao">Descricao:</label>
<input id="descricao" name="[Link]"
value="@[Link]" />

<label for="categoria">Categoria:</label>
<select id="categoria" name="[Link]">
@foreach(var categoria in [Link])
{
<option value="@[Link]"
selected="@[Link]([Link])">
@[Link]
</option>
}
</select>

<input type="submit" />


</form>

Com isso o formulário será preenchido automaticamente caso ocorra um erro de validação,
porém não conseguimos mais acessar a url /Produto/Form! Esse erro ocorre pois a action Form
não atribui um valor ao atributo Produto da ViewBag. Vamos então corrigir a action Form.

public ActionResult Form()


{
CategoriasDAO dao = new CategoriasDAO();
[Link] = new Produto();
[Link] = [Link]();
return View();
}

Pronto! Validamos nossos dados!


TRABALHANDO COM VIEWS

Nos capítulos anteriores desenvolvemos uma página que mostra a lista de todos os produtos
cadastrados no banco de dados, porém nessa página, para não colocarmos muitas informações,
listamos o Id, Nome e Quantidade dos produtos. Vamos agora desenvolver uma nova página
onde podemos visualizar todas as informações de um produto cadastrado no banco de dados.

Vamos então adicionar um novo método no ProdutoController que recebe um id, busca no
banco o produto com Id igual ao recebido e envia essa informação para ser exibida na view.
Vamos chamar essa action de Visualiza.

public ActionResult Visualiza(int produtoId)


{
ProdutosDAO dao = new ProdutosDAO();
Produto produto = [Link](produtoId);
[Link] = produto;
return View(produto);
}

Vamos agora implementar a view para a action Visualiza.

Id: @[Link]<br />


Nome: @[Link]<br />
Categoria: @[Link]<br />
Preço: @[Link]<br />
Descrição: @[Link]<br />
Quantidade: @[Link]<br />

<a href="/Produto">Voltar para a lista de produtos</a>

Repare que codificamos o link para a lista de produtos diretamente na view. O problema disso é
que, se um dia o link mudar, precisaremos mudar em todos os HTMLs que apontem para o
mesmo endereço! Muito trabalhoso!

Podemos utilizar um novo método do HtmlHelper, o ActionLink. Esse método cria o código
html de um link de acordo com os parâmetros passados. Queremos definir que o texto do link
deve ser Voltar para a lista de produtos e que esse link deve nos redirecionar para a
action Index da classe ProdutoController, para isso vamos utilizar a versão sobrecarregada de
ActionLink que recebe o texto do link, o nome da action e o nome do controller.

@[Link](texto, nomeDaAction, nomeDoController)

Em nosso caso, queremos inserir a seguinte chamada:

@[Link]("Voltar para a lista de produtos", "Index", "Produto")

Vamos agora inserir o link para a página de visualização para cada item da lista de produtos.
Queremos criar links que enviem o usuário para a action Visualiza do ProdutoController
passando produtoId como argumento. Como muitas vezes uma action deve receber um
identificador e realizar sua tarefa de acordo com o id recebido, o [Link] MVC configura a
rota padrão com um id genérico como argumento opcional. Dessa forma podemos criar urls da
forma /Produto/Visualiza/1.

Para que a action receba o valor do id capturado pelo [Link] MVC, devemos fazer com que
ela receba um argumento chamado id de qualquer tipo. Em nosso caso, queremos receber um id
inteiro, logo vamos substituir produtoId por id na action Visualiza:

public ActionResult Visualiza(int id)


{
ProdutosDAO dao = new ProdutosDAO();
Produto produto = [Link](id);
[Link] = produto;
return View(produto);
}

Vamos modificar a lista de produtos para que ela tenha links para a visualização. Abra o arquivo
Views/Produto/[Link] e localize o laço que percorre a lista de produtos:

@foreach (var produto in [Link])


{
<tr>
<td>@[Link]</td>
<td>@[Link]</td>
<td>@[Link]</td>
</tr>
}

Queremos que [Link] seja um link para a página de visualização. Para realizar essa
tarefa, podemos criar o link diretamente:

<td><a href="/Produto/Visualiza/@[Link]">@[Link]</a></td>

ou utilizar o ActionLink do HtmlHelper. O ActionLink possui uma versão sobrecarregada que


recebe o texto do link, o nome da action e um objeto cujos atributos serão utilizados para
preencher os parâmetros da url. Nesse caso, queremos enviar um objeto que tenha um atributo
chamado id contendo o valor do id do produto:

new { id = [Link] }

Logo o código do link fica da seguinte forma:

<td>@[Link]([Link], "Visualiza", new { id = [Link] })</td>

Porém temos um problema, o código da view não compila! O problema é que o compilador não
sabe qual é o tipo da variável produto, logo não consegue descobrir que a expressão
[Link] gera uma String e [Link] gera um int. Para resolver esse problema
devemos fazer com que a variável produto seja do tipo Produto:
@foreach([Link] produto in [Link])

Como agora o tipo de produto é conhecido, o código do ActionLink funciona!

Views fortemente tipadas


Ao contrário do que acontece no código do controller, nas views não temos nenhum auxílio da
IDE, o Visual Web Developer. Isso ocorre pois as variáveis enviadas para a view através da
ViewBag são dinâmicas, ou seja, o uso da variável só é verificado na execução do código e não
na compilação. No [Link] MVC esse problema é resolvido através de Views Fortemente
Tipadas (Strongly Typed View).

Para utilizarmos uma view fortemente tipada, precisamos enviar a a variável para a view de uma
forma diferente. Ela precisa ser enviada como argumento do método View. Por exemplo, na
action Index do ProdutoController, a lista de produtos pode ser enviada através do seguinte
código:

public ActionResult Index()


{
ProdutosDAO dao = new ProdutosDAO();
IList<Produto> produtos = [Link]();
return View(produtos);
}

A variável passada como argumento do método View pode ser acessada pela view através de
uma variável chamada Model, essa variável é considerada pelo [Link] MVC como a variável
principal da view. Agora precisamos modificar a lista de produtos
(Views/Produto/[Link]) para que ela utilize a Model ao invés de [Link]:

@foreach([Link] produto in Model)

Mas apenas essa modificação não é suficiente para o [Link] MVC saber o tipo da variável
Model, no início do código da view, precisamos indicar qual é o tipo da variável Model através
do comando @model do Razor:

@model IList<[Link]>

Com isso estamos declarando qual é o tipo da variável Model que está sendo utilizada na view e
por isso podemos utilizar livremente a inferência de tipos no código do foreach:

@foreach(var produto in Model)

Como agora o Razor sabe que a variável Model é do tipo


IList<[Link]>, a inferência de tipos deduzirá que a variável
produto declarada no foreach é do tipo [Link] ao invés do tipo
dinâmico.
CRIANDO ROTAS NA APLICAÇÃO

Ir para o próximo capítulo

Explicação

Customização de rotas
Suponha que a empresa em que você trabalha queira modificar o sistema de controle de estoque
para o sistema que você está desenvolvendo nesse curso, porém como exitem diversos clientes
que dependem das URLs do sistema atual, devemos fazer com que as URLs do novo sistema
sejam iguais às antigas.

Vamos fazer com que a listagem de produtos seja servida pela URL /produtos e que a
visualização por /produtos/{produtoId}. A customização de uma url no [Link] MVC 5 é
feita utilizando-se uma definida no framework chamada RouteAttribute, essa anotação é
utilizada sobre actions dos controllers e recebe como argumento a nova url do método.

Para fazermos com que o Index do ProdutoController possa ser acessado através de
/produtos, utilizamos o seguinte código:

[Route("produtos")]
public ActionResult Index()
{
// implementação
}

Podemos fazer o mesmo para a lógica de visualização, porém nela precisamos capturar qual é o
id que será enviado para a lógica do controller. Para capturarmos uma variável da url,
precisamos colocar o nome da variável que queremos capturar dentro de chaves, {id} para
capturar uma variável chamada id.

[Route("produtos/{id}")]
public ActionResult Visualiza(int id)
{
// implementação
}

Agora podemos acessar a visualização do produto de id 1 através da seguinte url: /produtos/1.

Além de utilizar o RouteAttribute, precisamos também habilitar a customização de rotas


dentro do arquivo App_Start/[Link]. Dentro desse arquivo podemos encontrar o
método RegisterRoutes.
Para habilitarmos a customização de rotas, precisamos utilizar o método
MapMvcAttributeRoutes do objeto RouteCollection que é recebido como argumento no
método RegisterRoutes.

public static void RegisterRoutes(RouteCollection routes)


{
[Link]();

// Código que já estava no método


}

Como utilizamos o ActionLink para construir os links do capítulo anterior, os endereços dos
links serão automaticamente atualizados para utilizar as urls que acabamos de configurar.

Mas no ActionLink precisamos passar qual é o nome da action e do controller para onde
queremos enviar o usuário, mas o que aconteceria se por algum motivo a equipe decidisse mudar
o nome do método ou do controller? Nesse caso teríamos que modificar todos os ActionLinks
de todo projeto!

Para resolvermos esse problema, podemos utilizar uma configuração adicional do


RouteAttribute, o Name. O parâmetro Name define qual é o nome da rota e esse nome pode ser
utilizado posteriormente para montarmos links nas views.

[Route("produtos", Name="ListaProdutos")]
public ActionResult Index()
{
// implementação
}

[Route("produtos/{id}", name="VisualizaProduto")]
public ActionResult Visualiza(int id)
{
// implementação
}

E agora, na view, podemos utilizar o método RouteLink do HtmlHelper passando o texto do


link e o nome da rota para montar o link. Para criarmos o link para a página de visualização,
utilizamos o seguinte código:

@[Link]("Voltar para a lista", "ListaProdutos")

No link de visualização, precisamos também passar quais são as informações que devem ser
enviadas para o servidor. Essas informações são enviadas, novamente, através de objetos
anônimos do C#.

@[Link]([Link], "VisualizaProduto", new {id = [Link]})

LAYOUT COM TWEET BOOTSTRAP


Explicação

Layout para a aplicação


Agora que já sabemos como utilizar o [Link] MVC, chegou a hora de melhorar a aparência da
aplicação. Para isso utilizaremos uma biblioteca css chamada twitter bootstrap que pode ser
baixada no site [Link] nesse curso utilizaremos a versão 3.1.1 que pode ser
baixada nesse link [Link]
[Link].

Depois do download do bootstrap, precisamos colocá-lo dentro da aplicação. Arquivos de


conteúdo estático como css e imagens são geralmente colocados dentro de uma pasta chamada
Content do projeto, vamos então criar essa nova pasta e dentro dela, criaremos a pasta Css que
conterá todos os arquivos css que serão utilizados. Dentro dessa pasta, cole o arquivo
[Link] que pode ser encontrado dentro do zip do twitter bootstrap, além disso, coloque
nessa pasta também o arquivo de estilo do site que pode ser baixado nessa url:

Vamos começar aplicando o layout na lista de produtos da aplicação. Abra o arquivo


Views/Produto/[Link] e dentro da tag head, vamos importar os arquivos css utilizando
a tag link:

<link rel="stylesheet" href="url do css" />

No href do link, precisamos passar a url do arquivo css dentro da pasta Content/Css do
projeto. No Razor, podemos conseguir o endereço da pasta da aplicação utilizando o símbolo ~
no código do href. Para chegarmos ao [Link], precisamos, a partir da pasta do projeto,
acessar a pasta Content/Css, então a url fica da seguinte forma: ~/Content/Css. Agora
podemos utilizar essa url na tag link:

<link rel="stylesheet" href="~/Content/Css/[Link]"/>


<link rel="stylesheet" href="~/Content/Css/[Link]"/>

Essa tag link é importada dentro do head da página:

<head>
<link rel="stylesheet" href="~/Content/Css/[Link]"/>
<link rel="stylesheet" href="~/Content/Css/[Link]"/>
</head>

Agora precisamos modificar o código do body da página para que ele utilize o twitter bootstrap
para fazer o layout. Começaremos com um menu superior onde poderemos acessar as diferentes
páginas da aplicação. Dentro da tag body, colocaremos uma div com a classe container e
dentro dessa tag, colocaremos um novo div para o cabeçalho da página:

<body>
<div class="container">
<div class="header">
<!-- código do menu do cabeçalho -->
</div>
</div>
</body>

Os links do menu ficarão dentro de uma lista do html, tag ul, com as classes nav nav-pills
pull-right. Além disso, mostraremos também o nome da aplicação dentro de uma tag h3:

<div class="header">
<ul class="nav nav-pills pull-right">
<li>@[Link]("Home", "Index", "Home")</li>
<li>@[Link]("Produtos", "Index", "Produto")</li>
<li>@[Link]("Categorias", "Index", "Categoria")</li>
<li>@[Link]("Usuários", "Index", "Usuario")</li>
</ul>
<h3 class="text-muted">Caelum Estoque</h3>
</div>

Depois de colocarmos o código do cabeçalho da aplicação, vamos colocar mais uma div que
conterá o código da tabela de produtos:

<div class="container">
<div class="header">
<!-- código do menu -->
</div>
<div id="conteudo">
<!-- Aqui fica o código da tabela de produtos -->
</div>
</div>

Se executarmos a aplicação, veremos a seguinte página:


Veja que a tabela padrão do html não ficou muito boa nesse layout, então utilizaremos uma
tabela definida no bootstrap. Dentro da tag table, coloque as classes table table-hover, com
isso teremos a tabela abaixo:

Com isso terminamos o layout da lista de produtos, agora precisamos replicar esse layout para as
outras páginas da aplicação. O menu superior e a importação dos estilos do bootstrap serão
utilizados em todas as páginas da aplicação, a única parte diferente entre as páginas é o conteúdo
da div que contém a tabela de produtos, então teremos que replicar esse código em todas as
views da aplicação.

Mas o que aconteceria se precisássemos mudar o layout da aplicação, como copiamos o código
para todas as páginas, teríamos que mudar o código de toda aplicação. Para resolvermos esse
problema, podemos utilizar os layout pages do [Link] MVC.

O layout page é um arquivo cshtml comum onde colocamos o código que é comum às views da
aplicação. Esse arquivo é geralmente colocado dentro de uma pasta chamada Views/Shared e
tem um nome começado com o símbolo _. Então, vamos criar uma nova pasta chamada Shared
dentro da pasta views do projeto e dentro dessa pasta, colocaremos o arquivo _Layout.cshtml
com o código que será repetido nas views:

<html>
<head>
<link rel="stylesheet" href="~/Content/Css/[Link]"/>
<link rel="stylesheet" href="~/Content/Css/[Link]"/>
</head>
<body>
<div class="container">
<div class="header">
<ul class="nav nav-pills pull-right">
<li>@[Link]("Home", "Index", "Home")</li>
<li>@[Link]("Produtos", "Index", "Produto")</li>
<li>@[Link]("Categorias", "Index", "Categoria")</li>
<li>@[Link]("Usuários", "Index", "Usuario")</li>
</ul>
<h3 class="muted-text">Caelum Estoque</h3>
</div>
<div id="conteudo">
<!-- Aqui fica o conteúdo da view -->
</div>
</div>
</body>
</html>

No ponto em que queremos colocar o conteúdo da view, precisamos chamar o método


@RenderBody() do Razor:

<html>
<head>
<link rel="stylesheet" href="~/Content/Css/[Link]"/>
<link rel="stylesheet" href="~/Content/Css/[Link]"/>
</head>
<body>
<div class="container">
<div class="header">
<ul class="nav nav-pills pull-right">
<li>@[Link]("Home", "Index", "Home")</li>
<li>@[Link]("Produtos", "Index", "Produto")</li>
<li>@[Link]("Categorias", "Index", "Categoria")</li>
<li>@[Link]("Usuários", "Index", "Usuario")</li>
</ul>
<h3 class="muted-text">Caelum Estoque</h3>
</div>
<div id="conteudo">
@RenderBody()
</div>
</div>
</body>
</html>

Agora precisamos fazer com que a lista de produtos utilize o layout que acabamos de criar. Para
fazer isso, precisamos abrir um bloco de código na view e dentro desse bloco definiremos uma
variável chamada Layout com o caminho completo para o layout page.

@{
Layout = "caminho completo para o layout page";
}

Na string do caminho para a layout page, podemos utilizar novamente o símbolo ~ para
referenciarmos a pasta inicial do projeto:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

Agora podemos apagar todo o código de layout que colocamos inicialmente na view da lista de
produtos. Agora só precisamos definir os layouts para as outras views da aplicação, então
teremos que, novamente, replicar o bloco que define a variável layout em todas as views. O que
pode causar problemas caso tenhamos que, por exemplo, mudar o nome do arquivo de layout.

Para resolvermos esse problema, precisamos definir essa variável Layout para todas as views da
aplicação, para isso, podemos criar no projeto um novo arquivo especial do razor chamado
_ViewStart.cshtml dentro da pasta Views da aplicação. O arquivo _ViewStart.cshtml é o
primeiro cshtml que é executado quando o razor gera o html e é geralmente utilizado para
definir variáveis globais para as views da aplicação.

Então vamos utilizar o _ViewStart.cshtml para definir o layout page padrão da aplicação.
Dentro da pasta Views, crie um novo arquivo chamado _ViewStart.cshtml com o código que
define a variável Layout:

@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

Melhorando o aparência dos formulários


Agora vamos melhorar também a aparêcia dos formulários que criamos na aplicação, para isso,
dentro de todas as tags input, colocaremos a classe form-control definida dentro do twitter
bootstrap:

<input name="[Link]" value="@[Link]" class="form-


control"/>

Além disso, colocaremos a classe form-control também dentro da tag select do cadastro de
produtos:

<select name="[Link]" class="form-control">


<!-- código das options -->
</select>

Após essas modificações, o formulário fica da seguinte forma:


Com isso conseguimos customizar nossa aplicação [Link] MVC 5!

AJAX

Manipulação da quantidade em estoque


Nesse capítulo vamos desenvolver a funcionalidade de manipular a quantidade de produtos que
está gravada no banco de dados, então dentro do ProdutoController vamos desenvolver uma
nova action chamada DecrementaQtd que recebe o id do produto que será decrementado:

public ActionResult DecrementaQtd(int id)


{
}

Dentro desse método, precisamos buscar o produto do banco de dados, decrementar sua
quantidade, atualizar as informações e por fim redirecionar o usuário para a página de listagem
de produtos para que ele veja as informações atualizadas:

public ActionResult DecrementaQtd(int id)


{
ProdutosDAO dao = new ProdutosDAO();
Produto produto = [Link](id);
[Link]--;
[Link](produto);
return RedirectToAction("Index");
}

Agora na listagem de produtos, podemos adicionar mais uma coluna com um link que chama
essa nova action:

@foreach(var produto in Model)


{
<tr>
<td>@[Link]</td>
<td>@[Link]([Link], "Visualiza", new
{id=[Link]})</td>
<td>@[Link]</td>
<td><a href="/Produto/DecrementaQtd/@[Link]">Decrementar</a></td>
</tr>
}

Podemos testar essa nova funcionalidade da aplicação acessando a lista de produtos, url
/produtos. Quando clicarmos no link de decrementar a quantidade, podemos ver que a
quantidade é realmente decrementada no banco de dados, porém a página é recarregada.

Esse recarregamento ocorre pois quando fazemos uma requisição web, o navegador sempre
espera a resposta devolvida pelo servidor e depois faz o recarregamento da página, esse é o modo
síncrono de requisições web. Para evitarmos o recarregamento das páginas, precisamos utilizar o
modo assíncrono de navegação.

Requisições assíncronas com javascript


Para fazermos requisições assíncronas em uma aplicação web, precisamos programar o
navegador utilizando a linguagem javascript. Requisições assíncronas feitas por javascript são
conhecidas como requisições ajax.

Cada navegador implementa as requisições assíncronas de uma forma diferente, e para lidar com
essa diferença entre os navegadores do mercado, utilizaremos uma biblioteca javascript chamada
jquery (que é colocada pelo visual studio dentro da pasta Scripts do projeto).

Para podermos utilizar a biblioteca jquery, precisamos inicialmente importá-la dentro do cshtml
da lista de produtos, fazemos isso com o seguinte código:

<script type="text/javascript" src="~/Scripts/[Link]"></script>

Agora que importamos a biblioteca jquery, precisamos declarar um bloco de código javascript
que realmente fará a requisição ajax:

<script type="text/javascript">
// o script fica aqui
</script>
Para fazermos uma requisição ajax do tipo get utilizando o jquery, utilizamos a função $.get
definida na bibioteca e para o post, o $.post.

Nessas funções, o primeiro argumento que colocamos é a url para onde queremos enviar a
requisição e o segundo representa os parâmetros que serão enviados para o servidor:

$.post(url, params);

No nosso caso, a url é /Produto/DecrementaQtd. Já os parâmetros precisam ser enviados


através de um dicionário do javascript, onde declaramos o nome do parâmetro e o valor que será
associado àquele nome:

var url = "/Produto/DecrementaQtd";


var params = { id: 1 };
$.post(url, params);

Com esse código, faremos uma requisição ajax para decrementar a quantidade do produto que
tem id igual a 1. Para podermos reutilizá-lo para os outros produtos cadastrados, vamos isolá-lo
dentro de uma função javascript que recebe o id do produto que será decrementado:

function decrementa(produtoId){
var url = "/Produto/DecrementaQtd";
var params = { id: produtoId };
$.post(url, params);
}

Mas veja que dentro do código da função colocamos manualmente a url para a action
DecrementaQtd do servidor. O que aconteceria se essa url fosse modificada (pelo
RouteAttribute, por exemplo)? Nesse caso teríamos que lembrar de modificar também esse
código javascript. Para resolvermos esse problema, podemos utilizar um objeto do [Link]
MVC responsável por gerar o endereço das actions na camada de visualização da aplicação, o
UrlHelper, que pode ser acessado através da variável @Url dentro do código do cshtml.

Para gerarmos uma url com o UrlHelper, utilizamos o método Action informando qual é a
action e qual é o controller que queremos acessar:

@[Link]("DecrementaQtd", "Produto")

A função decrementa do javascript utilizando o UrlHelper fica da seguinte forma:

function decrementa(produtoId){
var url = "@[Link]("DecrementaQtd", "Produto")";
var params = { id: produtoId };
$.post(url, params);
}

Agora precisamos fazer com que o clique no link de decremento chame a função decrementa
que acabamos de declarar no código javascript. Então vamos inicialmente modificar o link para
que quando clicado, o navegador não saia da lista de produtos:
<a href="#">Decrementar</a>

Para executarmos uma função no clique do link precisamos utilizar o atributo onclick dentro da
declaração da tag a colocando a chamada para o decrementa com o id do produto correto:

<a href="#" onclick="decrementa(@[Link]);">Decrementar</a>

Com essa modificação, toda vez que o usuário clicar em um link, o navegador enviará uma
requisição ajax para o servidor para decrementar a quantidade de um produto cadastrado.

Atualizando a página com o jQuery


Fizemos com que os links da tabela enviem requisições ajax para o servidor para decrementar a
quantidade de um produto cadastrado, porém a quantidade que está sendo mostrada na tabela não
está sendo atualizada.

Quando o servidor terminar de responder a requisição ajax, caso ela seja bem sucedida,
queremos atualizar o valor da quantidade que está sendo exibida. Para executarmos uma função
quando uma requisição ajax é bem sucedida, precisamos utilizar o terceiro argumento do
$.post. Esse argumento recebe a função que será executada caso a requisição seja bem
sucedida:

function decrementa(produtoId){
var url = "/Produto/DecrementaQtd";
var params = { id: produtoId };
$.post(url, params, atualiza);
}

function atualiza(){
// código que será executado depois do ajax.
}

Dentro do atualiza, podemos, por exemplo, mostrar uma caixa de mensagens se a requisição
foi bem sucedida:

function atualiza(){
alert("Sucesso");
}

Agora quando clicarmos em um dos links de decremento, o navegador fará uma requisição ajax e
o usuário verá a mensagem "Sucesso". Mas ao invés de mostrar uma mensagem, queremos
atualizar a quantidade atual exibida na tabela. Para isso, utilizaremos o jQuery.

Para conseguirmos manipular o conteúdo de uma página utilizando o jquery, precisamos


inicialmente buscar o elemento que queremos manipular, no caso o td que mostra a quantidade
atual do produto. Para buscarmos o elemento mais facilmente, colocaremos um id na declaração
do td da quantidade:
<td id="quantidade">@[Link]</td>

Mas com esse código, o mesmo id será colocado para todos os produtos. Para conseguirmos um
id único para cada produto, precisamos, por exemplo, colocar o @[Link]:

<td id="quantidade@[Link]">@[Link]</td>

Mas se executarmos o código, veremos que no html gerado, o id de todos os tds ficou com o
código: quantidade@[Link]. Isso aconteceu porque quantidade@[Link] se parece
com um endereço de e-mail válido e por isso o Razor não interpreta o código para ler o id do
produto. Para forçarmos o Razor a interpretar o código, precisamos colocar parêntesis em volta
da expressão que deve ser executada:

<td id="quantidade@([Link])">@[Link]</td>

Agora dentro do código do atualiza, precisamos do id e da quantidade do produto que foi


modificado para conseguirmos atualizar a página. Para podermos utilizar mais facilmente as
informações de um objeto devolvido pelo servidor, nós faremos com que o servidor devolva uma
resposta em um formato que pode ser utilizado facilmente pelo javascript, o Json (Javascript
Object Notation).

Para devolvermos o Json do produto do servidor, utilizamos mais um método herdado da classe
Controller chamado Json passando qual é o objeto que queremos devolver como resposta:

public ActionResult DecrementaQtd(int id)


{
ProdutosDAO dao = new ProdutosDAO();
Produto produto = [Link](id);
[Link]--;
[Link](produto);
return Json(produto);
}

Para podermos utilizar a resposta do servidor dentro da função atualiza, precisamos apenas
colocar um argumento na declaração da função:

function atualiza(resposta) {
// usa a resposta devolvida
}

Dentro da variável resposta temos o Json do produto que foi devolvido pelo servidor. Como a
resposta está no formato Json, podemos ler as propriedades do produto diretamente do Json. Para
lermos, por exemplo, a Quantidade do produto, utilizamos o código: [Link].
Podemos, por exemplo, mostrar a quantidade atualizada com o seguinte código:

function atualiza(resposta) {
alert([Link]);
}
Agora que já sabemos como utilizar o Json, aprenderemos como utilizar o jquery para atualizar a
página. O primeiro passo é buscarmos o elemento que queremos atualizar dentro do html da
página. Para isso precisamos utilizar a função $ definida pelo jquery passando o id do elemento
que queremos buscar com o prefixo #:

function atualiza(resposta) {
var elemento = $("#quantidade" + [Link]);
}

Agora que temos o elemento que será atualizado, precisamos utilizar a função html do jquery
para atualizar o conteúdo do html do elemento:

function atualiza(resposta){
var elemento = $("#quantidade" + [Link]);
[Link]([Link]);
}

Agora nossa página consegue decrementar a quantidade utilizando requisições ajax para o
servidor e também atualizar o conteúdo da página utilizando a resposta que foi devolvida. O
código final do Views/Produto/[Link]:

@model IList<[Link]>

<table>
<thead>
<tr>
<th>Id</th>
<th>Nome</th>
<th>Quantidade</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach(var produto in Model)
{
<tr>
<td>@[Link]</td>
<td>@[Link]</td>
<td id="quantidade@([Link])">@[Link]</td>
<td><a href="#"
onclick="decrementa(@[Link]);">Decrementar</a></td>
</tr>
}
</tbody>
</table>

<script type="text/javascript" src="~/Scripts/[Link]"></script>


<script type="text/javascript">
function decrementa(produtoId){
var url = "@[Link]("DecrementaQtd", "Produto")";
var params = {id : produtoId};
$.post(url, params, atualiza);
}
function atualiza(resposta){
var elemento = $("#quantidade" + [Link]);
[Link]([Link]);
}
</script>

AUTENTICAR UTILIZADORES

Mantendo dados entre requisições


Sabemos como implementar uma aplicação web capaz de responder requisições, porém imagine
que precisamos mostrar para um usuário quantas vezes ele acessou uma determinada página.
Então devemos ter alguma forma de manter um contador que depende do usuário que está
acessando a página.

O código que queremos deve ser da seguinte forma:

int contador = PegaContadorDoUsuarioAtual();


contador++;
GuardaOContadorDoUsuario(contador);

Para suportar esse tipo de estado, o [Link] MVC implementa o conceito de sessão.

No [Link] MVC, a sessão do usuário pode ser acessada de uma action através da variável
Session, que foi herdada da classe Controller. A variável Session funciona como um
dicionário de String para object, logo podemos armazenar diversos nomes com valores
diferentes por usuário.

Em nosso exemplo, queremos armazenar um valor do tipo int dentro da Session.

Session["contador"] = contador;

Assim como em um dicionário do C#, podemos recuperar o valor associado a uma chave com
Session[nomeDaChave], porém como a sessão guarda o tipo object, precisamos converter o
valor devolvido para o tipo correto. No caso do contador, precisamos converter o valor devolvido
para o tipo int, essa converão pode ser feita através da classe Convert:

int contador = Convert.ToInt32(Session["contador"]);

Caso uma chave não tenha sido inserida na sessão, a busca Session[chaveInexistente]
retorna null. Se passarmos o valor null para o método Convert.ToInt32, ele nos retorna o
valor zero.

Vamos agora implementar nosso contador por usuário. Criaremos um novo controller chamado
ContadorController e adicionaremos o método Index:
public ActionResult Index()
{
return View();
}

Agora, precisamos fazer uma série de operações: recuperar o valor do contador da session,
incrementá-lo, armazenar o valor atualizado na session e, por fim, enviá-lo para a view. Caso o
contador não tenha sido definido, queremos definir o contador como 0.

public ActionResult Index()


{
object valorNaSession = Session["contador"];
int contador = Convert.ToInt32(valorNaSession);
contador++;
Session["contador"] = contador;
return View(contador);
}

Agora só precisamos mostrar o valor do contador na camada de visualização da aplicação.


Vamos então criar o arquivo Views/Contador/[Link]

Contador atual: @Model

Tente acessar essa action de diversos navegadores e veja que o valor do contador é diferente para
cada navegador.

O Sistema de autenticação
Queremos que apenas usuários logados no sistema tenham acesso às páginas de listagem e
cadastro de produtos. Então precisamos de uma nova página da aplicação onde faremos o login
dos usuários. A lógica dessa nova tela ficará dentro de um novo controller chamado
LoginController. Dentro dessa classe, a action Index será a responsável por mostrar o
formulário de login para o usuário:

public class LoginController : Controller


{
public ActionResult Index()
{
return View();
}
}

Agora precisamos implementar a view do formulário de login, arquivo


Views/Login/[Link]:

<form action="/Login/Autentica" method="post">


<label for="login">Login:</label>
<input name="login" id="login" class="form-control" />

<label for="senha">Senha:</label>
<input name="senha" id="senha" class="form-control" />

<input type="submit" value="Logar" />


</form>

Mas com esse código os dados digitados no campo de senha do formulário ficarão expostos. Para
esconder a senha digitada pelo usuário, podemos utilizar um novo tipo de input do html
chamado password:

<form action="/Login/Autentica" method="post">


<label for="login">Login:</label>
<input name="login" id="login" class="form-control" />

<label for="senha">Senha:</label>
<input name="senha" id="senha" class="form-control" type="password" />

<input type="submit" value="Logar" />


</form>

Os dados desse formulário serão enviados para a action Autentica do LoginController:

public ActionResult Autentica(String login, String senha)


{

Nessa action, precisamos verificar se as informações que foram enviadas pelo formulário
realmente existem dentro do banco de dados, para isso utilizaremos o método Busca do
UsuariosDAO. Esse método busca um usuário dado o login e a senha. Se as informações
estiverem corretas, o método devolve o Usuario do banco de dados, senão ele devolve a
referência nula:

public ActionResult Autentica(String login, String senha)


{
UsuariosDAO dao = new UsuariosDAO();
Usuario usuario = [Link](login, senha);
}

Se o usuario tiver uma referência válida, vamos armazená-lo na sessão do servidor e depois
redirecionar para a página inicial da aplicação (a lista de produtos), senão vamos enviar o usuário
de volta para a página de login da aplicação.

public ActionResult Autentica(String login, String senha)


{
UsuariosDAO dao = new UsuariosDAO();
Usuario usuario = [Link](login, senha);
if(usuario != null)
{
Session["usuarioLogado"] = usuario;
return RedirectToAction("Index", "Produto");
}
else
{
return RedirectToAction("Index");
}
}

Agora podemos testar o login na aplicação entrando na url /Login. No banco de dados do
projeto que foi importado no começo do curso temos um usuário chamado caelum com a senha
caelum que pode ser utilizado para o teste dessa lógica de login.

FILTRO PARA AUTORIZAR UTILIZADORES

Autorização através de filtros


Agora temos uma lógica de autenticação na aplicação, porém o usuário ainda consegue acessar
qualquer página mesmo não estando logado. Para resolvermos esse problema, na listagem de
produtos, por exemplo, precisamos verificar se o usuário está logado antes de mostrar a lista:

public class ProdutoController : Controller


{
public ActionResult Index()
{
object usuarioLogado = Session["usuarioLogado"];
if(usuarioLogado != null)
{
// lógica para mostrar a lista
}
else
{
return RedirectToAction("Index", "Login");
}
}
}

Mas também precisamos proteger as outras actions do ProdutoController, então essa lógica de
verificação do usuário logado terá que ser copiada para todas as actions do controller.

Para resolvermos esse problema, utilizaremos o filtro do [Link] MVC 5. Filtros são
componentes que conseguem executar lógicas antes e depois do código do controller. Para
criarmos um filtro, precisamos de uma classe que herda de ActionFilterAttribute do
namespace [Link], então no projeto criaremos uma nova pasta chamada Filtros e
dentro dessa pasta criaremos a classe AutorizacaoFilterAttribute:

public class AutorizacaoFilterAttribute : ActionFilterAttribute


{

}
Dentro de um filtro, quando queremos executar uma ação antes do código da action, precisamos
sobrescrever o método OnActionExecuting e para executar uma ação depois do código da
action, sobrescrevemos o OnActionExecuted. Em nosso caso, queremos verificar se o usuário
está logado antes da lógica do controller, então sobrescreveremos o OnActionExecuting:

public override void OnActionExecuting(ActionExecutingContext filterContext)


{

Dentro desse método, recebemos um argumento do tipo ActionExecutingContext, dentro


desse objeto podemos conseguir informações sobre a requisição que está sendo tratada
atualmente.

No código do OnActionExecuting, se o usuário estiver logado, queremos deixar a lógica do


controller executar normalmente, senão precisamos redirecionar o usuário para a página de login
da aplicação. Então precisamos inicialmente acessar a sessão do servidor para buscar o usuário
logado. Quando queremos acessar a sessão do servidor a partir do código do filtro, precisamos
ler a propriedade HttpContext do filterContext e dentro do HttpContext, podemos acessar a
Session do servidor:

public override void OnActionExecuting(ActionExecutingContext filterContext)


{
object usuarioLogado = [Link]["usuarioLogado"];
}

Nos filtros, quando queremos deixar o usuário executar a lógica do controller, não precisamos
fazer nada. Então precisamos tratar apenas o caso em que o usuário não está logado, nesse caso,
não queremos permitir a execução do código do controller e para isso, precisamos escrever na
propriedade Result do filterContext.

No caso em que o usuário não está logado, queremos escrever no Result um resultado fará um
redirect no navegador do usuário, porém dentro do filtro não podemos utilizar o método
RedirectToAction da mesma forma que fazíamos no controller, precisamos instanciar
diretamente o objeto devolvido pelo RedirectToAction que é o RedirectToRouteResult.

Dentro do RedirectToRouteResult, precisamos passar o nome do controller e da action para


onde queremos enviar o usuário. Essas informações são enviadas dentro de um objeto do tipo
RouteValueDictionary e dentro desse dicionário precisamos passar as informações dentro de
um objeto anônimo do C#:

[Link] = new RedirectToRouteresult(


new RouteValueDictionary(
new { action="Index", controller="Login" }));

E todo esse código ficará dentro de um if que verifica se o usuário está logado:

public override void OnActionExecuting(ActionExecutingContext filterContext)


{
object usuarioLogado = [Link]["usuarioLogado"];
if(usuarioLogado == null)
{
[Link] = new RedirectToRouteResult(
new RouteValueDictionary(
new { action = "Index", controller = "Login" }));
}
}

Agora que o código do filtro está pronto, precisamos avisar ao [Link] MVC que ele será
utilizado na action Index do ProdutoController, para isso precisamos anotar essa action com a
classe do filtro que foi criado:

public class ProdutoController : Controller


{
[AutorizacaoFilterAttribute]
public ActionResult Index()
{
// código para a lista de produtos
}
}

Mas como foi dito anteriormente no curso, quando usamos uma classe como anotação não
precisamos colocar o sufixo Attribute no nome da anotação:

public class ProdutoController : Controller


{
[AutorizacaoFilter]
public ActionResult Index()
{
// código para a lista de produtos
}
}

Mas se quisermos proteger todas as actions desse controller, teríamos que colocar a anotação em
todos os métodos, ao invés disso, podemos colocar a anotação sobre a declaração da classe
ProdutoController:

[AutorizacaoFilter]
public class ProdutoController : Controller
{
public ActionResult Index()
{
// código para a lista de produtos
}
}

Quando o filtro é colocado sobre um controller, ele será executado antes e depois de cada uma
das actions desse controller.
Também podemos falar para o [Link] MVC que um determinado filtro precisa ser executado
em toda requisição que chega na aplicação. Quando queremos registrar um filtro global na
aplicação, precisamos abrir um arquivo chamado [Link] do projeto, é nele que fazemos as
configurações programáticas globais de uma aplicação [Link] MVC.

Dentro do método Application_Start do [Link], precisamos adicionar a instância do


filtro dentro da coleção de filtros globais da aplicação o [Link].

protected void Application_Start()


{
[Link](new AutorizacaoFilterAttribute());
// resto do código continua igual
}

Veja que se colocarmos muitas configurações globais dentro do [Link], o arquivo acaba
ficando grande e bagunçado, para resolver esse problema, geralmente colocamos as
configurações dentro de classes separadas e depois simplesmente chamamos a classe de
configuração dentro do [Link]. A classe que é normalmente utilizada para registrar filtros
globais é uma classe chamada FilterConfig que é usualmente criada dentro da pasta
App_Start da aplicação.

Dentro dessa classe, os filtros serão registrados dentro de um método chamado


RegisterGlobalFilters que recebe um argumento do tipo GlobalFilterCollection, o
mesmo tipo do [Link]:

public class FilterConfig


{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
[Link](new AutorizacaoFilterAttribute());
}
}

E agora podemos chamar o RegisterGlobalFilters dentro do Application_Start:

protected void Application_Start()


{
[Link]([Link]);
// resto do código
}

Agora o filtro será executado para toda requisição que chega ao servidor.

Cross Site Request Forgery


Até agora, nossas actions tratam todas as requisições feitas para o servidor, porém imagine que
sua aplicação tenha uma funcionalidade que permite recuperar senhas perdidas por e-mail:
public ActionResult RecuperaSenha(String email)
{
UsuarioDao dao = new UsuarioDao();
Usuario usuario = [Link](email);
GeraNovaSenha(usuario);
[Link](usuario);
EnviaNovaSenhaParaOEmailDoUsuario(usuario);
return View();
}

E um formulario que atualiza o e-mail atual do usuário logado:

<form action="seu_site/Usuario/AtualizaEmail" method="post">


<input name="novoEmail" />
<input type="submit" />
</form>

Esse formulário será enviado para o método AtualizaEmail do UsuarioController, que


simplesmente muda o e-mail cadastrado do usuário logado.

Agora suponha que um usuário se autentique no seu site e esqueça de fazer o logout. Nesse caso,
para o servidor da aplicação, o usuário continuará logado. Agora esse usuário entra em um site
malicioso que envia automaticamente o seguinte formulário html:

<form action="seu_site/Usuario/AtualizaEmail" method="post">


<input name="novoEmail" value="[Link]@[Link]"/>
</form>

Como o usuário continua logado em nossa aplicação, a requisição será processada normalmente
pelo servidor, que irá trocar o e-mail cadastrado do usuário para [Link]@[Link] e,
utilizando a funcionalidade de recuperação de senhas, o hacker poderá tomar o controle da conta
do usuário.

O problema ilustrado acima é conhecido como cross site request forgery (csrf). A solução dada
pelo [Link] MVC é colocar um token (uma chave secreta que só o browser e o servidor
conheçam naquele momento) entre os dados enviados pelo formulário. Esse token é conhecido
como csrf token e pode ser gerado pelo método AntiForgeryToken do HtmlHelper. Vamos
modificar nosso formulário de cadastro de produtos para utilizar o csrf token.

<form action="/Produto/Adiciona">
@[Link]()
<label>Nome: <input name="[Link]" /></label>
@[Link]("[Link]")
<label>Preco: <input name="[Link]" /></label>
@[Link]("[Link]")
<label>Quantidade: <input name="[Link]" /></label>
@[Link]("[Link]")
<label>Descricao: <input name="[Link]" /></label>
@[Link]("[Link]")
<label>
Categoria:
<select name="[Link]">
@foreach(var categoria in Model) {
<option value="@[Link]">@[Link]</option>
}
</select>
@[Link]("[Link]")
</label>
<input type="submit" />
</form>

Porém, apenas adicionar o token ao formulário não resolve o problema. Devemos agora fazer
com que o servidor verifique se o token enviado é válido. Para isso utilizaremos um filtro
definido pelo [Link] MVC, o ValidateAntiForgeryTokenAttribute. Para utilizá-lo,
devemos apenas anotar nossa action. Vamos modificar o método Adiciona do
ProdutoController para verificar o token:

class ProdutoController : Controller


{
// outras actions do controller

[ValidateAntiForgeryToken]
public ActionResult Adiciona(Produto produto)
{
// implementação do adiciona
}
}

Agora apenas requisições que enviem um token com valor correto serão tratadas pela action.

Você também pode gostar