Treinamento Asp.net MVC (S2B) PUC Minas

Post on 19-Mar-2017

137 views 7 download

Transcript of Treinamento Asp.net MVC (S2B) PUC Minas

MicrosoftStudents to BusinessDesenvolvimento ASP.Net MVC – 2ª Fase

Professor: Herivelton Martins (MCP)heriveltonm@algartech.comheriveltonmartins@hotmail.com

Visão Geral sobre o Visual Studio 2015

Introdução do ASP.Net MVC

Banco de Dados

ADO.Net

Entity Framework e MVC

Camada de Apresentação

Camada de Controle

Validações \ Sessões \ Tratamento de Erros

Projeto Final

2ª Fase (Agenda)

Visão Geral do Visual Studio 2015

É uma ferramenta de desenvolvimento completa que atende praticamente a todas as plataformas de desenvolvimento, como:• Web• Windows/Client• Dispositivos Móveis (Windows Phone, Android e iOS)• Computação em Nuvem• Internet das Coisas - IoT

O que é o Visual Studio 2015?

Hoje o Visual Studio 2015 possui 3 versões:

• Visual Studio Enterprise• Visual Studio Professional• Visual Studio Community Edition

A versão Community é totalmente gratuita e permite também a criação de todo tipode aplicação.

O Visual Studio pode também ser utilizado na versão Português

Faça o download no site: http://www.visualstudio.com/

Visual Studio 2015

O Visual Studio suporta uma infinidade de linguagens, mas nativamente, quando você instala a ferramenta, nós temos:

• C#• Visual Basic• Visual C++• Visual F#

Visual Studio - Linguagens

Este é um exemplo de código escrito com C#

Visual Studio – C#

Podemos desenvolver para web com Visual Studio, através de templates, que são modelos de aplicações utilizáveis e que agilizam o processo de desenvolvimento.

Hoje podemos criar aplicações:• WebForms• Asp.Net MVC• Asp.Net WebAPI• HTML / CSS / Javascript

Visual Studio – Desenvolvimento Web

Podemos desenvolver aplicações para Windows Client, ou seja, programas que irão funcionar no desktop, como por exemplo o Word; Para isto o Visual Studio nos oferece algumas maneiras de criar este tipo de aplicação:

• Windows Forms – formato mais tradicional de aplicações• WPF – permite criarmos interfaces mais ricas e interessantes• Universal App – usa WPF permite criar aplicações que irão

funcionar em todos os Dispositivos com Windows: Desktop,Telefone, Xbox, IoT, etc.

Visual Studio – Windows

Temos diversas ferramentas integradas ao Visual Studio, que auxiliam o desenvolvimento e tornam o desenvolvedor muito mais produtivo, por exemplo:

• Nuvem do Microsoft Azure totalmente integrado• Gerenciamento do Ciclo de Vida das Aplicações (ALM) com Visual

Studio Online e Team Foundation Server• Integração com GitHub, um dos maiores portais de código open

source• Gerenciamento de Banco de Dados SQL integrado• Emuladores de dispositivos como Windows Phone e até mesmo

Android• Publicação de aplicações web diretamente na nuvem

Visual Studio – Ferramentas

ASP.Net Visão em Alto Nível

Visual Studio – Framework .Net

Universal Windows Platform (UWP)Multiplataforma

Visual Studio – Ferramentas - SQL

Integração com SQL Server

Visual Studio – Ferramentas – Emulador AndroidEmulador Android Nativo

Visual C#

Visual C#

Linguagem moderna de alto nível implementada pela Microsoft para ser usada no Microsoft VisualStudio

Multi-propósito• Apps• Desktop• Embarcados• Web

Foco em simplicidade, orientação à objetos e poder computacional

