Baixe o app para aproveitar ainda mais
Prévia do material em texto
ASP NET CORE MVC 2 Thiago Paiva Aula 1 – ASP NET CORE e o MVC Tópicos O que é MVC O que é ASP NET CORE MVC Recursos O que é o padrão MVC Padrão de arquitetura de software; Separa a aplicação em 3 camadas (Model View Controller); Principal benefício é o isolamento das regras de negócio da lógica de apresentação. O que é o padrão MVC Model -> responsável pela manipulação de dados. Realiza escrita, leitura e validação de dados View -> responsável pela interação com o usuário. Exibe dados por meio de html ou xml Controller ->Responsável pelas requisições do usuário. É ele que controla quais views e models serão utilizados O que é o padrão MVC O que é ASP NET CORE MVC ? A estrutura do ASP.NET Core MVC é uma estrutura de apresentação leve, de software livre e altamente testável, otimizada para uso com o ASP.NET Core. ASP.NET Core MVC fornece padrões para criar sites dinâmicos que possibilitam a separação limpa de preocupações. Ele dá controle total sobre marcações, suporte ao desenvolvimento amigável a TDD e usa os padrões mais recentes. Versão Atual : 2.1 Recursos ASP.NET Core MVC inclui o seguinte: Roteamento Associação de modelos Validação de modelo Injeção de dependência Filtros Áreas APIs Web Capacidade de teste Mecanismo de exibição do Razor Exibições fortemente tipadas Auxiliares de marcação Componentes da exibição Fonte : Microsoft Aula 2 – Preparo do Ambiente Tópicos : Instalando o Visual Studio Community Preparo do Ambiente Visual Studio Community 2017 -> https://www.visualstudio.com/pt-br/thank-you- downloading-visual-studio/?sku=Community&rel=15 Aula 3 – Primeiro Projeto Tópicos Criando o primeiro projeto Pastas e arquivos padrões Primeiro Projeto Pastas : Properties - Possui arquivos com as propriedades do arquivo, como por exemplo informações a respeito da publicação do aplicativo. O arquivo launchSettings.json possui as informações para publicação do aplicativo, variáveis de ambiente e outros. Wwwroot - Possui os arquivos estáticos da aplicação, isto é, aquilo que não mudam durante o processo de compilacação da aplicação. Isso incluí arquivos CSS, JS, imagens, ícones e outros. Controllers - Pasta que possui os controllers utilizados pela aplicação. Nela você encontrará o controller padrão Home, que possui as ações Home, About e Contact. Primeiro Projeto Models - Pasta que possui os models utilizados pela aplicação. Nela você encontrará uma ViewModel (será visto mais adiante) utilizada no auxílio de exibição de erros. Views - Pasta que possuí as views utilizadas pela aplicação. Há dentro dela mais algumas pastas Views/Home - Pasta utilizada pelas views do controller Home Views/Shared - Pasta que possui as views que são utilizadas em mais de um parte da aplicação ou utilizada por mais de um controller. _CookieConsentPartial.cshtml - PartialView (será visto mais adiante) que mostra um banner na página principal. Geralmente utilizado para o usuário concordar com a política de cookies utilizada pela aplicação. Primeiro Projeto Layout.cshtml - Possui todo o HTML usado nas outras views. _ValidationScriptsPartial.cshtml - Usa taghelpers (será visto mais adiante) e configurações de ambiente para adicionar ou remover scripts quando a aplicação está sendo executada no ambiente de desenvolvimento. _Error.cshtml - View padrão para a exibição de erros. Primeiro Projeto _ViewsImports.cshtml - Incluí namespaces que outras views podem referenciar sem o uso da comando using. _ViewStart.cshtml - Possuí o código que é executado antes das outras views. appsettings.json - Atribuição de variáveis para diferentes ambientes. É nesse arquivo que configuramos a conexão com o banco de dados, por exemplo. Program.cs - Indica onde buscar as configurações para a execução da aplicação. Startup.cs - Serve para atividades, como incializar configurações, configurar o ambiente do aplicativo e outras tarefas para possibilitar o aplicativo de ser executado. Aula 4 – Trabalhando com bibliotecas / scripts no lado do cliente (client side) Tópicos Arquivos Estáticos Scripts Instalando bibliotecas client side Content Delivery Network (CDN) Bundle Minification Configuração de bundle e minification Arquivos Estáticos Arquivos que são enviados diretamente aos clientes pelo ASP NET CORE. São armazenados no diretório raiz (wwwroot) do sistema. Exemplos : HTML, CSHTML(Razor), CSS, JS, .JPG e etc. Scripts Scripts são arquivos javascript ou css usados na interação do usuário com o sistema no lado do cliente. Para instalá-los, basta utilizarmos alguma ferramenta para o gerenciamento de biblioteca no lado do cliente (client side). A ferramenta padrão utilizada no Visual Studio e ASP NET CORE 2.1 é o Library Manager (libman). Instalando bibliotecas Para utilizar o libman, basta clicar com o botão direito do mouse sobre o gerenciador de soluções e escolher “Gerenciar bibliotecas do lado do cliente” ou “Manage client side libraries” O arquivo “libman.json será criado.” Instalando bibliotecas O arquivo será criado com o seguinte código "version": "1.0", "defaultProvider": "cdnjs", "libraries": [] “version” -> representa a versão do arquivo. “defaultProvider” -> é o provedor por onde os arquivos serão baixados. O valor padrão é “cdnjs”, ou seja, os arquivos serão pegos através content delivery network. O CDN usado pelo Visual Studio é o https://cdnjs.com/. É possível usar um sistema de arquivos próprio, basta definir “filesystem” em vez de “cdnjs”. “libraries” : [] -> bibliotecas e scripts a serem utilizados. Instalando bibliotecas É possível definir um diretório padrão para todos os arquivos serem salvos. Basta utilizar o comando “defaultDestination” "defaultDestination": "wwwroot/“ Isso define que todos os arquivos serão salvos no diretório “wwwroot/” Instalando bibliotecas Já dentro de “libraries”.... Deve-se utilizar o comando “library” para definir a biblioteca ou framework a ser utilizada. “library”: biblioteca@versão "library": "fullcalendar@3.9.0", Instalando bibliotecas Em seguida, utiliza-se o comando “files” para definir quais arquivos serão baixados. “files” : [“arquivo1”, “arquivo2”, ... , “arquivoN”] "files": [ "fullcalendar.js", "fullcalendar.min.css", "locale/pt-br.js" ] E finalmente, deve-se definir o diretório que esses arquivos serão salvos, utilizando o comando “destination”. Nesse caso, o diretório padrão (defaultDestination) não pode ter sido definido anteriormente. “destination”: “diretório” "destination": "wwwroot/“ Instalando bibliotecas Ainda é possível definir um provedor para cada biblioteca, mas novamente, não pode ter um provedor padrão (defaultProvider) definido. “provider”: “provador” “provider”: “cdnjs” Instalando bibliotecas Juntando tudo... { "version": "1.0", "defaultProvider": "cdnjs", "defaultDestination": "wwwroot/", "libraries": [ { "library": "fullcalendar@3.9.0", "files": [ "fullcalendar.js", "fullcalendar.min.css", "locale/pt-br.js" ] } ] } Instalando bibliotecas Agora basta clicar com o botão direito do mouse em “Restore Client-Side Libraries” ou “Restaurar bibliotecas do lado do cliente” Caso você selecione “Habilitar Restauração de bibliotecas do lado do cliente no build” ou “Enabled Restore on Build…” as bibliotecas sempre serão restauradas quando o programa for compilado. Content Delivery Network (CDN) Rede de distribuição de informação; Permite fornecerconteúdo web de forma rápida a vários usuários; Conteúdo distribuído entre vários servidores; Direciona o conteúdo ao usuário com base no servidor mais próximo; Exemplos de empresas no Brasil : CloudFlare, CloudFront e GoCache. Content Delivery Network (CDN) Fonte: http://www.cdnreviews.com/ Content Delivery Network (CDN) Algumas Vantagens : Arquivos podem ter “pré-cache” : Usuários já podem estar com scripts no cache de seus navegadores. Dessa forma, não será necessário baixar para o navegador esse script novamente, ocorrendo economia de banda no seu sistema / servidor. Controle de versão : CDNs geralmente possuem os scripts mais recentes. Dessa forma, é possível sempre ter os scripts mais atualizados em seu sistema. Economia de recursos : CDNs podem distribuir carga, reduzir o consumo de banda, otimizar seu sistema e reduzir o preço de sua hospedagem online. Bundle Combina vários arquivos em um único arquivo. Reduz o número de requisições ao servidor necessárias para renderizar uma página web. Menos arquivos geram menos requisições HTTP Bundle Modo “convencional” Bundle Utilizando bundle O arquivo padrão em que ele é configurado é o site.js O jeito mais rápido de se utilizar bundle é utilizando o pacote BundleMinifier Minificação Remove caracteres e espaços desnecessários. Dessa forma, reduz o tamanho dos arquivos. Algumas ferramentas usadas : Gulp e Grunt Para se utilizar, basta habilita-lo no arquivo site.js usando o comando "minify": { "enabled": true }, Minificação A função AddAltToImg = function (imageTagAndImageID, imageContext) { var imageElement = $(imageTagAndImageID, imageContext); imageElement.attr('alt', imageElement.attr('id').replace(/ID/, '')); } Ficaria AddAltToImg=function(n,t){var i=$(n,t);i.attr("alt",i.attr("id").replace(/ID/,""))}; Configuração de bundle e minificação [{ "outputFileName": "wwwroot/js/site.min.js", "inputFiles": [ "wwwroot/js/bootstrap.js", "wwwroot/datepicker.js" ], "minify": { "enabled": true } }, { "outputFileName": "wwwroot/css/site.min.css", "inputFiles": [ "wwwroot/css/bootstrap.css", "wwwroot/datepicker.css" ], "minify": { "enabled": true } }] Configuração de bundle e minificação outFileName -> Nome do arquivo do bundle que será gerado; inputFiles -> Arquivo que serão adicionados no bundle; minify -> Permite escolher se os arquivos serão minificados ou não; renameLocals -> permite renomear variáveis locais Há ainda mais algumas opções para a personalização do arquivo que será gerado. Essas opções pode ser vistas no link https://github.com/madskristensen/BundlerMinifier/wiki/JavaScript-Minifier- settings Bibliotecas e classes no lado do servidor É possível instalar pacotes e bibliotecas que não estão presentes no ASP NET CORE MVC. Para realizar determinada tarefa, basta usar o gerenciador de pacotes NUGET. Esses novos pacotes e bibliotecas serão instalados do lado do servidor. Aula 5 – Sistema de rotas Tópicos O que é Como utilizá-lo Múltiplas rotas Roteamento por atributos Mapeando múltiplas rotas por atributos Sistema de rotas É usado um middleware de rotas para corresponder com as rotas requisitadas e então mapeá-las em ações; São definidas na classes startup ou em atributos; São usadas para gerar URLs enviadas em respostas; Sistema de rotas app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); Nesse exemplo, a rota padrão é a rota que direcionará o usuário para a ação index, controller home, ou seja, sempre que o sistema for acessado, a página index do controller home será exibida. O ‘?’ do ‘id’ indica que aquele id é um atributo opcional. O id é usado em rotas geralmente quando é necessário atualizar ou excluir um registro em um banco de dados. Rotas múltiplas É possível usar múltiplas rotas, basta usar mais “maproute” no UseMvc. app.UseMvc(routes => { routes.MapRoute("produto", "produto/descricao", defaults: new { controller = "Blog", action = "Article" }); routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); }); Nesse caso, não se usa controller e action no template da rota. O controller produto, ação descricao seriam usados. Roteamento por atributos Roteamento por atributos usa uma coleção de atributos para mapear diretamente ações para rotas. public class HomeController : Controller { [Route("")] [Route("Home")] [Route("Home/Index")] public IActionResult Index() { return View(); } } No exemplo acima, se o usuário não estabelecer o que deseja acessar, se tentar acessar apenas /Home ou /Home/Index, ele será direcionado para a ação index, controller home de qualquer maneira. Roteamento por atributos Ainda é possível determinar qual ação será acessada através de requisições GET ou POST. [HttpGet("/Avioes")] public IActionResult ListarAvioes() { // ... } [HttpPost("/Avioes")] public IActionResult NovoAviao() { // ... } No exemplo acima, caso uma requisição GET chegue ao controlador, a ação ListarAvioes será acionada. Já se usa requisição POST chegar ao controlador, a ação NovoAviao será acionada. Roteamento por atributos Caso seja necessário atributos ou usar nomes em rotas, é bem simples também ! public class AvioesController : Controller { [HttpGet("/Avioes/{id}", Name = "AviaoEspecifico")] public IActionResult PegarAviaoPeloId(int id) { ... } } A ação será executada como Avioes/777 por exemplo. Roteamento por atributos com múltiplas rotas [Route("Aereos")] [Route("[controller]")] public class AvioesController : Controller { [HttpPost("PegarTodos")] [HttpPost("ListarTodos")] public IActionResult ListarTodos() } No exemplo acima, ao tentar acessar qualquer uma das rotas Aereos/PegarTodos, Aereos/ListarTodos, Avioes/PegarTodos e Avioes/ListarTodos implicará na ação ListarTodos, controller Avioes. Aula 6 – Models e Controllers Tópicos O que são models Codificando uma model O que são controllers O que são ActionResults Models São responsáveis pela manipulação de dados; São o “espelho” do banco de dados da aplicação; Realiza escrita, leitura e validação de dados. Exemplo model public class Carro { public int CarroId { get; set; } public string Modelo { get; set; } public string Marca { get; set; } public int Ano { get; set; } } Controllers Responsável pelas requisições do usuário. É ele que controla quais views e models serão utilizados public class HomeController : Controller { public IActionResult Inicio() { return View(); } public IActionResult Sobre() { return View(); } } ActionResults Classes que representam ações que serão realizadas no decorrer das interações do usuário com a aplicação public IActionResult Inicio() { return View(); } public IActionResult Sobre() { return Ok(); } public IActionResult Contato() { return NotFound(); } public IActionResult Curriculo() { return File("~/downloads/Curriculo.pdf", "application/pdf"); } public IActionResult Fim() { return Content("Fim ! Tenha um bom dia"); } Aula 07 – Object-Relational Mapping (ORM) Tópicos O que é um ORM Vantagens Desvantagens ORM – Object-Relational Mapping Mapeamento objeto relacional; Técnica de mapeamento objeto relacional; As tabelas do banco de dados são representadas através de classes; O programador não precisa se preocupar com comandos SQL para acessar o banco de dados; Exemplosde ORMs : Entity Framework, Hibernate e etc. ORM - Vantagens Ganho em produção; Mais fácil dar manutenção; Padronização da aplicação. ORM - Desvantagens Performance menor; Complexidade para se desenvolver uma boa arquitetura. Aula 08 – Primeiros passos com o Entity Framework Core Tópicos O que é o Entity Framework Core Abordagem Code-First Abordagem Database-First Entity Framework Core Versão leve, extensível e multiplataforma do entity framework; É o ORM padrão utilizado em projetos ASP NET CORE MVC; Possibilita desenvolvedores trabalhar com banco de dados usando objetos .NET; Elimina a necessidade de escrever a maior parte do código para acesso a dados que geralmente é necessário escrever; Trabalha com vários bancos de dados; Versão atual : 2.1 (26/08/2018). Abordagem code-first Nessa abordagem, a API no Entity Framework Core cria o banco de dados baseado nas convenções e configurações nas suas classes de domínio (models). Abordagem Database-First Nessa abordagem, a API do Entity Framework Core cria as classes de domínio e contexto baseado em um banco de dados existente usando comandos do EF CORE. Aula 09 - Razor Tópicos View Engine Razor Vantagens Algumas tag helpers Introdução ao Razor View engine utilizada para renderizar páginas. Possui uma sintaxe de marcação para incorporar código de servidor em páginas web. Essas sintaxe consiste na sintaxe razor, c# e html. Vantagens Provê uma experiência amigável, pois é bem parecido com HTML; Suporte intelliSense no Razor; Produtividade maior; Produção código mais robusto e mais fácil de dar manutenção. Algumas taghelpers <label asp-for=“Carro.Modelo”> Modelo </label> <input asp-for="Nome" class="form-control" /> <span asp-validation-for=“Email” class=“text-danger”> </span> <a asp-action="Index">Voltar</a> <a asp-action=“Excluir" asp-route-id="@item.CarroId">Excluir</a> Aula 10 – Implementação Code-First Tópicos O que é um dbContext Expressões Lambda Comandos Básicos Criação do primeiro CRUD (Create Retrieve Update Delete) Aula 11 – Implementação Database-First Tópicos Implementação Aula 12 – Mini Projeto I – Lista de tarefas Tópicos Implementação Aula 13 – Injeção de Dependência Tópicos O que é Implementação O que é Durante a criação de uma classe, a mesma deve ter suas dependências injetadas ao invés de criadas; Modos de ser feita : Via construtor; Via propriedades (get;set;); Via interface; Via algum framework. O que é Permite baixo acoplamento; Acoplamento significa o quão dependente uma classe é da outra. Implementação Modo errado public IActionResult Index() { var contexto = new TarefasContexto(null); return View(contexto.Tarefas.ToList()); } Dessa forma, é altamente acoplado pois a classe Index sabe muito a respeito do contexto, ou seja, sabe que ela é do tipo TarefasContexto. Implementação Modo correto private readonly TarefasContexto _contexto; public TarefasController(TarefasContexto contexto) { _contexto = contexto; } Desse modo, a variável _contexto está sendo construída via injeção de dependência e pode ser usada em qualquer ação dessa classe, sem essas ações saberem que _contexto é do tipo TarefasContexto. Além disso provocar o baixo acoplamento, também provoca a alta coesão, uma vez que as ações ficam responsáveis por apenas uma tarefa e não precisam instanciar _contexto. Implementação Ao injetar classes e interfaces, é necessário configurá-las no Startup services.AddSingleton<Interface, Classe>() services.AddScoped<Interface, Classe>() services.AddTransient<Interface, Classe>() Singleton -> Criação única de referência de classe em todo o ciclo de vida do projeto; Transient -> Criação de uma nova instância a cada dependência; Scoped -> Criação de apenas uma instância em todo o ciclo de vida da requisição. Aula 14 - Asynchronous Javascript and XML (Ajax) Tópicos O que é Ajax Implementação Ajax Asynchronous Javascript and XML Combinação do objeto XmlHttpRequest (para enviar e receber dados de um servidor), Javascript e DOM (HTML) para exibir informações. Ajax possibilita atualizar de modo assíncrono páginas web. Dessa forma, não é necessário recarregar a página inteira, apenas uma parte dela. Ajax não é linguagem de programação !!!! JSON JavaScript Object Notation; Sintaxe alternativa para enviar / receber dados; Alternativa ao XML. Pessoa { “Nome” : “Thiago”, “Idade” : “29” } Aula 15 – Task async e await Tópicos O que é task async e await Implementação Task async e await Utilizados em programação assíncrona; Permite a execução do programa na thread principal enquanto uma tarefa mais longa é executada na sua própria thread, separada da thread principal; Quando a execução da tarefa acabar, ela possibilitará que a thread principal saiba se a tarefa falhou ou deu tudo certo. Task async e await Task async é utilizado para deixar claro que a ação no controlador será executado de modo assíncrono. public async Task<IActionResult> Index () Então utilizamos await para parar a execução da thread atual até que o método assíncrono chamado tenha sido concluído. await _contexto.Tarefas.ToListAsync() Aula 16 – Partial Views Tópicos O que são Partial Views Implementação Partial Views São views renderizadas dentro de outras páginas; São “pedaços de views”; Ótimas para serem reutilizadas em várias páginas; Uma view pode possuir várias partial views; Partial Views Renderizando via HTML Helper Html.PartialAsync("MinhasNotas") / Html.PartialAsync("Aulas/MinhasNotas")/ Html.PartialAsync("Aulas/MinhasNotas.cshtml") Ainda é possível passar dados para essas views Html.PartialAsync("Aulas/MinhasNotas", AlunoId) Partial Views Utilizando RenderPartial @{ Html.RenderPartialAsync("MinhasNotas"); } Esse precisa ser chamado em um bloco de código do Razor. @{ Html.RenderPartialAsync("MinhasNotas“, Model); } Partial Views Utilizando Tag Helper <partial name = “MinhasNotas”/> Passando dados <partial name = “MinhasNotas” model = “Model”/> Aula 17 – View Components Tópicos O que são View Components Implementação View Components Parecidas com partial views; Permitem renderizar um pedaço de view; Podem receber parâmetros e ter alguma lógica de negócio; São invocadas por uma página de layout; Seu principal objetivo é ser reusável. Implementação Seu nome deve ter ViewComponent no final ProdutoViewComponent Ou ter o atributo ViewComponentAttribute [ViewComponentAttribute] Produto Deve herdar de ViewComponent ProdutoViewComponent : ViewComponent Implementação Suas instruções lógicas devem ficar dentro de Invoke ou InvokeAsync (assíncrono) public class ProdutosViewComponent : ViewComponent { public IViewComponentResult Invoke(int id) { return View(“Produtos", PegarTodos()); } } Implementação Será procurado pela view com nome Default dentro da pasta com o nome da ViewComponent. Produtos/Default Então basta chamar o componente na view necessária @await Component.InvokeAsync(“Produtos”); Aula 18 – Mini Projeto – Pesquisa Criptomoedas Tópicos Introdução Implementação Aula 19 - Áreas Tópicos O que são Implementação Áreas São usadas para organizar funcionalidades relacionadas em grupos, namespaces(para roteamento) e estruturas de pastas diferentes; Possibilitam dividir aplicações grandes em um grupo de funções menores. Áreas Crie uma pasta e nomeie-a “Areas”. Em seguida, crie outra pasta com o nome do subgrupo que você achar melhor, “Produtos”, por exemplo. Por último, crie as pastas para Models, Views e Controllers. Áreas É necessário informar ao controller a área a qual ele está associada. [Area("Products")] public class HomeController : Controller {} Então faça uma nova rota para deixar claro que está utilizando áreas routes.MapRoute( name: "area", template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); Áreas Ainda é possível nomear as rotas; app.UseMvc(routes => { routes.MapAreaRoute("RotaComArea", “Produtos", “ProdutosComArea/{controller}/{action}/{id?}"); routes.MapRoute("default_route", "{controller}/{action}/{id?}"); }); Dessa forma, quando a área “produto” for acessada, a url vista pelo usuário será “ProdutosComArea/nomedoController/nomedaAction Aula 20 – Validação de dados Tópicos Validação com data annotations Validação Remota Sobrescrita de validação Aula 20.1 – Validação com Data Annotations Tópicos Como funciona Validação de dados com Data Annotations Tipos de dados utilizados no DataType Validação de dados com Data Annotations Serve para validar o que foi digitado pelo usuário de acordo com as regras de negócio da aplicação. Validação de dados com Data Annotations A validação de dados é feita utilizando data annotations e jquery unobtrusive. Usa-se esses atributos entre colchetes. Required Campo Obrigatório StringLenght(100) O campo não pode ter mais de 100 caracteres DataType(DataType.Tipo) Esse campo é um tipo de dado específico RegularExpression Valida o campo através de uma expressão regular Range(1, 100) Esse campo só aceita valores entre 1 e 100 Compare Validar se 2 atributos são iguais Validação de dados com Data Annotations O framework valida até 200 campos (valor padrão) através do Model state; É possível configurar isso no ConfigureServices. services.AddMvc(options => options.MaxModelValidationErrors = 50); Tipos de dados utilizados no DataType CreditCard Cartão de crédito Currency Dinheiro Custom Tipo de dados personalizado Date Data Datetime Data e hora do dia Duration Tempo em que o objeto existe Tipos de dados utilizados no DataType EmailAddress Email Html Arquivo html ImageUrl URL para uma imagem MultilineText Texto de várias linhas Password Senha PhoneNumber Número de telefone PostalCode Código postal Tipos de dados utilizados no DataType Text Representa o texto a ser exibido Time Valor temporal Upload Upload de arquivo Url Representa um valor de url Aula 20.2 – Validação Remota Tópicos Como funciona Implementação Validação Remota Muito útil para validar informações no lado do cliente em relação aos dados no servidor; Permite validar se um usuário, CPF, email, etc já existe na base de dados; No atributo a ser validado, deve-se utilizar a anotação Remote e, em seguida, o método e o controller em que o método se encontra. [Remote(“Método", “Controller")] public Type Name { get; set; } [Remote("UsuarioExisteAsync", "Pessoas")] public string Nome { get; set; } Validação Remota Em seguida, deve-se codificar a ação que fará essa validação. public async Task<JsonResult> UsuarioExisteAsync (string nome) { if (await _context.Pessoas.AnyAsync(x => x.Nome == nome)) return Json("Usuário já existe !"); return Json(true); } Aula 20.3 - Validação personalizada Tópicos Como funciona Implementação Validação personalizada As validações padrões são herdadas de ValidationAttribute; Faça uma classe herdando de ValidationAttribute; A validação de dados deve ser feita sobrescrevendo o método isValid(). Validação personalizada public class AdultoAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { Pessoa pessoa = (Pessoa)validationContext.ObjectInstance; if (pessoa.Idade < 18) return new ValidationResult("Apenas adultos podem se cadastrar"); return ValidationResult.Success; } } Então deve-se adicionar a validação ao campo necessário. [Adulto] Public int Idade {get;set;} Aula 21 – Mais algumas anotações Tópicos Outras anotações Anotações para tabelas Outras anotações Display Exibe o que texto que você quiser [Display(Name=”ABC”)] DisplayFormat Exibe o que texto no formato que você quiser [DisplayFormat(DataFormat String = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] DatabaseGenerated Informa se os dados da chave primária serão fornecidos pelo usuário ou gerados pelo banco de dados [DatabaseGenerated(Datab aseGeneratedOption.None)] Anotações para as tabelas Table Permite mudar o nome que será criado no banco de dados [Table(“Pessoas”)] Column Permite melhorar o mapeamento de atributos para o banco de dados. É possível mudar o nome, tipo e ordem em que o atributo aparecerá na tabela [Column(“Nome", TypeName="ntext")] Key Chave primária da tabela. Pode ser usado mais de uma vez na mesma tabela, produzindo, desse forma, uma chave composta [Key] ForeignKey Chave estrangeira da tabela [ForeignKey(“Pessoa”)] Anotações para as tabelas DatabaseGenerated(D atabaseGeneratedOpti on.Computed) Especifica que o valor do atributo será gerado pelo banco de dados assim que o valor for salvo pela primeira vez e regerado sempre que o valor for atualizado [DatabaseGenerated(D atabaseGeneratedOpti on.Computed)] DatabaseGenerated(D atabaseGeneratedOpti on.Identity) Especifica que o valor do atributo será gerado pelo banco de dados apenas na primeira vez que for salvo [DatabaseGenerated(D atabaseGeneratedOpti on.Identity)] Anotações para as tabelas DatabaseGenerated(D atabaseGeneratedOpti on.None) Especifica que o valor do atributo não será gerado pelo banco de dados. Nesse caso, ele provavelmente será informado pelo usuário [DatabaseGenerated(D atabaseGeneratedOpti on.None)] Aula 22 – TempData Tópicos O que é Implementação TempData Usado para o armazenamento de dados temporários; Por padrão, toda a informação será apagada após a próxima requisição; Para a informação ser mantida, deve-se utilizar o método Keep(); TempData.Keep() Muito útil para transferir informações de uma ação para a outra. TempData Implementação TempData["nome"] = "Thiago"; TempData["idade"] = "29"; string nome; int idade; if (TempData.ContainsKey("nome")) nome = TempData["nome"].ToString(); if (TempData.ContainsKey("idade")) idade = int.Parse(TempData["idade"].ToString()); Aula 23 - ViewData Tópicos O que é Implementação ViewData Objeto dinâmico útil para transferir dados entre controller e view; É um dicionário que possui pares chave-valor; Cada chave deve ser uma string. // Código no controller IList<Produto> produtos = new List<Produto> { new Produto() { Nome = "Biscoito", Preco = 3.75 }, new Produto() { Nome = "Café", Preco = 5.25 }, new Produto() { Nome = "Pão", Preco = 0.45 } }; ViewData["produtos"] = produtos; ViewData //Código na View @foreach (var p in ViewData["produtos"] as IList<Produto>) { <ul> <li>@p.Nome</li> <li>@p.Preco</li> </ul> } ViewData Utilizando chave-valor. // Códigono controller ViewData.Add(new KeyValuePair<string, object>("Nome", "Thiago")); ViewData.Add(new KeyValuePair<string, object>("Idade", "29")); // Código na View <h2>@ViewData["Nome"]</h2> <h3>@ViewData["Idade"]</h3> Aula 24 - ViewBag Tópicos O que é Implementação ViewBag Objeto dinâmico; Muito parecido com ViewData; Usado para passar dados do controller para a view. //controller IList<Produto> produtos = new List<Produto>(); produtos.Add(new Produto { Nome = "Café", Preco = 3.50 }); produtos.Add(new Produto { Nome = "Leite", Preco = 1.25 }); produtos.Add(new Produto { Nome = "Açucar", Preco = 4.75 }); ViewBag.produtos = produtos; ViewBag // view @foreach(var p in ViewBag.produtos) { <ul> <li>@p.Nome</li> <li>@p.Preco</li> </ul> } Aula 25 – Modelagem Relacional no Entity Framework Tópicos Modelagem Relacional Introdução Entity Framework Fluent API Configurando relacionamentos 0..1 e 1..1 Configurando relacionamentos 1..N Configurando relacionamentos N..N Aula 25.1 – Modelagem Relacional Tópicos Modelagem Relacional Introdução Entity Framework Fluent API Modelagem Relacional Modelagem utilizada para representar dados em um banco de dados como uma coleção de tabelas; Cada tabela possuí um nome único e seu conjunto de atributos com seus nomes e domínios; As tabelas podem ter relacionamentos 0..1, 0..N, 1..1, 1..N e N..N. Introdução Entity Framework Fluent API Usada para configurar relacionamentos entre classes; Suporta diversos tipos de mapeamento; O mapeamento da classe é configurado sobrescrevendo o método OnModelCreating no seu contexto(DbContext). Introdução Entity Framework Fluent API HasKey -> Define a chave primária; HasColumnName -> Define o nome da coluna que será criada no banco de dados; HasColumnType -> Define o tipo de dado da coluna que será criada no banco de dados; HasMaxLenght -> Define a quantidade máxima de caracteres em um atributo varchar; IsRequired -> Define se o atributo pode ter valor nulo ou não; ToTable -> Define o nome da tabela que será criada no banco de dados. Introdução Entity Framework Fluent API protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Pessoa>().HasKey(x => x.PessoaId); modelBuilder.Entity<Pessoa>().Property(x => x.Nome).HasColumnName("Nome").HasColumnType("varchar").HasMaxLength(50).I sRequired(); modelBuilder.Entity<Pessoa>().Property(x => x.Idade).HasColumnName("Idade").HasColumnType("int").IsRequired(false); modelBuilder.Entity<Pessoa>().Property(x => x.Peso).HasColumnName("Peso").HasColumnType("float").IsRequired(false); modelBuilder.Entity<Pessoa>().ToTable("Pessoas"); } Aula 25.2 – Configurando relacionamentos 0..1 e 1..1 Tópicos Configurando relacionamentos 0..1 Configurando relaciomantos 1..1 Configurando relacionamentos 0..1 Nesse mapeamento 0..1, indica que uma pessoa pode ter 0 ou 1 endereços, ou seja, endereço é opcional; Endereço estará obrigatoriamente ligado a alguma pessoa. Configurando relacionamentos 1..1 Nesse mapeamento, uma pessoa estará obrigatoriamente relacionado a um e apenas um endereço; Um endereço estará relacionado a uma e apenas uma pessoa; Caso tente relacionar um endereço a mais de uma pessoa, a aplicação apresentará um erro. Configurando relacionamentos 1..1 Mapeamento Pessoa modelBuilder.Entity<Pessoa>() .HasOne(x => x.Endereco) .WithOne(x => x.Pessoa) .HasForeignKey<Pessoa>(x => x.EnderecoId); Mapeamento Endereço modelBuilder.Entity<Endereco>() .HasOne(x => x.Pessoa) .WithOne(x => x.Endereco); Aula 25.3 – Configurando relacionamentos 1..N Tópicos Configurando relacionamentos 1..N Configurando relacionamentos 1..N Nesse mapeamento, um empregado estará relacionado a apenas um trabalho; No entanto, um trabalho poderá estar relacionado a 1 ou vários empregados. Configurando relacionamentos 1..N Mapeamento Empregado modelBuilder.Entity<Empregado>() .HasOne(x => x.Trabalho) .WithMany(x => x.Empregados) .HasForeignKey(x => x.TrabalhoId); Mapeamento Trabalho modelBuilder.Entity<Trabalho>() .HasMany(x => x.Empregados) .WithOne(x => x.Trabalho); Aula 25.4 – Configurando relaciomentos N..N Tópicos Configurando relacionamentos N..N Configurando relacionamentos N..N Em uma mapeamento N..N, é necessário criar uma nova tabela para auxiliar nesse relacionamento. Empregado está relacionado a um ou vários Emprego_Trabalho e Emprego_Trabalho está relacionado a apenas um empregado; Trabalho está relacionado a um ou vários Emprego_Trabalho e Emprego_Trabalho está relacionado a apenas um Trabalho. Configurando relacionamentos N..N modelBuilder.Entity<EmpregadoTrabalho>().HasKey(x => new { x.EmpregadoId, x.TrabalhoId }); modelBuilder.Entity<EmpregadoTrabalho>() .HasOne(x => x.Empregado) .WithMany(x => x.EmpregadoTrabalhos) .HasForeignKey(x => x.EmpregadoId); modelBuilder.Entity<EmpregadoTrabalho>() .HasOne(x => x.Trabalho) .WithMany(x => x.EmpregadoTrabalhos) .HasForeignKey(x => x.TrabalhoId); Configurando relacionamentos N..N Aula 26 – Procura de registros Tópicos O que é Implementação Procura de registros A procura de registros é feita através de um formulário; Este formulário possui um campo para o usuário digitar o termo de pesquisa; Esse campo tem um nome que será interceptado no controller; Esse termo é, então, passado para o controller para que possa ser feita uma consulta ao banco de dados; O resultado da procura no banco de dados é enviado para a view e então exibido aos usuários. Aula 27 - Paginação Tópicos O que é Implementação Paginação A utilidade da paginação é mostrar uma quantidade N de registros em uma página; O restante dos registros é exibido na próxima página; Isso ajuda no tempo de carregamento da aplicação; Uma das várias formas de se fazer paginação em ASP NET CORE MVC, é utilizando o pacote X.PagedList.Mvc.Core. Paginação Adicione o X.PagedList ao controller; using X.PagedList; Em seguida, faça a ação responsável pela paginação receber a página atual dos registros; public async Task<IActionResult> Index(int? pagina) { const int itensPorPagina = 5; int numeroPagina = (pagina ?? 1); return View(await _context.Pessoas.ToPagedListAsync(numeroPagina, itensPorPagina)); } Paginação Ajuste a sua view @model X.PagedList.IPagedList<Paginacao.Models.Pessoa> @using X.PagedList.Mvc.Core E então use o html helper para gerar a paginação @Html.PagedListPager(Model, pagina => Url.Action("Index", new { pagina })) Aula 28 – Utilizando ViewModels Tópicos O que são Implementação ViewModels ViewModel é um objeto que tem o objetivo de apenas receber ou exibir dados ao usuário; Não está relacionado com banco de dados; Não é mapeado para uma tabela em banco de dados. Aula 29 – Projeto Módulo Iniciante – Gerenciador de Despesas Tópicos Introdução Implementação Gerenciador de despesas Aula 30 – Trabalhando com imagens Tópicos O que é Formas de se usar Armazenando imagens no banco de dados Armazenando apenas links das imagens no banco de dados Imagens Armazenar imagens de usuários, produtos, paisagens e etc para uso futuro; As formas mais utlizadas para se armazenar imagens são; Salvar a imagem no banco de dados; Salvar apenas a url da imagem no banco de dados e a imagem em um diretório / pasta. Aula 30.1 – Salvandoimagens no banco de dados Tópicos Como funciona Vantagens Desvantagens Implementação Imagens no banco de dados Imagens no banco de dados A imagem é salva no banco de dados em formato hexadecimal (exemplo). Vantagens Simplicidade no procedimento em caso de mudança de imagens; Diminui o risco de acesso não autorizado; Não é necessário implementar estratégia de backup diferente; Eficiente quando há poucas imagens. Desvantagens A medida que a quantidade de imagens aumentar, o espaço necessário no banco de dados será maior; Aumenta-se os custos e cai o desempenho do banco de dados; O desempenho no acesso a esses arquivo é menor. Implementação No arquivo Startup.cs, configure sua aplicação para usar arquivos estáticos; app.UseStaticFiles(); Na view, não esqueça de colocar enctype no form, ter um input do tipo file a atribuir um nome a ele; <form asp-action="Create" enctype="multipart/form-data"> <input type="file" class="form-control" name="Image" id="Image" /> O nome da imagem (Image) deverá ser utilizado no controller. Ele se transformará em um parâmetro para o controller conseguir pegar essa imagem Implementação No controller, tenha um parâmetro do tipo IFormFile com o nome do input usado na view. public async Task<IActionResult> Create([Bind("PessoaId,Foto")] Pessoa pessoa, IFormFile Image) Implementação Então basta converter essa imagem. if (Image != null) { byte[] b; using (var or = Image.OpenReadStream()) { using (var ms = new MemoryStream()) { or.CopyTo(ms); b = ms.ToArray(); } pessoa.Foto = b; } } Implementação Já para a visualização.... Use o Url.Action para montar a url da imagem; <img src="@Url.Action("PegarImagem", "Pessoas", new { id = item.PessoaId })" /> E não se esqueça de fazer a ação para retornar a imagem. public IActionResult PegarImagem(int id) { byte[] b = _context.Pessoas.Find(id).Foto; return File(b, "image/jpg"); } Aula 30.2 – Salvando links de imagens no banco de dados Tópicos Como funciona Vantagens Desvantagens Implementação Links de imagens salvos no banco de dados Links de imagens salvos no banco de dados Salvar apenas a url da imagem no banco de dados e a imagem em um diretório / pasta. Vantagens Menor custo; Armazenar em um sistema de arquivo é mais barato do que armazenar em um banco de dados; Maior desempenho do banco de dados. Desvantagens Precisa de um gerenciamento mais eficiente, pois ao se excluir a imagem no banco de dados, você estará excluindo apenas a url da imagem, não a imagem por si só; A imagem não estará armazenada no banco de dados, então será preciso se preocupar com a estratégia de backup da mesma; Risco em relação a segurança maior. Apesar de usuários mal intencionados não conseguiram acessar a imagem através do banco de dados, podem fazer isso através do sistema de armazenamento do arquivo; Problemas com portabilidade. Implementação No arquivo Startup.cs, configure sua aplicação para usar arquivos estáticos; app.UseStaticFiles(); Então devemos criar a pasta para onde as imagens serão salvas. Nesse exemplo, o nome da pasta é Imagens; Na view, não esqueça de colocar enctype no form, ter um input do tipo file a atribuir um nome a ele. <form asp-action="Create" enctype="multipart/form-data"> <input type="file" class="form-control" name="Image" id="Image" /> O nome da imagem (Image) deverá ser utilizado no controller. Ele se transformará em um parâmetro para o controller conseguir pegar essa imagem. Implementação No controller, tenha um parâmetro do tipo IFormFile com o nome do input usado na view. public async Task<IActionResult> Create([Bind("PessoaId,Link")] Pessoa pessoa, IFormFile imagem) Implementação Defina o link que a imagem será salva var linkUpload = Path.Combine(_environment.WebRootPath, "Imagens"); Crie o arquivo na pasta e insira seu link no banco de dados if (imagem != null) { using (var fileStream = new FileStream(Path.Combine(linkUpload, imagem.FileName), FileMode.Create)) { await imagem.CopyToAsync(fileStream); pessoa.Link = "~/Imagens/" + imagem.FileName; } } Implementação Para exibir essa imagem na view, basta utilizar <img src="@Url.Content(item.Link)" width="400" height="400"/> Aula 31 – Álbum de Fotos Tópicos Implementação Aula 32 – Trabalhando com CSV Tópicos O que são Implementação Trabalhando com arquivos CSV Comma-Separated values Arquivo de valores separados por vírgulas; Arquivos com extensão .csv são planilhas utilizadas em vários softwares. Excel, Libre Calc e Google Sheets são exemplo de softwares voltados à planilhas; Exportar tabelas HTML para planilhas é amplamente utilizado em diversas empresas no mundo afora. Implementação Pegue os registros necessários var registros = _context.Pessoas.ToList(); Crie uma variável do tipo StringBuilder e define o cabeçalho da tabela; StringBuilder arquivo = new StringBuilder(); arquivo.AppendLine("PessoaId;Pessoa;Idade"); Percorra a lista de registros e adicione-os na sua variável foreach(var item in registros) { arquivo.AppendLine(item.PessoasId + ";" + item.Nome + ";" + item.Idade + ";"); } Implementação Basta retornar o arquivo codificado, definir seu tipo e nome. return File(Encoding.ASCII.GetBytes(arquivo.ToString()), "text/csv", "dados.csv"); Aula 33 – Trabalhando com arquivos PDF Tópicos O que é Implementação Trabalhando com arquivos PDF Portable Document Format; Formato arquivo desenvolvido pela Adobe; Permite representar arquivos de maneira independente de aplicativos; É muito comum a exportação de arquivos PDF para a produção de relatórios; Utilizaremos o pacote Rotativa.AspNetCore para tal tarefa. Implementação Instale o pacote Rotativa.AspNetCore na sua aplicação; Crie uma pasta chamada “rotativa” no wwwroot e copie os seguintes arquivos para lá : help-wkhtmltoimage.txt, help-whhtmltopdf.txt, whhtmltopdf.exe, whhtmltoimage.exe; Especifique no arquivo Startup.cs que você está utilizando o rotativa. RotativaConfiguration.Setup(env); Implementação Então basta retornar a view como PDF, passar alguma model para ela (opcional) e definir o nome do arquivo (opcional) public IActionResult VisualizarComoPDF() { return new ViewAsPdf("PDF", _context.Pessoas.ToList()) { FileName = "Dados.pdf" }; } Aula 34 - Sessões Tópicos O que é Implementação Sessões Sessões possibilitam salvar e armazenar dados enquanto o usuário navega pelo seu sistema. Os dados continuam armazenados após solicitações. Esses dados são excluídos quando a sessão expira (20 min valor padrão) ou quando se faz isso manualmente (Session.Clear). Implementação Para usá-las, adicione as linhas abaixo no Startup.cs services.AddSession(); Ainda é possível configurar as sessões services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(10); }); Em seguida, na função configure, adicione o comando app.UseSession() (deve vir antes de app.UseMvc). Implementação É possível adicionar dados do tipo string ou inteiro em sessões. Basta utilizar HttpContext.Session.SetString("Pessoa", "Thiago"); HttpContext.Session.SetInt32("Idade", 29); Para pegar esses valores, basta utilizar o comando get ViewData["Pessoa"] = HttpContext.Session.GetString("Pessoa"); ViewData["Idade"] = HttpContext.Session.GetInt32("Idade"); Então basta chamar os ViewDatasna view <h2>@ViewData["Pessoa"]</h2> <h3>@ViewData["Idade"]</h3> Aula 35 – Cookies Tópicos O que é Implementação Cookies São pequenos arquivos armazenados no navegador do usuário; Seguem o padrão chave-valor; Podem ser usados com várias finalidades, como por exemplo, identificar um usuário que já visitou o seu site. Implementação Primeiro, deve-se configurar o cookie. Para essa tarefa, utilizamos a classe CookieOptions; CookieOptions cookie = new CookieOptions(); cookie.Expires = DateTime.Now.AddHours(1); cookie.HttpOnly = true; cookie.Secure = true; Para escrever um cookie, utilizamos o Response.Cookies.Append(“Identificador”, “Valor”, Opções); Response.Cookies.Append("Visitante", "Sim", cookie); Implementação Para ler os valores de um cookie, utilizado o Request.Cookies[“Identificador”]; Request.Cookies["Visitante"] Para excluir um cookie, utilizamos o Response.Cookies.Delete(“Identificador"); Response.Cookies.Delete("Visitante"); Aula 36 – Autenticação por cookies (cookieAutentication) Tópicos O que é Implementação Autenticação por cookies Às vezes, é necessário apenas prover um modo de o usuário logar e deslogar em uma aplicação sem muita sofisticação e complexidade; É nessa hora que se usa a autenticação por cookies (cookie authentication); Autenticação por cookies provê uma forma simples e rápida de autenticação, sem muitas funções adicionais; Não é necessário utilizar o ASP NET CORE Identity (será visto em outra aula). Implementação Primeiro deve-se criar a parte de registro de usuários. Esse registro é um registro normal, o usuário insere seus dados em um formulário e esses são salvos em um banco de dados; Então crie um formulário para login e após receber os dados digitados pelo usuário, consulte o banco de dados para ver se o mesmo existe; if (_contexto.Pessoas.Any(x => x.Nome == p.Nome && x.Senha == p.Senha)) Implementação Então use um atributo ou conjunto de atributos (claim – será visto com mais detalhes em outra aula) para validar que esse usuário é realmente ele var claims = new List<Claim> { new Claim(ClaimTypes.Name, p.Nome) }; Agora use esse atributo para criar uma identidade e permitir o login do usuário var userIdentity = new ClaimsIdentity(claims, "login"); Associe esse atributo a um ClaimsPrincipal para representar a autenticação desse usuário; ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity); Implementação E finalmente autentique esse usuário await HttpContext.SignInAsync(principal); Para deslogar esse usuário, basta utilizar await HttpContext.SignOutAsync(); Implementação Já para configuramos a aplicação, devemos fazê-lo no Startup.cs; services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Home/Login"; }); E então deixar claro que estamos utilizando autenticação de usuários. app.UseAuthentication(); Implementação Não esqueça de colocar Authorize nos controllers e actions que exigem autenticação. [Authorize()] public IActionResult Contato() Aula 37 – Mini Projeto – Sistema para montagem de currículo Tópicos Introdução Implementação Aula 38 – Cache Tópicos O que é Implementação Cache Possibilita armazenar dados na memória cache do servidor; Pode otimizar e melhorar a escalabilidade de um sistema reduzindo a carga necessária para exibir informações; Funciona melhor com dados que não mudam com frequência; Faz uma cópia de dados e possibilita que sejam exibidos mais rápido; Utiliza-se a interface IMemoryCache. Implementação Deve-se habilitá-la no Startup.cs services.AddMemoryCache(); Crie uma variável do tipo IMemoryCache; private readonly IMemoryCache _cache; Implementação Configure o cache utilizando MemoryCacheEntryOptions var opcoesCache = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(30)); Crie o cache passando para ele seu identificador, valor e configuração Datetime horaAtual = DateTime.Now; _cache.Set(“TesteCache", horaAtual, opcoesCache); É possível verificar se o cache já existe e ele possui algum valor _cache.TryGetValue(" TesteCache ", out horaAtual); Implementação Na view, use os dados com cache e sem cache e veja a diferença <div class="col-md-3"> <h3> Hora atual: @DateTime.Now.ToString()</h3> </div> <div class="col-md-3"> <h3>Hora atual no cache: @Model.Value.ToString()</h3> </div> Aula 39 – Padrão Repositório Tópicos O que é Implementação Padrão Repositório Cria uma camada de abstração entre a camada de acesso de dados e a camada de lógica de negócio. Promove uma abordagem para baixo acoplamento para o acesso a dados. Centraliza o acesso aos dados Deve-se criar uma interface e listar todos os métodos nela; A classe que herdar dessa interface, deverá fazer a implementação dos métodos. Implementação Interface interface IPessoaRepository { IEnumerable<Pessoa> PegarTodos(); Pessoa PegarPeloId(int pessoaId); void InserirPessoa(Pessoa pessoa); void AtualizarPessoa(Pessoa pessoa); void ExcluirPessoa(int pessoaId); void Salvar(); } Implementação Classe que implementa os métodos public class PessoaRepository : IPessoaRepository { // variáveis e construtores public void AtualizarPessoa(Pessoa pessoa) { _contexto.Entry(pessoa).State = EntityState.Modified; } Implementação public void ExcluirPessoa(int pessoaId) { Pessoa pessoa = _contexto.Pessoas.Find(pessoaId); _contexto.Pessoas.Remove(pessoa); } public void InserirPessoa(Pessoa pessoa) { _contexto.Pessoas.Add(pessoa); } public Pessoa PegarPeloId(int pessoaId) { return _contexto.Pessoas.Find(pessoaId); } Implementação public IEnumerable<Pessoa> PegarTodos() { return _contexto.Pessoas.ToList(); } public void Salvar() { _contexto.SaveChanges(); } } Implementação Registre no Startup.cs services.AddTransient<IPessoaRepository, PessoaRepository>(); Agora basta chamar os métodos nas ações public IActionResult Index() { return View(_repository.PegarTodos()); } Aula 40 – Repositório Genérico Tópicos O que é Implementação Repositório Genérico Possibilita criar um único repositório genérico para todas as classes; Possibita reúso de código; Provê baixo acoplamento. Implementação Liste os métodos em uma interface public interface IRepositorioGenerico<TEntity> where TEntity : class { IQueryable<TEntity> PegarTodos(); Task<TEntity> PegarPeloId(int id); Task Inserir(TEntity entity); Task Atualizar(TEntity entity); Task Excluir(int id); } Implementação Implemente os métodos public class RepositorioGenerico<TEntity> : IRepositorioGenerico<TEntity> where TEntity : class { private readonly Contexto _contexto; public GenericRepository(Contexto contexto) { _contexto = contexto; } public IQueryable<TEntity> PegarTodos() { return _contexto.Set<TEntity>(); } Implementação public Task<TEntity> PegarPeloId(int id) { return _contexto.Set<TEntity>().FindAsync(id); } public async Task Inserir(TEntity entity) { await _contexto.Set<TEntity>().AddAsync(entity); await _contexto.SaveChangesAsync(); } public async Task Atualizar(TEntity entity) { _contexto.Set<TEntity>().Update(entity); await _contexto.SaveChangesAsync(); } Implementação public async Task Excluir(int id) { var entity = await PegarPeloId(id); _contexto.Set<TEntity>().Remove(entity);await _contexto.SaveChangesAsync(); } Implementação Escreva uma interface que herde de IRepositorioGenerico. Isso possibilitará acesso aos métodos. public interface IPessoaRepositorio : IRepositorioGenerico<Pessoa> { } Faça uma classe herdado de RepositorioGenerico para ter acesso aos métodos já implementados e implemente os métodos da interface IPessoaRepositorio public class PessoaRepository : GenericRepository<Pessoa>, IPessoaRepository { public PessoaRepository(Contexto contexto) : base(contexto) { } } Aula 41 – Projeto Módulo Intermediário – Ficha de Academia Tópicos Introdução Implementação Ficha de Academia Aula 42 – Logging Tópicos O que é Implementação Logging Logging é uma forma de mostrar atividades, erros e outros eventos ocorridos em um sistema; Ajuda a fazer auditorias e rastrear a origem de problema; Em ASP.NET CORE MVC, usa-se o namespace Microsoft.Extensions.Logging. Log Levels Level Nível Método Descrição Trace 0 LogTrace() Usado por desenvolvedores para rastreamento Debug 1 LogDebug() Usado no debug de aplicações Information 2 LogInformation() Usado para mensagens no fluxo da aplicação Warning 3 LogWarning Usado para eventos anormais ou inesperados no fluxo da aplicação Log Levels Error 4 LogError() Mensagens de erros Critical 5 LogCritical() Falhas que precisam de atenção imediata Implementação Adicione o serviço de logging no startup services.AddLogging(); services.AddSingleton<ILoggerFactory, LoggerFactory>(); Em seguida, crie uma variável do tipo ILooger e injete as dependências no controller a ser utilizado private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } Implementação Então basta utilizar os métodos para começar a exibir as mensagens _logger.LogWarning(“Entrando no Index"); _logger.LogError(“Erro na inserção no about"); _logger.LogCritical("Erro de conexão"); Aula 43 – Gerenciamento de Erros Tópicos O que é Implementação Gerenciamento de páginas de erros O gerenciamento de erros é importante para saber o comportamento inesperado que o sistema está tendo; Existem vários códigos de erros, tais como : 404 – Página não encontrada 500 – Erro no servidor Gerenciamento de páginas de erros Implementação Configure onde serão recebidos os códigos de erros no startup.cs app.UseStatusCodePagesWithReExecute("/Erros/{0}"); Em seguida, crie um controller com uma ação para receber esses códigos e coloque o roteamento adequado public class ErrosController : Controller { [HttpGet("Erros/{codigoErro}")] public IActionResult Index(int codigoErro) { return View(codigoErro); } } Implementação Crie uma view e defina as mensagens de erro @model int @{ var codigoErro = Model; var mensagem = ""; Implementação switch (codigoErro) { case 404: mensagem = "Página não encontrada"; break; case 500: mensagem = "Erro no servidor - O servidor não conseguiu completar a requisição"; break; default: mensagem = "Erro - Algo inesperado aconteceu"; break; } } Implementação <div class="jumbotron"> <h1>Erro @Model</h1> <h3>@mensagem</h3> </div> Aula 44 – Envio de emails Tópicos O que é Implementação Envio de emails Para o envio de emails, é necessário ter um servidor SMTP. Usaremos o do google. O endereço do servidor é smtp.gmail.com A porta do servidor é 587 Configure a sua conta para permitir aplicativos menos seguros https://myaccount.google.com/u/0/lesssecureapps?pageId=none Envio de emails Não é necessário utilizar o gmail sempre; É possível utilizar outros provedores de email. Servidor Endereço SMTP Porta Yahoo smtp.mail.yahoo.com 587 Gmail smtp.gmail.com 587 Hotmail smtp.live.com 587 Implementação Configure o email no appsenttings.js "ConfiguracoesEmail": { "Endereco": "smtp.gmail.com", "Porta": "587", "Email": “SeuEmail", "Senha": “SuaSenha", "Destinatario": “Email" } Implementação Crie uma classe idêntica ao objeto criado no appsettings.js. Essa classe receberá posteriormente a configurações do email public class ConfiguracoesEmail { public string Endereco { get; set; } public int Porta { get; set; } public string Email { get; set; } public string Senha { get; set; } public string Destinatario { get; set; } } Implementação Crie uma interface com método a ser utilizado para enviar o email public interface IEmail { Task EnviarEmail(string email, string assunto, string mensagem); } Implementação Então crie uma classe que implemente esse método e injete as configurações na classe ConfiguracoesEmail public class Email : IEmail { public ConfiguracoesEmail _configuracoesEmail; public Email(IOptions<ConfiguracoesEmail> configuracoesEmail) { _configuracoesEmail = configuracoesEmail.Value; } Implementação Implemente o método public async Task EnviarEmail(string email, string assunto, string mensagem) { string destinatario = string.IsNullOrEmpty(email) ? _configuracoesEmail.Email : email; MailMessage mail = new MailMessage() { From = new MailAddress(_configuracoesEmail.Email, "Thiago Paiva Medeiros") }; Implementação mail.To.Add(new MailAddress(destinatario)); mail.Subject = assunto; mail.Body = mensagem; mail.IsBodyHtml = true; mail.Priority = MailPriority.High; using (SmtpClient smtpClient = new SmtpClient(_configuracoesEmail.Endereco, _configuracoesEmail.Porta)) { smtpClient.Credentials = new NetworkCredential(_configuracoesEmail.Email, _configuracoesEmail.Senha); smtpClient.EnableSsl = true; await smtpClient.SendMailAsync(mail); } } Implementação Não esqueça de registrar as configurações do email no startup.cs services.Configure<ConfiguracoesEmail>(Configuration.GetSection("Configuracoe sEmail")); Registre a interface e classe que a implementa no startup.cs para possibilitar a injeção de dependência services.AddTransient<IEmail, Email>(); Aula 45 – ASP NET CORE Identity Aula 45.1 – Introdução ASP NET CORE Identity Tópicos O que é Implementação Introdução ASP NET CORE Identity Sistema de associação que permite adicionar a funcionalidade de gerenciamento de usuários ao aplicativo; Usuários podem utilizar provedores externos para realizar login e cadastro em aplicativos, como por exemplo, Twitter, Linkedin e Facebook; Pode ser configurado para utilizar bancos de dados na nuvem (Azure, por exemplo); Utilizamos o namespace Microsoft.AspNetCore.Identity. Introdução ASP NET CORE Identity Ele permite : I. Criar usuários; II. Criar privilégios (roles); III. Associar usuários a roles; IV. Recuperar senhas; V. Efetuar login / logout de usuários VI. Validação de contas e etc. Aula 45.2 – Criação de usuários no ASP NET CORE Identity Tópicos Implementação Criação de usuários A tabela usada para cadastro de usuários já possui atributos padrão; Criação de usuários Para a inserção de novos atributos, é necessário herdar de IdentityUser e adicionar os atributos nessa classes; public class Usuario : IdentityUser { public string SobreNome { get; set; } public int Idade { get; set; } } Criação de usuários O contexto deve herdar de IdentityDbContext; public class Contexto : IdentityDbContext { public Contexto(DbContextOptions<Contexto> opcoes): base(opcoes) { } } O contextodeve herdar de IdentityDbContext<TEntity> caso o Identity estiver sendo personalizado; public class Contexto : IdentityDbContext<Usuario> { public DbSet<Usuario> Usuarios { get; set; } public Contexto(DbContextOptions<Contexto> opcoes): base(opcoes) { } } Criação de usuários Faça a configuração no startup.cs services.AddDefaultIdentity<Usuario>().AddEntityFrameworkStores<Contexto>(); Configure a autenticação app.UseAuthentication(); Criação de usuários É possível configurar as opções de cadastro de usuário services.Configure<IdentityOptions>(opcoes => { opcoes.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; opcoes.User.RequireUniqueEmail = true; }); O valor padrão de RequireUniqueEmail é false. Criação de usuários Antes de criar o usuário, é necessário configurar a senha. Por padrão, as senhas no Identity devem ter caracteres maiúsculos e minúsculos, números e caracteres especiais. Senhas ainda deve ter, no mínimo, 6 caracteres. Comando Descrição Valor Padrão RequireDigit Obriga a senha a ter números true RequiredLenght Tamanho mínimo da senha 6 RequireLowerCas e Obriga a senha a ter caracteres minúsculos true Criação de usuários RequireNonAlpha numeric Obriga a senha a ter caracteres especiais true RequireUniqueCh ars Quantidade de caracteres repetidos na senha 1 RequireUppercase Obriga a senha a ter caracteres maiúsculos true Criação de usuários Isso deve ser configurado no startup services.Configure<IdentityOptions>(opcoes => { opcoes.Password.RequireDigit = true; opcoes.Password.RequireLowercase = true; opcoes.Password.RequireNonAlphanumeric = true; opcoes.Password.RequireUppercase = true; opcoes.Password.RequiredLength = 6; opcoes.Password.RequiredUniqueChars = 1; }); Criação de usuários Faça a injeção de dependência private readonly SignInManager<Usuario> _gerenciadorLogin; private readonly UserManager<Usuario> _gerenciadorUsuarios; public ContasController(SignInManager<Usuario> gerenciadorLogin, UserManager<Usuario> gerenciadorUsuarios) { _ gerenciadorLogin = gerenciadorLogin; _ gerenciadorUsuarios = gerenciadorUsuarios; } SignInManager -> Usado para efetuar login / logout de usuários UserManager -> Usado para a criação dos usuários Criação de usuários Após receber os dados, verifique se os mesmos são válidos e crie o usuário [HttpPost] public async Task<IActionResult> Registro(RegistroViewModel registro) { if(ModelState.IsValid) { var usuario = new Usuario { UserName = registro.Nome, Idade = registro.Idade, SobreNome = registro.SobreNome }; var result = await _gerenciadorUsuarios.CreateAsync(usuario, registro.Senha); Criação de usuários Caso a criação seja feita com sucesso, é possível logar o usuário no sistema em seguida if(result.Succeeded) { await _gerenciadorLogin.SignInAsync(usuario, false); return RedirectToAction("Index", "Home"); } } return View(registro); } Criação de usuários Já para realizar o logout do usuário, basta utilizar SignOut() [HttpPost] public async Task<IActionResult> Logout() { if (User.Identity.IsAuthenticated) await _gerenciadorLogin.SignOutAsync(); return RedirectToAction("Index", "Home"); } Aula 45.3 – Criação de roles no ASP NET CORE Identity Tópicos Implementação Criação de roles Assim como a tabela de usuários, a tabela de roles também já possui atributos padrões Criação de roles Para a personalização das roles, pode-se criar outra classe herdado de IdentityRole e adicionar novos atributos public class NivelAcesso : IdentityRole { public string Descricao { get; set; } } Criação de roles Mude a classe contexto e adicione IdentityRole e string public class Contexto : IdentityDbContext<Usuario, NivelAcesso, string> { public DbSet<Usuario> Usuarios { get; set; } public DbSet<NivelAcesso> NiveisAcessos { get; set; } public Contexto(DbContextOptions<Contexto> opcoes): base(opcoes) { } } Atualize o startup services.AddIdentity<Usuario, NivelAcesso>().AddEntityFrameworkStores<Contexto>(); Criação de roles Declare a variável do tipo RoleMananer e injete a sua dependência private readonly RoleManager<NivelAcesso> _gerenciadorNivelAcesso; public NivelAcessosController(RoleManager<NivelAcesso> gerenciadorNivelAcesso) { _gerenciadorNivelAcesso = gerenciadorNivelAcesso; } Verifique se essa role já existe bool roleExiste = await _gerenciadorNivelAcesso.RoleExistsAsync(nivelAcesso.Name); Criação de roles Caso não existe, crie-a if (!roleExiste) { await _gerenciadorNivelAcesso.CreateAsync(nivelAcesso); } Aula 45.4 – Associação de usuários à roles Tópicos Implementação Associação de usuários à roles A tabela AspNetUserRoles é usada exatamente para isso; Ela possibilita um relacionamento M:N entre IdentityUser e IdentityRole; Para associar um usuário à uma role, basta utilizar a função AddToRoleAsync(Tuser User, string NomeRole) Implementação Crie uma ação que possua todas os usuários e roles public IActionResult Create() { ViewData["UserId"] = new SelectList(_context.Usuarios.ToList(), "Id", "UserName"); ViewData["RoleId"] = new SelectList(_context.NiveisAcessos.ToList(), "Name", "Name"); return View(); } Implementação Após receber o id do usuário e o nome da role, encontre esse usuário e associe-o à essa role public async Task<IActionResult> Create(UsuariosRolesViewModel usuariosRoles) { if (ModelState.IsValid) { var usuario =await _userManager.FindByIdAsync(usuariosRoles.UserId); await _userManager.AddToRoleAsync(usuario, usuariosRoles.Role); return View("Home/Index"); } return View(usuariosRoles); } Aula 45.5 – Login / Logout de usuários Tópicos Implementação Login / logout de usuários Para o login de usuários, basta utilizar _signInManager.SignInAsync(usuario, false); O segundo atributo especifica a possibilidade de se lembrar os dados do usuário Para o logout do usuário, basta utilizar _signInManager.SignOutAsync(); Aula 46 – Testes unitários Tópicos Introdução Implementação Testes unitários Forma de se testar unidades (módulos) individuais de sistema; Permite testar se cada unidade realmente faz o que deveria fazer; Bibliotecas que podem ser usadas : MsTest, XUnit, NUnit, etc. Testes unitários com xUnit O primeiro passo é criar um projeto utilizando o xUnit na aba testes do Visual Studio; Então é possível usar 2 atributos nos métodos a serem testados : Fact e Theory; Usa-se o Fact em métodos sem parâmetros; [Fact] public void Somar() { Assert.NotEqual(5, 4 + 4); } É possível fazer vários tipos de testes. O exemplo acima testa se 4 + 4 é diferente de 5. Nesse caso, a função passará no teste. Testes unitários com xUnit Usa-se o Theory para deixar claro que o método de teste terá parâmetros; Deve-se utilizar o atributo InlineData para inserir os dados de testes. [Theory] [InlineData("Paralelepipedo", "para")] [InlineData("Avião", "vi")] [InlineData("Atualmente", "mente")] public void VerificarSubString(string palavra, string substring) { Assert.Contains(substring, palavra); } Aula 47 – Emulando comportamento de objetos com Moq Introdução Implementação Emulando comportamentos com Moq Para testar se um objeto desempenha sua função corretamente, é necessário emular o seu comportamento; É nesse momentoque utiliza-se o processo conhecido como “mocking”; Mocking é processo de simular comportamentos possíveis e impossíveis de objetos, possibilitando testes nos mesmos sem muito esforço e codificação; Usaremos a biblioteca Moq. Emulando comportamentos com Moq Crie uma interface e a implemente public interface IMetodos { string PegarNomePeloId(int id); } public class Metodos : IMetodos { private readonly Contexto _contexto; public Metodos(Contexto contexto) { _contexto = contexto; } public string PegarNomePeloId(int id) { return _contexto.Carros.Find(id).Nome; } } Emulando comportamentos com Moq No método a ser testado, declare uma variável do tipo mock; var mock = new Mock<IMetodos>(); Configure o comportamento que esperado; mock.Setup(p => p.PegarNomePeloId(2)).Returns("Siena"); Declare uma variável para o controller e passe um objeto mock para ele; CarrosController carros = new CarrosController(mock.Object); Então basta testar o que é necessário. string resultado = carros.PegarNomePeloId(2); Assert.Equal("Siena", resultado); Aula 48 – Projeto Final – Aluguel de carros Tópicos Introdução Obrigado !!!!
Compartilhar