Atualmente na versão 6, onde o compilador foi totalmente reescrito (em C#) abriu muitas possibilidades, como por exemplo escrever analisadores estáticos de código

Visual C#

A linguagem (e o .NET Framework) suportam uma variedade de conceitos e estilos de programação

• Orientação a Objetos• Tarefas Assíncronas• Atributos e Propriedades• Coleções de Objetos• Iteradores• Reflexão e Binding• Threading• Serialização

Tipos de Dados

Tipos de Dados

C# é uma linguagem fortemente “tipada” - isso significa que os métodos, variáveis e constantesprecisam ser descritas através de um tipo de dado antes de serem utilizadas

Cada tipo de dado possui características como• Tamanho de Armazenamento• Valores Iniciais• Valores Máximos e Mínimos• Operações

Tipos de Dados

Tipos Integrais (Inteiros)

TIpo Tamanho Menor Valor Maior Valor Valor Inicial Classificação

sbyte 8 bits com sinal ‐128 127 0 Valor

Byte 8 bits sem sinal 0 255 0 Valor

char 16 bits U + 0000 para FFFF + U ‘\0’ Valor

short 16 bits com sinal ‐32.768 a 32.767 0 Valor

ushort 16 bits sem sinal 0 65.535 0 Valor

int 32 bits com sinal ‐2.147.483.648 2.147.483.647 0 Valor

uint 32 bits sem sinal 0 4,294,967,295 0 Valor

Long 64 bits com sinal ‐9,223,372,036,854,775,808 9.223.372.036.854.775.807 0L Valor

ulong 64 bits sem sinal 0 18,446,744,073,709,551,615 0 Valor

Tipos de Dados

Ponto Flutuante

Tipo Tamanho Menor Valor Maior Valor Padrão Classificação

float 32 bits 0.0F 0.0F Valor

double 64 bits 0.0D 0.0D Valor

Cadeia de CaracteresTipo Tamanho Valor Padrão Classificação

String até 2 GB (depende da plataforma e do hardware) null Referência

Exercício

1. Criei uma Solution no Visual Studio 2. Dentro de uma classe defina as seguintes variráveis:• Id: Integer• Nome: String• Preco: DecimalVerifique a propriedades.

Introdução ao ASP.Net MVC

Visual Studio – Asp.Net MVC

No modelo Asp.Net MVC a aplicação é dividida em 3 partes:• Model – que contém os dados, por exemplo o acesso a um banco

de dados• View – é a parte que o usuário verá no browser. No Visual Studio

trabalhamos com a engine Razor, que é um misto de C# com HTML• Controller – faz a ligação entre o modelo e a view, executando

ações do usuário

ASP.Net MVC Web Project Template

Visual Studio – Desenvolvimento Web

Exemplo de Código MVC - Controller

Visual Studio – Desenvolvimento Web

Exemplo de Código MVC - View

Arquivos de Projeto e Configuração

Exercícios• Crie um projeto Asp.Net MVC e observe a estrutura de arquivos e pastas

Banco de Dados

SQL Server

Faça o download da versão SQL Server Express em:

https://www.microsoft.com/pt-br/download/details.aspx?id=42299

SQL Server

O Visual Studio 2015 permite você criar um SQL Server Database:

* Arquivo de Banco de Dados Local

DataBases

Criando uma nova Base de Dados: DBLojaVirtual

Criando a Base de Dados DBLojaVirtual

Base de Dados Criada

TabelasCrie as seguintes TABELAS no banco de dados DBLojaVirtual:

Categorias ProdutosColuna Tipo Coluna TipoCategoriaID (PK) Integer ProdutoID (PK) IntegerNome Varchar(100) Nome Varchar(100)

Descricao Varchar(255)Preco Decimal(10,2)CatogoriaID (FK) Integer

Adicionando novas tabelas

Tabela: CategoriasCrie a tabela: Categorias

Tabela: ProdutosCrie a tabela: Produtos

CRUDInserindo alguns registros na tabela de categoria e produtos

Consultando os dados

Atualizando os Dados

Exercícios1. Crie um novo projeto Asp.Net MVC chamado “Livraria”2. Crie um Banco de Dados chamado “DBLivraria”3. Crie duas Tabelas: • Editora• Campos(EditoraID, Nome) Livro Campos (LivroId, Titulo, Autor, Editora_EditoraId*) *FK• Realize a Inserção, Consulta, Atualização e Remoção de Registros destas Tabelas

ADO.NET

ADO.NET

ADO.NET (ActiveX Data Objects) consiste num conjunto de classes definidas pela . NET framework (localizadas no namespace System.Data) que pode ser utilizado para aceder aos dados armazenados numa base de dados remota.

Drivers

Geralmente, protocolos binários são mais apropriados para reduzir o tamanho das mensagens e consequentementediminuir a carga do canal de comunicação. Por isso, osSGDBs utilizam protocolos binários.

Para resolver esse problema e facilitar o desenvolvimento das aplicações, as empresas proprietá-rias dos SGDBs, normalmente, desenvolvem e distribuem drivers de conexão. Um driver de conexão atua como um intermediário entre as aplicações e os SGDBs.

ODBC

Para facilitar o trabalho do desenvolvedor da aplicação, a Microsoft® definiu uma especificação chamada ODBC(Open Database Connectivity) para padronizar a interface dos drivers de conexão. Assim, quando uma empresa proprietária de um banco de dados pretende desenvolver um driver, ela segue essa especificação com o intuito de popularizá-lo.

Criando uma conexão ODBC

string string De Conexao = @" driver ={ SQL Server };server = LOCALHOST\SQLEXPRESS; database = DBLojaVirtual;uid = sa;pwd=sa;";

string string De Conexao = @"driver ={ SQL Server };server = LOCALHOST\SQLEXPRESS; database = DBLojaVirtual;Integrated; Security=True";

String de Conexão

OBDC ConnectionOdbcConnection: Utiliza a classe System.Data.Odbc.OdbcConnection do .NET Framework

Odbc Connection conexao = new Odbc Connection ( string De Conexao );

Inserindo registros via ODBCInserir um novo registro na categoria câmera

string texto Do Comando = @" INSERT INTO Categorias ( Nome)VALUES (‘Câmeras’);";

Odbc Command comando = new Odbc Command ( texto Do Comando , conexao );

conexao . Open ();comando . Execute Non Query ();

Mais Sobre

O caractere “@” antes de um valor literal do tipo string indica que os caracteres dentro da string não devem ser processados como caracteres especiais.

Encerrando conexão ODBCFinalizando uma conexão ODBC

Importante

A mesma conexão pode ser reaproveitada para executar várias operações. Quando não houver mais operações a serem executadas, devemos finalizar a conexão ODBC através

do método Close(). Finalizar as conexões ODBC que não são mais necessárias é importante pois libera recursos no SGBD.

conexao.close();

OU

Using (OdbcConnection conexao = new OdbcConnection(stringConexao)){

// Utiliza a conexão}

Criando uma conexão ODBC completaInserindo um registro via ODBC

SQL Injection X Parameters

A implementação da inserção de registros feita anteriormente possui uma falha grave. Os dados obtidos do usuário através do teclado não são tratados antes de serem enviados para o SGDB.Solução:

OdbcDataReader

Exercícios1. Utilize projeto Asp.Net Empty (Vazio) chamado “Livraria”2. Crie uma classe para realizar Inserção, Consulta via ODBC:• Editora Campos(EditoraID, Nome) Livro Campos (LivroId, Titulo, Autor, Editora_EditoraId*) *FK

Entity Framework

Entity FrameworkUtilizando conexões ODBC para fazer uma aplicação C# interagir com os SGDBs. As consultas são definidas com a linguagem SQL. A sintaxe dessa linguagem é diferenteem cada SGDB.

SELECT TOP 100 * FROM produtos ORDER BY autor ASC

SELECT * FROM ( SELECTROW_NUMBER() OVER (ORDER BY nome ASC) AS rownumber, ProdutoId, nome, descricaoFROM produtos) WHERE rownumber <= 100

Sintaxe SQL Server

Sintaxe Oracle (PL SQL)

Orientação a Objetos VS Modelo Relacional

Outro problema na comunicação entre uma aplicação C# e um SGDB é o conflito de paradigmas. Os SGDBs são organizados seguindo o modelo relacional. Por outro lado, as aplicações C# utilizam o modelo orientado a objetos.

Ferramentas ORM

Para facilitar a comunicação entre aplicações C# que seguem o modelo orientado a objetos e os SGDBs que seguem o modelo relacional, podemos utilizar ferramentas que automatizam a transição de dados entre as aplicações e os SGDBs. Essas ferramentas são conhecidas como ferramentas ORM (Object Relational Mapper).

As principais ferra- mentas ORM para C# utilizadas no mercado são o Entity Framework e o NHibernate. Nessecurso, utilizaremos o Entity Framework 5.0.0.

Como funciona o Entity Framework?

DB

ORM

Entities in Code

Instalando o Entity Framework

A instalação do Entity Framework em um projeto do Visual Studio 2012 podeser facilmente realizada através do Package Manager Console. Veja o comando de instalação a seguir.

PM > Install - Package Entity Framework - Version 5.0.0Terminal: Package Manager Console

Mais SobreO Entity Framework também pode ser instalado através do Manage NuGet Packages. Basicamente, o Manage NuGet Packages é a alternativa visual ao Package ManagerConsole.

Instalando o Entity Framework

1

2

Configuração

O Entity Framework é fortemente baseado no conceito de “Convenção sobre Configuração”. Dessa forma, nenhuma configuração é necessária a não ser que seja necessário alterar o comportamento padrão.

<? xml version =" 1.0 " ?>< configuration >< connection Strings ><add name="DefaultConnection"

connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\DBLoja.mdf;Initial Catalog=DBLoja;Integrated Security=True" providerName="System.Data.SqlClient" />

</ connection Strings ></ configuration >

XML do Arquivo de Configuração Web.Config

Convenções de Mapeamento

Por padrão, no Entity Framework, o mapeamento das entidades segue as regras do Code First.

Classe (Model): Categoria.cs

Classe (Model): Produto.cs

Registrar entidades no DBContextAs entidades devem ser “registradas” em um DbContext. Para registrar uma entidade, basta definir uma propriedade do tipo DbSet. Veja o exemplo abaixo.

Classe: LojaVirtualDBContext.cs

De acordo com as convenções do Code First, as entidades Categoria e Produto serão mapeadas para tabelas chamadas Categorias e Produtos respectivamente.

Além disso, por padrão, essas tabelas serão criadas em uma base de dados chamada EF.LojaVirtualDBContext.Esse nome corresponde ao full qualified name da classe LojaVirtualDBContext

Desabilitar a pluralização aos Nomes de Tabelas

Para desabilitar a pluralização aplicada no nome das tabelas, é necessário sobrescrever o método OnModelCreating() da classe DbContext.

LojaVirtualDBContext.cs

Personalizando a Base de Dados no DBContext

Podemos modificar o nome da base de dados escolhido por padrão. Para isso, basta adicionar um construtor na classe que define o DbContextsemelhante ao mostrado no código abaixo.

LojaVirtualDBContext.cs

Primary KeyO Entity Framework assumirá como identificador de uma entidade, a propriedade cujo nome seja ID ou EntidadeID escrito com letras maiúsculas e/ou minúsculas. Essa propriedade será mapeada para uma coluna definida no banco de dados como chave primária da tabela correspondente a entidade.

Classe (Model): Categoria.cs

Classe (Model): Produto.cs

Complex TypesConsidere a seguinte entidade.

Contato.cs

Complex Types

Do ponto de vista da modelagem orientada a objetos, deveríamos refatorar essa classe separando as propriedades relacionadas aos endereços de um contato.

Contato.cs

Endereco.cs

Complex TypeComo nenhuma propriedade da classe Endereco se enquadra nas convenções de Primary Key e supondo que nenhuma propriedade tenha sido mapeada explicitamente para uma coluna definida como chave primária, o Entity Framework assumirá que essa classe é um Complex Type. Além disso, um Complex Type não pode referenciar uma entidade através de uma propriedade.As classes Contato e Endereco serão mapeadas para uma única tabela chamada Contatoes. Essa tabela possuirá a estrutura mostrada na imagem a seguir.

Mapeamento das classes Contato e Endereco

Mapeamento dos Relacionamentos

Classe (Model): Categoria.cs

Classe (Model): Produto.cs

As mesmas tabelas seriam obtidas se o relacionamento fosse definido na entidade Categoria ao invés de ser definido na entidade Produto.

Essas duas entidades serão mapeadas para as tabelas Produtos e Categorias. Na tabela Produtos, será adicionada uma chave estrangeira chamada Categoria_CategoriaIDreferenciado a chave primária da tabela Categoria. Observe na imagem abaixo a estrutura das tabelas.

Tabelas DBLojaVirtual

Type DiscoveryQuando duas entidades estão relacionadas, não é necessário que ambas sejam “registradas” no DbContext. Apenas a entidade principal necessita ser registrada.Exemplo: Categorias

Se as duas entidades forem registradas, tanto os Produtos quanto as Categorias podemser obtidos diretamente pelo DbContext.

Exercícios1. Crie um novo projeto Asp.Net MVC chamado “Livraria”2. Crie duas Entidades: • Editora Campos(EditoraID, Nome)• Livro Campos (LivroId, Titulo, Autor, Editora_EditoraId*) *FK Realize a criação do DBContext e demais itens semelhante a aula anterior.

Data Annotations

ValidationAttributes: Derivam da classe ValidationAttribute e são usados para garantir regras de validação que podem ser aplicadas a classes ou membros.

DisplayAttributes: Usados para especificar como os dados de uma classe ou membro são exibidos.

Data Modeling Attributes: Usados para especificar a estrutura e o relacionamento entre classes de dados (muito utilizados no EntityFramework Code First).

Data Annotations

Podemos utilizar anotações para sobrescrever as convenções de mapeamento. A seguir apresentaremos as principais anotações.

Table e Column

Aluno.cs

Tabela e colunas geradas no Banco de Dados

Data AnnotationsA anotação Column também permite a escolha do tipo da coluna correspondente à propriedade anotada.

Coluna personalizada usando Data Annotations

Produto.cs

DatabaseGeneratedPor padrão, quando a propriedade correspondente à chave primária de uma tabela é numérica, os valores dessa chave serão gerados pelo banco de dados. Podemos alterar esse comportamento através da anotação DatabaseGenerated.

Aluno.cs

KeyConsidere a seguinte classe.Nenhuma propriedade se enquadra nas convenções de nomenclatura de chave primária. Con- tudo, é possível definir explicitamente, qual propriedade será mapeada como chaveprimária através da anotação Key.

Aluno.cs

Show Potential Fixes: Sugere inclusão da referênciaColuna criada como Identity no banco de dados

RequiredUma propriedade pode ser definida explicitamente como obrigatória através da anotação Requi- red. No banco de dados, as colunas correspondentes às propriedades obrigatórias serão definidas com a opção not null.

Aluno.cs

MaxLength e MinLengthDefinindo a quantidade mínima e máxima de caracteres de uma propriedade

Aluno.cs

Tabela a ser gerada com mapeamento do tamanho

NotMapped

Observe que a propriedade Idade pode ser calculada a partir da propriedade DataDeNascimento. Portanto, não é necessário armazenar o valor da idade no banco de dados.

Aluno.cs

Tabela Sem o campo não mapeado

InversePropertyConsidere as seguintes entidades.

Pessoa.cs

Livro.cs

Nesse caso, como o Entity Framework não consegue combinar as propriedades das duas entidades para estabelecer dois relacionamentos bidirecionais, ele criará no banco de dados quatro chaves estrangeiras, uma para cada propriedade de navegação das entidades Pessoa e Livro.

Relacionamento não combinados

InversePropertyPara agrupar as propriedades de navegação das entidades Pessoa e Livro, devemos utilizar a anotação InverseProperty. Observe o código a seguir.

Pessoa.cs

Livro.cs

Inverse Property (Agrupando)

Relacionamentos combinados com InverseProperty

Exercícios

DBContextAs instâncias das entidades de uma aplicação que utiliza o Entity Framework são administradas por objetos do tipo DbContext. Esses objetos são responsáveis pelas operações de inserção, remoção, alteração e consulta. A seguir, mostraremos o funcionamento básico de um DbContext.

Utilizando um DBContext dentro de um bloco Using

Persistindo

Para indicar que determinado objeto deve ser persistido no banco de dados, devemos utilizar o método System.Data.Entity.DbSet.Add(), passando o objeto em questão como parâmetro. O método Add() adiciona o objeto ao contexto com o estado Added.

Para armazenar de fato as informações de um objeto no banco de dados, utilizamos o método SaveChanges() do DbContext. Todos os objetos do contexto que estejam no estado Added são inseridos no banco de dados quando o método SaveChanges() é chamado.

Persistindo (Cont.)

Persistindo um objeto

Buscando

Para obter um objeto que contenha informações do banco de dados, basta utilizar o método Find() do DbSet. Devemos passar o identificador do objeto que desejamos recuperar como parâ-metro para esse método.

Buscando uma categoria com o identificador 1

RemovendoPara indicar que determinado objeto deve ser removido, basta utilizar o método System.Data.Entity.DbSet.Remove(). Esse método marca o objeto para ser removido do banco de dados, colocando-o no estado Deleted.Quando o método SaveChanges() é chamado, todas os objetos no estado Deleted são removidos do banco de dados.

Remove o registro de Categoria

AtualizandoPara alterar os dados do registro correspondente a um objeto, basta modificar as suas propriedades. Quando as propriedades de um objeto do contexto são alteradas, o estado Modified é associado a este objeto. Objetos no estado Modified são atualizados no banco de dados quando o método SaveChanges() é chamado.

Alterando o nome de uma categoria

ListandoPara obter uma listagem com todos os objetos referentes aos registros de uma tabela, podemos utilizar a Language Integrated Query (LINQ), que nos permite escrever consultas dentro do código C#.

Utilizando LINQ para fazer uma consulta

Exercícios1. Crie um novo projeto Asp.Net MVC chamado “Livraria”2. Crie uma classe nova chamada ManterAlunos.cs3. Crie métodos de consulta, inserção, atualização e exclusão de Livros Livros: Campos (LivroId, Titulo, Autor, Editora_EditoraId*) *FK

Repositórios

As classes DbContext e DbSet do Entity Framework oferecem recursos suficientes para que os objetos do domínio sejam persistidos, recuperados, alterados e removidos do banco de dados. Porém, em aplicações com alta complexidade e grande quantidade de código, “espalhar” as chamadas aos métodos do DbContext e DbSet pode gerar dificuldades na manutenção e no entendimento do sistema.

Repositórios (Cont.)

Para melhorar a organização das nossas aplicações, diminuindo o custo de manutenção e aumentando a legibilidade do código, podemos aplicar o padrão Repository do DDD (Domain Driven Design).

Conceitualmente, um repositório representa o conjunto de todos os objetos de um determinado tipo. Ele deve oferecer métodos para administrar seus elementos.

Repositórios (Cont.)

Os repositórios podem trabalhar com objetos prontos na memória ou reconstruí-los com dados obtidos de um banco de dados. O acesso ao banco de dados pode ser realizado através de uma ferramenta ORM como o Entity Framework.

Repositório (Cont.) Exemplo

CategoriaRepository.cs

Code First Migrations

O Entity Framework Code First da Microsoft tem uma funcionalidade que permite controlar as mudanças no banco de dados que serão realizadas de acordo com as alterações na camada de mo- delo da aplicação. Essa funcionalidade é chamada de Code First Migrations.

Inclua o código abaixo na inicialização da aplicação

Code First Migrations (Geração de objetos)

Após a execução do projeto, teremos a seguinte tabela e banco de dados.

Tabela de Categorias

* Altere a classe Produto.cs, incluindo um novo campo chamado “Quantidade” e execute a aplicação novamente

Code First Migrations (Habilitando)Com a alteração na classe Categoria, um exceção é gerada ao executar o projeto.

Para resolver esse problema, o banco de dados precisa ser atualizado. Para fazer essa atualização, o Entity Framework recomenda a utilização da ferramenta Code FirstMigrations.

O primeiro passo para utilizar Code First Migrations é habilitá-lo e adicioná-lo ao projeto através do Package Manager Console.

Code First Migrations

O comando Enable-Migrations adiciona uma pasta chamada Migrations no projeto. Esta pasta contém dois arquivos.

• A classe Configuration permite definir o comportamento do Code First Migrations para o nosso contexto.• A classe parcial InitialCreate define a primeira versão das tabelas do banco de dados.

Code First Migrations (Comandos)

O Code First Migration tem dois comandos fundamentais.

• Add-Migration que gera o código necessário para atualizar o banco de dados de acordo com as alterações nas classes de modelo.• Update-Database aplica as alterações pendentes no banco de dados.

Execute o comando abaixo no Nuget:PM> Add-Migration AddQuantidadeToProduto

Code First Migrations

A classe que define a migração é adicionada à pasta Migrations.

Para atualizar o banco de dados com as alterações definidas na Migration, devemos executar o comando Update-Database.PM> Update-Database

Uma nova coluna é adicionada à tabela Produtos no banco de dados.

Exercícios

Camada de Apresentação

Camada de Apresentação

A camada de apresentação é responsável por gerar as páginas de uma aplicação web. Os dados apresentados em uma página web são definidos na camada de modelo. A camada de controle recupera os dados da camada de modelo e os envia para a camada de apresentação. Basicamente, a camada de apresentação definirá como esses dados serão apresentados para os usuários da aplicação.

Exemplo de uma aplicação Web

Veremos a seguir um exemplo de uma simples aplicação web em ASP.NET MVC 4. Essa aplicação possuirá uma página principal que deverá exibir o seu número de visualização.

Primeiramente, criaremos um controlador para gerenciar o número de visualização da página principal. Os controladores são definidos por classes que derivam da classe Controller.

Exemplo de uma aplicação Web

Os nomes dos controladores devem terminar com a palavra Controller. Além disso, eles devem ser definidos na pasta Controllers da aplicação. Considere a classe LojaVirtualControllerdefinida abaixo.

LojaVirtualController.cs

Exemplo de aplicação Web

O método Index() será chamado toda vez que a urlhttp://<IP_SERVIDOR>:<PORTA_APP>/LojaVirtual/Index for requisitada por um navegador. Note que essa url é formada pelo nome do controlador (nome da classe que define o controlador sem o sufixo Controller) seguido pelo nome do método.

Para indicar que o fluxo de execução deve seguir para a camadade apresentação, o método Index() invoca o método View() e devolve a resposta obtida

Exemplo de uma aplicação Web

Na camada de apresentação, vamos adicionar a página associada ao método Index(). Para isso, criaremos um arquivo chamado Index.cshtml na pasta Views\LojaVirtual\ da aplicação com o conteúdo abaixo.

Index.cshtml

Para acessar a ViewBag, devemos utilizar o caractere @, como no código acima.

Integração com Entity Framework

A integração entre Entity Framework e ASP.NET MVC 4 é realizada de maneira extremamente simples. No Visual Studio 2015, ao criar um projeto ASP.NET MVC 4 do tipo Basic, a biblioteca do Entity Framework 5 é adicionada automaticamente.

As configurações padrões do Entity Framework podem ser alteradas através do arquivo Web.config. Por fim, bastaria implementar as entidades e mapeá-las como visto nos Capítulos anteriores

Scaffold

O Visual Studio 2015 é capaz de gerar telas e controladores para as operações de inserção, leitura, alteração e remoção (CRUD) a partir de uma entidade de um projeto ASP.NET MVC 5. Os controladores gerados podem utilizar as funcionalidades do Entity Framework para interagir com o banco de dados.

ScaffoldGerando a classe Controller

Gerando o Scaffold

ScaffoldAdicionando o Controller

Gerando o Scaffold via Controller

Scaffold

Gerando a Controller através de uma classe Model

Adicionando o Controller usando Scaffold

Scaffold

Views Geradas automaticamente pelo Scaffold

Scaffold das Views gerado

Para testar, acesse o endereço:http://localhost:<PORTA_APP>/Produto/Index

Exercícios

• Gere o scaffold da classe Model Categoria• Execute a aplicação• Acesse a página e verifique como está sendo apresentada

Razor e ASPX

Até a segunda versão do ASP.NET MVC, as telas (ou páginas) de uma aplicação web eram de- senvolvidas em ASPX. A partir da terceira versão desse framework, podemos usar a linguagem Razor para construir essas telas.

Razor @{ ...}

Aspx <% %>

@{string nome = “Bill Gate”;

}

<p> Nome: @nome </p>

<%string nome = “Bill Gate”;

%>

<p> Nome: <%=nome%> </p>

Condicionais (if e else)Podemos utilizar os comandos de controle de fluxo if e else. Veja os exemplos abaixo.

@* Comentários *@@if ( nome == “Bill Gates” ){<p> Homem Mais rico do Mundo!</ p>}else{<p> Continue trabalhando .</ p>}<! -- ou -->@{

string nome = “Bill Gates”;if( nome == “Bill Gates” ){<p> Homem Mais Rico do Mundo !</ p>}else{<p> Continue trabalhando .</ p>}

}

<% -- Comentários -- %><% if ( nome == “Bill Gates” ){%>

<p> Homem Mais rico do Mundo!</ p><%}else{%>

<p> Continue trabalhando .</ p><% } %>

Código da página em Razor

Código da página em ASPX

• Mesma regra para laços e outros operadores condicionais. Exemplo: for... While..

Exercícios de Fixação

• Crie uma página Web utilizando Razor que imprima um laço (de 1 a 10) com números Randômicos na tela.

• Utilize o método Random() para gerar os números aleatórios na camada Controller

ViewBag e Strogly Typed Views

A ViewBag é utilizada para transmitir dados da camada de controle para a camada de apresentação. Para adicionar um item à propriedade ViewBag, devemos definir uma chave para esse item. Veja o código abaixo.

ViewBag.HoraDoServidor = DateTime.Now.ToShortTimeString ();

Adicionando a ViewBag na classe do Controller

<p> A hora do servidor é @ViewBag.HoraDoServidor </p>

Acessando a ViewBag na classe do View

Desvantagem: não é possível garantir a existência dessas chaves em tempo de compilação

Strongly typed viewsDefine tipo do objeto que será transferido da camada de controle para a camada de apresentação.

public Action Result Acao (){

Produto produto = new Produto { Nome = “iPhone 5s", Descricao = “iPhone 5s 32Gb“, preco = 1799.00 }; return View ( produto );

}

Passando um objeto para a camada de apresentação

Acessando um objeto da view

@using LojaVirtual.Models@model Produto

<p> Nome: @model.nome </p>

• Agora o compilador conhece o tipo do objeto transmitido

Coleções de ObjetosVamos exibir uma coleção de objetos utilizando a classe ICollection

Adicione uma Action para listar os objetos na Controller ProdutoController.cs

Criando a View

Exibindo o resultado da Action na tela para o usuário.O objeto Produto foi repassado e listado na tabela.

Exercícios

• Crie um objeto do Tipo Produto na classe Controller de Produtos e passe este como objeto para ser acessado pela View

HTML Helpers

HTML Helpers

A função das páginas CSHTML é gerar hipertexto XHTML para enviar aos navegadores dos usuários. Os arquivos .cshtml misturam tags XHTML com scripts de servidor escritos em C#. Essa mistura pode prejudicar a legibilidade do código em alguns casos.

HTML Helpers

Para facilitar a manutenção do código das páginas CSHTML, o ASP.NET MVC oferece os chamados HTML Helpers.A função de um HTML Helper é encapsular um código XHTML.

<a href ="/Produto/Index/">Lista de produtos</ a>

@Html.ActionLink("Listade produtos", " Index ", “Produto")Código link usando HTML Helper

Código para Link CSHTML comum

ActionLink Helper

O helper ActionLink é utilizado para gerar os links das páginas de uma aplicação web. Esse helper pode ser utilizado de diversas maneiras. A forma mais simples de utilizá-lo é passar a ele dois parâmetros: o texto e a ação associados ao link desejado.

@Html.ActionLink(“Texto Exibido para o Usuário", “Action")Código link usando ActionLink. Usando o controlador Implícito

ActionLink Helper

Podemos definir o controlador desejado explicitamente. Para isso, é necessário passar um terceiro parâmetro para o método ActionLink.

@Html.ActionLink(“Texto Exibido para o Usuário", “Action“, “Controlador”)Código link usando ActionLink. Usando o controlador Explícito

@Html.ActionLink(“Texto Exibido para o Usuário", “Action“, new { Inicio = 0, Final = 10 } )

Acrescenta parâmetros de URL

Também podemos passar parâmetros.

Begin Form e EndForm Helpers

No ASP.NET MVC, há um conjunto de HTML Helpers para facilitar a criação de formulários nas páginas de uma aplicação web.Para criar um formulário, utilizamos o helper BeginForm. Para terminar um formulário, utiliza- mos o helperEndForm. Veja o exemplo a seguir.@{Html.BeginForm();}

<!-- elementos do formulário -->

@{Html.EndForm();}Utilizando o Helpers BeginForm e EndForm

BeginForm com using

Também podemos utilizar o comando using para garantir que os formulários sejam fechados.Nesse caso, não é necessário adicionar o helper EndForm. @usgin(Html.BeginForm()){<!-- elementos do formulário -->}

Utilizando o BeginForm com using

@usgin(Html.BeginForm(“Action”, “Controlador”)){<!-- elementos do formulário -->}

Utilizando BeginForm e definindo a Action e o Controlador

BeginForm

Por padrão, os formulários gerados pelo helper BeginForm fazemrequisições do tipo POST. Nesse caso, as ações associadas a essesformulários devem ser anotadas com HttpPost para indicar o tipode requisição HTTP esperado.

public class LojaVirtualDBController : Controller {

// POST : /LojaVirtual/Home[HttpPost]public ActionResultHome() {...return View ();}

}Anotando uma ação com HttpPost

Controles HTML Helper

@Html.CheckBox(“Ativo", false) CheckBox

@Html.TextBox(“Nome", “Digito o nome do produto“) TextBox

@Html.TextArea(“Descricao", “Digite a descrição completa do produto”) TextArea

@Html.RadioButton(“Estado", “MG”, true)@Html.RadioButton(“Estado", “SP”, false)@Html.RadioButton(“Estado", “RJ”, false)

RadioButton

@Html.Hidden(“CategoriaId", 1) Hidden

Controles HTML Helpers

@Html.Password(“Senha", “senha1234”) Password

Mais sobre:Os dados preenchidos nos elementos de um formulário são recuperados da ViewBag. Considere o código abaixo:

Caso exista uma chave chamada Nome na ViewBag, então o valor associado a essa chave será o valor inicial da caixa de texto. Podemos alterar esse comportamento, passando um segundo parâmetro para o helper TextBox, que será o valor inicial da caixa de texto. Observe o código a seguir.

Mais sobre:Os dados preenchidos nos elementos de um formulário são recuperados da ViewBag. Considere o código abaixo:

Caso exista uma chave chamada Nome na ViewBag, então o valor associado a essa chave será o valor inicial da caixa de texto. Podemos alterar esse comportamento, passando um segundo parâmetro para o helper TextBox, que será o valor inicial da caixa de texto. Observe o código a seguir.

@Html.TextBox(“Nome", “Nome inicial”)

@Html.TextBox(“Nome")

Strongly Typed Helpers

A forma que os HTML Helpers foram aplicados não permite que o compilador verifique a existência das propriedades associadas aos elementos dos formulários.

O código anterior supõe que o objeto recebido como parâmetro pela ação associada ao formulário onde o checkbox foi inserido possua uma propriedade chamada Aceito. Essa propriedade pode não existir. Contudo, nenhum erro de compilação seria gerado nesse caso.

@Html.CheckBox(“Ativo", false)

Strongly Typed Helpers

Para evitar esse tipo de problema, podemos utilizar a seguinte sintaxe em telas fortemente tipadas:

@model LojaVirtual.Models.Produto...@HTML.CheckBoxFor(c => c.Ativo)...

Com essa sintaxe, o compilador tem condições de verificar a existência das propriedades. Sendo assim, ele produzirá um erro de compilação se uma propriedade inexistente for utilizada.

Strongly Typed Helpers

@Html.CheckBoxFor(c => c.Ativo) CheckBox

@Html.TextBoxFor(c => c.Nome) TextBox

@Html.TextAreaFor(c => c.Descricao) TextArea

@Html.RadioButtonFor(x => x.Estado, “MG”)@Html.RadioButtonFor(x => x.Estado, “SP”)@Html.RadioButtonFor(x => x.Estado, “RJ”)

RadioButton

@Html.HiddenFor(e => e.CategoriaId) Hidden

Strongly Typed Helpers

@Html.PasswordFor(c => x.Senha) Password

Mais sobre:Os dados preenchidos nos elementos de um formulário de uma tela fortemente tipada são recuperados da propriedade Model. Considere o código abaixo:

Caso exista a propriedade Model.Nome, o valor inicial dessa caixa de texto será o valor dessa propriedade.

Mais sobre:Os dados preenchidos nos elementos de um formulário de uma tela fortemente tipada são recuperados da propriedade Model. Considere o código abaixo:

Caso exista a propriedade Model.Nome, o valor inicial dessa caixa de texto será o valor dessa propriedade.

@Html.TextBoxFor(c => c.Nome)

DropDownList Helper

Quando um produto é cadastrado, o usuário podem escolher a categoria deste produto. A categoria pode ser selecionada através de um DropDownList. Para criar um DropDownList, podemos utilizar o HTML Helper DropDownList.cshtmlO primeiro passo para utilizar o helper DropDownListé criar uma SelectList na camada de controle com as opções que o usuário poderá selecionar.

O segundo passo é adicionar o helper DropDownList na camada de apresentação.@Html.DropDownList(“Categorias”)

Utilizando o DropDownList na tela .cshtml

public class ProdutoController : Controller{

public ActionResult Create(){

List<Categoria> categorias = db.Categorias.ToList();ViewBag.Categorias = new SelectList(categorias, "CategoriaId", "Nome"); return View();

}}

EditorFor

Para cada propriedade da entidade Produto, utilizamos um helper para gerar o código HTML necessário para a entrada de dados. Por exemplo, no caso das propriedades Nome e Preco, utilizamos o HelperTextBox. Para a propriedade booleana Ativo, utilizamos o helper CheckBox

Usando o EditorFor

Observe que a escolha do helperdepende basicamente do tipo da propriedade associada a ele. Podemos deixar essa escolha a cargo do helper EditorFor. Para propriedades de tipo booleano, esse helper utilizará o CheckBox. Para propriedades do tipo string, esse helper utilizará o TextBox.

EditorForModel

Também temos o helperEditorForModel para construir um formulário completo com base nas propriedades de uma entidade. Esse helper seguirá a mesma abordagem do EditorFor. Ou seja, para cada propriedade do Model, ele utilizará o helper apropriado.

CSHTML: Página de Edição de Produto usando EditorForModel()

Personalizando o EditorForModel

Para personalizar o funcionamento do helper EditorFor e do EditorForModel, podemos utilizar algumas anotações. Veja o exemplo abaixo.

Exercícios

Layouts

É comum que as páginas de uma aplicação web possuam conteúdo em comum (por exemplo, um cabeçalho ou um rodapé). O conteúdo em comum pode ser replicado em todas as páginas através do CTRL+C e CTRL+V. Porém, essa não é uma boa abordagem, pois quando alguma alteração precisa ser realizada, todos os arquivos devem ser modificados. Também é comum que as páginas de uma aplicação web possuam um certo padrão visual. Daí surge o conceito de Layouts.

Layouts

Tudo que é comum a todas as páginas de um determinado grupo pode ser definido em um Layout. Dessa forma, qualquer alteração é facilmente realizada modificando-se apenas um arquivo.

Layout.cshtml

Layout

No layout definido no código anterior, utilizamos o método Render() das propriedades Styles e Scripts para adicionar conteúdo CSS e JavaScript. Na tag <title>, acrescentamos @ViewBag.Title, para que cada página possa definir o seu próprio título. Por fim, o método RenderBody() indica onde o conteúdo definido em cada página será adicionado.É recomendado que os arquivos que definam layouts sejam colocados na pasta Views\Share.

Layout

O ASP.NET MVC 4 possui um mecanismo capaz de agrupar o conteúdo CSS de diversos arquivos dinamicamente. Para usar esse mecanismo, basta invocar o método Render() da propriedade Styles.

Analogamente, a propriedade Scripts possui o método Render(), que também tem por obje- tivo agrupar o código JavaScript de diversos arquivos.

@Styles.Render("~/Content/Site.css“, "~/Content/Arquivo1.css“, "~/Content/Arquivo2.css“, "~/Content/Arquivo2.css“)

Incluindo vários arquivos CSS via Styles.Render()

RenderBody

Quando a página de edição de produtos é requisitada, o arquivo Alterar.cshtml é processado antes do arquivo Layout.cshtml, o que permite definir o valor de ViewBag.Title no arquivo Alterar.cshtml e utilizá-lo no layout.

_ViewStart

Para definir o layout de Alterar.cshtml, foi necessário armazenar o caminho completo do arquivo que define o layout na propriedade Layout. Para definir um layout padrão para todas as páginas, basta acrescentarmos o arquivo _ViewStart.cshtml à pasta View.

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

}

_ViewStart.cshtml

Lacunas

Também podemos criar seções em um layout para serem preenchidas com conteúdos específicos definidos nas páginas. Considere o seguinte layout.

Opcional:

@if ( IsSectionDefined ("SideBar"))

Opcional:

@if ( IsSectionDefined ("SideBar"))

RenderSection

Para definir o conteúdo de uma seção, devemos utilizar o código @section. Observe o código de uma página que utiliza o layout criado anteriormente e define a seção Sidebar.

Alterar.cshtml

Exercícios

Partial Views

Quanto mais elaborada é uma página de uma aplicação web, mais extenso é o seu código. Códigos muito extensos prejudicam a legibilidade e a manutenção da aplicação. Para organizar melhor o código, podemos dividir o conteúdo de uma página web em vários arquivos.Suponha que desejamos dividir o conteúdo de uma página em duas partes. Devemos criar um arquivo para cada parte.

< h1 > Parte 1 </ h><p> Conteúdo da parte1 </ p>

_Parte1.cshtml

< h1 > Parte 2 </ h><p> Conteúdo da parte2 </ p>

_Parte2.cshtml

Partial Views

Por fim, devemos criar um arquivo principal para agrupar essas partes. Utilizaremos o métodoPartial() para inserir o conteúdo dos arquivos secundários no arquivo principal.

<html><head>

<title>Exemplo de partial</title></head>

<body>@Html.Partial("_Parte1")@Html.Partial("_Parte2")

</body></html>

Principal.cshtml

Exemplo: Partial Views

Unificando as páginas Edit.cshtml e Create.cshtml Crie uma partial view com o conteúdo comum entre as duas páginas Insira a Partial View nas duas páginas Crie uma partial view usando foreach e passando o objeto como

parâmetro

Camada de Controle

Camada de Controle

No ASP.NET MVC as urls são mapeadas para métodos (ações) em classes que definem os chamadas controladores. As requisições enviadas pelos navegadores são processadas pelos controladores.

Camada de Controle

O processamento realizado por um controlador para tratar uma requisição consiste basicamente em:

• Recuperar os dados enviados pelo usuário através de formulários.• Interagir com a camada de modelo.• Acionar a camada de apresentação para construir a página HTML que deve ser enviada para o usuário como resposta à sua requisição.

Camada de Controle

Para que uma classe seja considerada um controlador, ela deve seguir algumas regras.

• O nome da classe deve ter o sufixo “Controller”.• A classe deve implementar a interface System.Web.Mvc.IController ou herdar da classe System.Web.Mvc.Controller.

Actions

As ações são utilizadas para processar as requisições realiza- das pelos navegadores. Para criar uma ação, é necessário definir um método public dentro da classe de um controlador. Os parâmetros desse método podem ser utilizados para receber os dados enviados pelos usuários através de formulários HTML. Esse método deve devolver um ActionResult que será utilizado pelo ASP.NET MVC para definir o que deve ser executado depois que a ação terminar.

Actions

Quando um usuário faz uma requisição HTTP através de um navegador, o ASP.NET MVC verifica na tabela de rotas o controlador e a ação associados à url da requisição realizada. Essa tabela é definida no arquivo RouteConfig.cs e inicializada no arquivo Global.asax.

Por padrão, quando criamos um projeto ASP.NET MVC no Visual Studio, uma rota com o formato{controller}/{action}/{id} é adicionada na tabela de rotas.Exemplo: http://www.s2b.com.br/Produto/Edit/1

ActionResult

Quando uma ação termina, o método correspondente deve devolver um ActionResult. O valor devolvido indica para o ASP.NET MVC o que deve ser executado depois da ação. Veja abaixo uma lista com alguns tipos específicos de ActionResult que podem ser utilizados.

ActionResult

Considerando uma aplicação ASP.NET MVC 4 em C# e Razor, o método View(), ao ser cha- mado sem parâmetros, executará o seguinte processo para determinar qual arquivo deve ser utilizado para construir a página de resposta.

1. Se o arquivo Views\Teste\Acao.cshtml existir, ele será utilizado.2. Caso contrário, se o arquivo Views\Shared\Acao.cshtml existir,

ele será utilizado.3. Se nenhum desses arquivos existir, uma página de erro será

devolvida.

ActionResult

Por outro lado, podemos especificar o nome do arquivo que define a página de resposta. Veja o exemplo abaixo.

Além disso, podemos passar um objeto para a camada de apresentação. Esse objeto será utilizado nas páginas fortemente tipadas

return View(“NomeDaView”);

return View(Produto);

ActionResult

Também é possível especificar o nome do arquivo que define a página de resposta e o objeto que deve ser transmitido para a camada de apresentação ao mesmo tempo.

return View(“NomeDaView”, produto);

PartialViewResult

Devolve uma página parcial da camada de apresentação. Exemplos:

O método PartialView() utiliza a mesma abordagem do método View() para determinar o arquivo que deve ser utilizado para construir a página parcial de resposta.

return PartialView();

return PartialView(“NomeDaPartialView”, produto);

ActionResult (Outros recursos)

RedirectResult: Redireciona o navegador para uma URL específica. Exemplo:

RedirectToAction: Redireciona para outra ação da camada de controle. Exemplo:

return Redirect(“http://www.s2bminas.com.br”);

return RedirectToAction(“OutraAction”, “OutroController”);

ContentResult: Devolve texto. Exemplo

return Content(“Texto”, “text\plain“);

ActionResult (Outros recursos)

JsonResult: Devolve um objeto no formato JSON. Exemplo

return Json(produto);

JavaScript: Devolve um código JavaScript. Exemplo

return JavaScript(“\$(‘\#divResultText’).html(‘JavaScript Passed’);”);

FileResult: Devolve dados binários. Exemploreturn File(@”c:\relatorio.pdf”, “application\pdf”);

EmptyResult: Devolve resposta vazia. Exemploreturn EmptyResult();

Parâmetros

Os parâmetros enviados pelos usuários através de formulários HTML podem ser recuperados por meio da propriedade Request.string nome = Request[“Nome”];

Esses parâmetros também podem ser recuperados através dos parâmetros da ação responsável pelo processamento da requisição HTTP realizada. Para isso, basta definir um parâmetro C# para cada parâmetro HTTP com o mesmo nome. Veja o exemplo abaixo:Nome : <input type="text" name=“Nome"/> Descrição: <input type="text" name=“Descricao"/> Preço: <input type="text" name=“Preco"/>

Parâmetros

No código anterior, criamos um formulário HTML com os parâmetros nome, descrição e preço. Esses parâmetros serão recuperados na ação Salva definida no código abaixo.[ HttpPost ]public ActionResult Salva(string nome, string descricao, string preco){

Produto produto = new Produto{Nome = nome, Descricao = Descricao, Preco = Preco}; db.Produtos.Add(produto);return View();

}

Parâmetros

O ASP.NET MVC também é capaz de montar objetos com os valores dos parâmetros HTTP envi- ados pelo usuário e passá-los como argumento para as ações dos controladores.[ HttpPost ]public ActionResult Salva(Produto produto){

db.Produtos.Add(produto);return View();

}

Exercícios

Utilize RedirectToAction Passe alguns parâmetros via Resques[] e via Objetos para a

Controller

TempData

Ao efetuar um redirecionamento, uma nova requisição é realizada pelo navegador. Nesta nova requisição, não temos mais acesso aos dados e objetos da requisição anterior ao redirecionamento. Caso haja a necessidade de preservar dados ao longo do redirecionamento, podemos utilizar a propriedade TempData.

TempData (Continuação)

Por exemplo, ao cadastrar uma produto, podemos efetuar um redirecionamento para a tela de listagem de produtos. Na propriedade TempData, podemos acrescentar uma mensagem indicando o eventual sucesso da operação. Veja o exemplo abaixo.

[ HttpPost ]public ActionResult Salva(Produto produto){

db.Produtos.Add(produto);db.SaveChanges();TempData[“Mensagem”] = “Produtos cadastrados com sucesso!”;return RedirectToAction(“Index”);

}

TempData (camada de apresentação)

Na camada de apresentação, podemos recuperar os dados armazenados na propriedade TempData.Veja o código a seguir:

@if (TempData["Mensagem"] != null ){

<p>@TempData["Mensagem"]</p>}

Exercícios

Repasse uma mensagem da camada de Controle para a de Apresentação usando o TempData;

Rotas

O nome do controlador e o nome da ação desejados fazem parte da url. Exemplo: http://localhost<PORTA_APP>/Produto/Index

O formato dessas urls é definido por rotas criadas no arquivo RouteConfig.cs e carregadas no arquivo Global.asax.

RouteConfig.cs

Rotas

O primeiro argumento do método MapRoute é o nome da rota, o segundo é a expressão que define o formato da rota e o terceiro é o conjunto de valores padrão dos parâmetros da rota.

URL Mapeamento da URL

/ controller = "Home", action = "Index"

/Produto controller = “Produto", action = "Index"

/Produto/Adiciona controller = “Produto", action = "Adiciona"

/Produto/Remove/1 controller = “Produto", action = "Remove", id = 1

Adicionando uma rota

Para acrescentar uma rota, podemos utilizar o método MapRoute(). Suponha que a listagem de produtos deva ser acessada através da urlhttp://localhost:<PORTA_APP>/Catalogo. Nesse caso, podemos adicionar uma rota no arquivo RoutesConfig.cs, como mostrado abaixo.

routes.MapRoute ( name : "Nova Rota", url : "Catalogo",defaults : new{controller = “Produto", action = "Index" }

);

Importante: As rotas são processadas na ordem em que foram inseridas. Portanto, é importante definir as rotas mais específicas antes das rotas mais genéricas.

Adicionando Parâmetros a uma rota

Por padrão, os parâmetros adicionados a uma rota são obrigatórios. Dessa forma, a listagem de categorias só poderá ser acessada se o valor do parâmetro maximo for definido na url da requisição. Por exemplo, http://localhost:<PORTA_APP>/Categoria/20. Se uma requisição for realizada para a url http://localhost:<PORTA_APP>/Categoria, um erro ocorrerá. routes.MapRoute (

name : "Nova Rota", url : "Categoria/{maximo}",defaults : new{controller = “Categoria", action = "Index" }

);

Adiconando parãmetros

Para mudar esse comportamento, podemos tornar o parâmetro máximo opcional. Veja exemplo abaixo:routes.MapRoute (

name : "Nova Rota", url : "Categoria/{maximo}",defaults : new{controller = “Categoria", action = "Index" ,maximo = UrlParameter.Optional }

);

Os parâmetros das rotas podem ser recuperados nas ações. Public ActionResult Index(int? maximo){

// Implentação}

Exerícios

Crie algumas Rotas novas

Validação

Os usuários podem cometer erros ao preencher um formulário. Por exemplo, esquecer de preencher um campo que é obrigatório. Os parâmetros enviados pelos usuários devem ser validados pela aplicação com o intuito de não permitir o armazenamento de informações erradas.

Validação (Camada de Controle)

O primeiro passo para implementar a validação dos parâmetros enviados através de formulários HTML é definir a lógica de validação na camada de controle.O segundo passo é definir mensagens informativas para enviar aos usuários. O ASP.NET MVC possui um objeto especializado no armazenamento de mensagens de erros de validação. Esse objeto pode ser acessado através da propriedade ModelState.If (produto.Nome == null || produto.Nome.Trim().Length == 0){

ModelState.AddModelError(“Nome”, “O campo Nome é obrigatório”);}

Validação na camada de Controle

Validação (Camada de Controle)

As mensagens são armazenadas no ModelState através do método AddModelError(). Esse método permite que as mensagens sejam agrupadas logicamente, pois ele possui dois parâmetros: o primeiro é o grupo da mensagem e o segundo e a mensagem propriamente.Se algum erro for encontrado, o fluxo de execução pode ser redirecionado para uma página que mostre as mensagens informativas aos usuários.O ModelState possui uma propriedade que indica se erros foram adicionados ou não. Essa propriedade chama-se IsValid.

Validação (Camada de Controle)

Veja o exemplo abaixo:[HttpPost]public ActionResult Salva(Produto produto){

if (produto.Nome == null || produto.Nome.Trim().Length == 0){Model State.AddModelError("Nome", "O campo Nome é obrigatório.");}if (ModelState.IsValid ) {

...}else {return View("Cadastra");}

}

Validação (Camada View)

As mensagens de erros de validação podem ser acrescentadas em uma página através do método ValidationSummary() da propriedade Html. É importante salientar que esse método adiciona todas as mensagens de erro.@model LojaVirtual.Models.Produto@{

ViewBag.Title = "Cadastro de Produto"; }

< h2 >Cadastro de Produto</ h2 > @using (Html.BeginForm()) {

@Html.ValidationSummary()

< br/>…

Validação (Camada View)

Podemos utilizar o método ValidationMessageFor() para mostrar somente as mensagens de erro de validação de um determinado grupo.Para não mostrar erros dos grupos com o ValidationSummary(), devemos passar como parâmetro o valor true. Nesse caso, apenas os erros que não estão associados a um grupo específico serão apresentados pelo ValidationSummary().

Validação (Camada View)Exemplo de Exibição dos erros que não estão associados ao grupo.

@model LojaVirtual.Models.Produto@{

ViewBag.Title = "Cadastro de Produto"; }

< h2 >Cadastro de Produto</ h2 > @using (Html.BeginForm()) {

@Html.ValidationSummary(true) <br/>

@Html.LabelFor(model => model.Nome)@Html.EditorFor(model => model.Nome)@Html.ValidationMessageFor(model => model.Nome)

Validação (Anotações)

As lógicas de validação também podem ser definidas através de anotações adicionadas nas classes de modelo. Dessa forma, essas lógicas não estariam mais nos controladores, o que conceitualmente é o ideal, pois nos controladores só deveria existir lógica para controlar o fluxo da execução.

Validação (Anotações)

Required: Uma das validações mais comuns é a de campo obrigatório para propriedades do tipo string. As mensagens padrão podem ser alteradas através do atributo

ErrorMessage.

…[Required(ErrorMessage=“O campo Nome é obrigatório!”)]Public string Nome{get; set;}…

Outros validadores

StringLength: Tamanho máximo que uma string deve permitir.[StringLength(30)][StringLength(100, MinimumLength = 3)]

RegularExpression: Permite informar uma expressão regular para validar o campo.[RegularExpression("^[0-9]{8}$")]

Range: Permite informar um range de valores para o campo.[Range(0.01, 100.00,

ErrorMessage = “O preço deve ser entre 0,01 and 100,00")]

Exercícios

Sessões

Considere a aplicação de uma loja virtual. Nessa aplicação, os clientes selecionam os produtos desejados e os adiciona no seu carrinho de compra. Cada cliente deve ter o seu próprio carrinho para que os seus produtos não se misturem com os produtos selecionados por outros clientes. A aplicação deve armazenar o carrinho de um cliente até que a compra seja finalizada ou até ela ter certeza que o cliente não precisa mais do carrinho.Para resolver esse problema, podemos utilizar o conceito de Sessão. Para cada navegador conectado, o servidor manterá uma sessão aberta.

Sessões

Para armazenar informações, você deve adicionar uma chave e um valor na propriedade Session. Considere um objeto da classe Usuario que agrupa as informações sobre um determinado usuário. O código a seguir é um exemplo de como podemos guardar esse objeto na sessão após a realização da autenticação do usuário.Public class LoginController : Controller{

public ActionResult Login(Cliente cliente) {Session[“Cliente”] = cliente…

}}

Sessões

Você pode adicionar qualquer tipo de valor na sessão. De forma análoga, para resgatar as infor- mações armazenadas, basta acessar a chave correspondente da propriedade Session. Veja o exemplo a seguir:Cliente cliente = (Cliente)Session[“Cliente”];String saudacao = “Bem vindo” + cliente.Nome;

Para aliminar todas as chaves do dicionário, utilize o RemoveAll(). E para eliminar utilize o Abandon().Session.RemoveAll();

Session.Abandon();

Session Mode

O ASP.NET MVC disponibiliza quatro modos de sessão (Session Modes):InProc: [Padrão] Armazena a sessão na memória do

servidor. StateServer: São armazenadas em um servidor diferente.SQLServer: São armazenadas no Banco de Dados SQL

Server.Custom: O armazenamento pode ser personalizado.

<sessionState mode=“InProc” timeout=“30”/>Web.Config

Exercícios1) Armazena uma sessão na Controladora e recupere na View.

Filtros

Muitas vezes, queremos restringir o acesso à determinadas áreas de uma aplicação, seja por questões de segurança ou por organização. Em nossa aplicação poderíamos, por exemplo, definir que para poder adicionar, alterar e remover editoras, o usuário deve estar logado no sistema. Caso contrário, o usuário apenas poderá listar as editoras.

Filtros

Exemplo, o usuário tente adicionar uma editora através do formulário de cadastro, a ação Cadastra verificará se o usuário já está logado.

.public ActionResult Cadastro(){

if (Session[“Cliente”] != null) {return base.View();

}else {

return base.RedirectToAction(“Index”), “Login”)}

}Web.Config

Tipos de Filtros

O ASP.NET MVC possui 4 (quatro) tipos de filtros:

Tipo de Filtro Interface Implementação Padrão

Autorização IAuthorizationFilter AuthorizeAttribute

Ação IActionFilter ActionFilterAttribute

Resultado IResultFilter ActionFilterAttribute

Exceção IExceptionFilter HandleErrorAttribute

Filtros

Autorização: Filtro utilizado para restringir o acesso a ação do controlador a usuários autenticados e autorizados. Caso o usuário não tenha permissão, o filtro retorna a resposta 401 HTTP Unauthorized. Se o filtro for adicionado ao controlador, todas as ações terão o acesso restrito.

Importante:Este filtro é executado antes dos outros filtros

Outros Filtros

Ação: Este filtro é executado antes ou depois da ação ser executada. Este filtro é chamado depois do filtro de autorização e antes do filtro de resultado.

Resultado: O filtro de resultado é executado antes ou depois do resultado da ação ser processado. Este filtro permite alterarmos a maneira como o resultado da ação é gerado.

Exceção: Este filtro é utilizado para tratar as exceções. Este filtro é executado quando ocorre uma exceção no método ou nos filtros da ação.

Filtro de Autorização

Os filtros de autorização implementam a interface IAuthorizationFilter.

public interface Iauthorization Filter{

void OnAuthorization(AuthorizationContext filterContext);}

IAuthorizationFilter.cs

O método OnAuthorization é executado pelo ASP .NET MVC para realizar a autorização. A classe AuthorizationContext é derivada de ControllerContext, que permite o acesso aos dados do controlador, da rota e da requisição.

Filtros de Autorização

O ASP .NET MVC contém uma implementação padrão da IAuthorizationFilter que é a classe AuthorizeAttribute. A classe AuthorizeAttribute define a anotação Authorize, que pode ser adicionada a ação ou ao controlador para restringirmos o acesso a usuários autenticados e autorizados.Caso um usuário não autorizado acesse uma ação ou um controlador marcado com a anotação Authorize, o MVC Framework retornará a resposta 401 HTTP status. Se a aplicação estiver configurada para utilizar ASP.NET Forms Authentication, o usuário será redirecionado para uma página de login.

Filtros de Autorização (Exemplo)

Para o nosso primeiro exemplo, podemos utilizar o filtro de autorização, onde exigimos que o usuário esteja logado (autenticado) para acessar determinadas áreas da aplicação. Para isso, precisamos adicionar o seguinte código no nosso método de login:…

FormsAuthentication.SeAuthCookie(usuario.Username, false);…

AutenticadorController.cs

Filtros de Autorização (Exemplo)

Isto adiciona um novo cookie utilizado para a autenticação do usuário. Este novo cookie é in- dependente do cookie utilizado para armazenar informações da sessão. O primeiro parâmetro é referente ao nome do usuário (ou algo que o identifique). O segundo parâmetro é um booleano relativo ao tipo do cookie, se é permanente ou não. Caso seja true, ele sempre irá considerar que o usuário está autenticado após a primeira autenticação. Para eliminar o cookie de autenticação, devemos adicionar o

seguinte código na acão de logout:

FormsAuthentication.SignOut();AutenticadorController.cs

Filtros de Autorização (Exemplo)

As ações que devem utilizar o filtro de autorização devem ser anotadas com Authorize. Veja o exemplo na EditoraController.cs:[Authorize]public ActionResult Cadastra(){

return base.View();}

Para aplicar o filtro a todas as ações de um controlador, podemos adicionar a anotação Authorize na classe.[Authorize]public class EditoraController() : Controllher…

Filtros de Autorização

Desse modo, todas as ações presentes no controlador da Editora exigem que o usuário esteja autenticado.Quando o filtro de autorização “barra” um usuário de acessar uma página, podemos redirecionálo para a página de login. Devemos incluir o seguinte código dentro da tag <system.web> do arquivo Web.Config.<authenticationmode="Forms">

<formsloginUrl="~/Autenticador/Login“ timeout="2880"/></authentication>

Web.Config

Filtros de Autorização

Através da propriedade User, podemos obter o usuário associado a requisição atual. As informações do usuário podem ser obtidas através da propriedade Identity. Por exemplo, podemos verificar se o usuário associado à requisição atual está autenticado, basta utilizar a propriedade IsAuthenticated da propriedade Identity:

if (User.Identity.IsAuthenticated){

...}

Verificando a autenticação do usuário

Filtros de autorizaçãoPara obter o nome do usuário autenticado, podemos utilizar a propriedade Name da propriedade. Identity:

A propriedade Name retorna o nome do usuário que passamos como parâmetro para o método SetAuthCookie na autenticação.

string nome = User.Identity.Name;

Exercícios

Filtros de Ação

Os filtros de ação são executados antes ou depois de uma ação. Todos os filtros de ação de- vem implementar a interface IActionFilter. A interface IActionFilter contém dois métodos OnActionExecuted e OnActionExecuting.

public interface IActionFilter{

void OnActionExecuted(ActionExecutedContext filterContext);void OnActionExecuting(ActionExecutingContext filterContext);

}IActionFilter.cs

O método OnActionExecuting é chamado antes da ação ser executada e o método OnActionExecuted é chamado depois da ação ser executada.

Filtro de Resultados

O filtro de resultado é executado antes ou depois do resultado da ação ser gerado. O resultado da ação pode ser um JSON, uma página HTML ou qualquer outro resultado que derive da classe ActionResult. Para definir um filtro de resultado, devemos implementar a interface IResultFilter que contém dois métodos OnResultExecuted e OnResultExecuting.public interface IResultFilter{

void OnResultExecuted(ResultExecutedContext filterContext);void OnResultExecuting(ResultExecutingContext filterContext);

}

Filtro de Resultado

Para aplicar o filtro, basta adicionar a anotação ElapsedTime no controlador ou na ação.

...[ ElapsedTime ]public ActionResult Index () {

return View(db.Produtos.ToList()); }

...ProdutoController.cs

Filtro de Resultado

Ao acessar o seguinte endereço http://localhost:<PORTA_APP>/Produtos, podemos visualizar a duração entre a execução da ação e a geração do resultado

Filtros de Exceção

Os filtros de exceção são executados quando ocorrem exceções nas ações ou nos filtros. Os filtros de exceção devem implementar a interface IExceptionFilter.

public interface IExceptionFilter{

void OnException(ExceptionContext filterContext );}

IExceptionFilter.cs

Filtros de Exceção

O ASP .NET MVC contém a classe HandleErrorAttribute que é uma implementação padrão de IExceptionFilter. O filtro HandleErrorAttributeretorna a página Error localizada na pasta Views/Shared quando ocorre uma exceção. Através da HandleErrorAttribute podemos alterar a página de erro retornada de acordo com o tipo de exceção.[ HandleError(ExceptionType = typeof(InvalidOperationException ),View ="OperacaoInvalida")] [HandleError]public ActionResult Index (){

return View(db.Produtos.ToList ());}

IExceptionFilter.cs

Filtros de Exceções

No exemplo anterior, a primeira anotação filtrará os erros do tipoInvalidOperationException e retornará a página OperacaoInvalidada pasta Views/Shared. A segunda anotação filtrará todas as exceções e retornará a página padrão Error da pasta Views/Shared. É necessário habilitar o ele- mento customErrors no arquivoWeb.config para o filtro HandleErrorAttribute funcionar.

Exercícios

Tratamento de Erros

Inevitavelmente, as aplicações estão sujeitas a erros de várias naturezas. Por exemplo, erros podem ser gerados pelo preenchimento incorreto dos campos de um formulário. Esse tipo de erro é causado por falhas dos usuários. Nesse caso, é importante mostrar mensagens informativas com o intuito de fazer o próprio usuário corrigir os valores preenchidos incorretamente.

Tratamento de Erros (Try-Catch)

Os erros de aplicação podem ser identificados através do comando try-catch, que pode ser colocados nos métodos que definem as ações dos controladores. Ao identificar a ocorrência de um erro, os controladores podem devolver uma página web com alguma mensagem para o usuário.

Tratamento de Erros (Try-Catch)

Exemplo:

[ HttpPost ]public ActionResult Salva(Produto produto){

Try {db.Produtos.Add(produto);

}Catch {

return View("Error");}

return RedirectToAction("Index");}

Tratamento de errosExemplo de página de erros

…<h2>Servidor com problemas</h2><p>Houve um problema em nosso servidor .<br/>Por favor tente novamente dentro de alguns instantes .</ p>...

Error.cshtml

Importante: Uma página de erro padrão dentro da pasta Views\Shared

Custom Errors

Utilizar o comando try-catch nos controladores para lidar com os erros de aplicação não é uma boa alternativa, pois o código do controlador fica mais complexo. Além disso, haveria replicação de código nos controladores, pois provavelmente a página de erro seria padronizada.Para lidar com os erros de aplicação de uma maneira mais prática e fácil de manter, podemos configurar o ASP.NET MVC para utilizar páginas de erro padrão. O primeiro passo é alterar o arquivo de configuração Web.config, acrescentando a tag<customErrors> dentro da tag <system.web>.

Custom Errors

O atributo mode da tag <customErrors> pode assumir três valores:

On: A página de erro padrão será enviada para usuários locais e remotos.

Off: A página de erro detalhada será enviada para usuários locais e remotos.

RemoteOnly: A página de erro detalhada será enviada para osusuários locais e a padrão para os remotos.

Http Errors

Um dos erros mais conhecidos do HTTP é o 404, que ocorre quando o navegador faz uma re- quisição para uma url que não existe. Basicamente, esse erro é gerado por falhas dos usuários ao tentarem digitar diretamente uma url na barra de endereço dos navegadores ou por links ou botões “quebrados” nas páginas da aplicação.Quando o erro 404 ocorre, o ASP.NET MVC utiliza a página padrão para erros de aplicação con- figurada no Web.configatravés da tag <customErrors>. >. Porém, esse erro não deve ser considerado um erro de aplicação, pois ele pode ser gerado por falhas do usuário.

Http Errors…<h2>Arquivo ou caminho não encontrado!</h2><p>O caminho informado ou arquivo não foi encontrado.<br/>Verifique se a URL informada está correta!</ p>...

NotFound.cshtml

<customErrorsmode=" On"><errorstatusCode="404" redirect="~/ErrorPage/NotFound"/></custom Errors>

Web.Config

De acordo com o código anterior, devemos definir um controlador chamado ErrorPage com uma ação chamadaNotFound. Essa ação será acionada toda vez que o erro404 do HTTP ocorrer.public class ErrorPageController: Controller{

public ActionResult NotFound(){

return View ();}

}ErrrorPageController.cs

© 2016 Microsoft Corporation. All rights reserved.