Como arquitetar um aplicativo com ASP. NET Core (Arquitetura Limpa) | Trevoir Williams | Skillshare
Pesquisar

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Como arquitetar um aplicativo com ASP. NET Core (Arquitetura Limpa)

teacher avatar Trevoir Williams, Jamaican Software Engineer

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Aulas neste curso

    • 1.

      Introduction

      1:30

    • 2.

      Understanding Clean Architecture

      7:03

    • 3.

      What We Will Be Building

      4:22

    • 4.

      Setting Up Solution

      2:55

    • 5.

      Creating The Domain Project

      6:08

    • 6.

      Creating the Application Project

      7:14

    • 7.

      Implementing Automapper

      12:19

    • 8.

      Create Queries with MediatR

      16:18

    • 9.

      Finishing up Queries for MediatR

      7:42

    • 10.

      Create Commands with MediatR

      12:35

    • 11.

      Finishing up Commands with MediatR

      21:39

    • 12.

      Adding Validation

      27:27

    • 13.

      Adding Custom Exceptions and Response Objects

      13:14

    • 14.

      Additional Refactoring and Considerations

      9:39

    • 15.

      Section Overview

      1:46

    • 16.

      Adding Entity Framework Core

      5:37

    • 17.

      Implementing Persistence Layer

      15:27

    • 18.

      Add Infrastructure Project (Email Service)

      15:59

    • 19.

      Create and Configure Application API

      11:44

    • 20.

      Implement Thin API Controllers

      14:56

    • 21.

      Finishing up Thin API Controllers

      4:29

    • 22.

      Seed Data In Tables

      4:47

    • 23.

      Review Swagger API Support

      8:26

    • 24.

      Unit testing - Section Overview

      3:23

    • 25.

      Write Unit Tests for Application Code

      28:25

    • 26.

      Setup ASP.NET MVC Project

      2:14

    • 27.

      Use NSwag for API Client Code

      8:35

    • 28.

      Setup Custom API Clients and Base Code

      14:18

    • 29.

      Setup Leave Type Management Service

      12:11

    • 30.

      Setup Leave Type Management UI

      27:55

    • 31.

      Add Json Web Token (JWT) Authentication to API

      36:55

    • 32.

      Add Authentication to Web Project

      30:35

    • 33.

      Setup Leave Allocation Management

      18:50

    • 34.

      Setup Leave Request Management - Part 1 - Employee

      20:53

    • 35.

      Setup Leave Request Management - Part 2 - Admin

      24:29

    • 36.

      Unit Of Work For Batch Operations

      8:40

    • 37.

      API Exception Handling

      13:36

    • 38.

      Handling Token Expiration

      8:40

    • 39.

      Handling Token Expiration

      13:51

    • 40.

      Improve Data Auditing

      5:54

    • 41.

      Conclusion

      1:03

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

194

Students

--

Projects

Sobre este curso

Visão geral

Criando um aplicativo modular, testável e permanente em . NET Core requer uma base sólida. A configuração de uma arquitetura de aplicativo requer visão e muita consideração como decisões iniciais impacte o seu início impacte de trabalho de forma rápida é alargada e manutenção.

No longo prazo, as aplicações precisam ser mantidos e, neste caso, estendido. Entre o design e o código de seu código de a maneira de escrever o seu código foi escrito e o que é necessário ser revisado e no futuro passado.

Por que arquitetura SOLID

Quando conversamos sobre arquitetura SOLID , estamos referindo não é uma tarefa simples. As As Decisões tomadas de tomada no processo de processo de de de início para um processo de trabalho grande Advertência de essas práticas também podem contribuir para evitar to refactoring

SOLID representa:

  • S - Princípio de responsabilidade única

  • O - Princípio aberto

  • L - Liskov Princípio de substituição

  • I - Princípio de segregação de interface

  • D - Princípio de inversão de Dependência

Neste curso, você explorar princípios básicos que ajudam com a criação de código foundational de cabo. Em seguida, você descobre como configurar uma arquitetura de aplicação real com o ASP XP. Depois, vai aprender a conectar blocos diferentes e comuns como e-mail, autenticação e ter ter uma base para conectar outros serviços de terceiro quando o

Quando terminar com este curso, terá as habilidades e conhecimento para criar um aplicativo testável e atualizado de sua aplicação ASP.NET Core necessário para arquitetar o mundo real Aplicativos NET Core

Crie uma base forte em . Arquitetura limpa de NET 5

  • Aprenda arquitetura limpa ou Cebola e boas práticas

  • Aprenda a responsabilidade de comando

  • Implementar padrão Mediatr

  • Adicione o serviço de e-mail usando SendGrid

  • Abordagem de design motivado à arquitetura de software

  • Manejo de expressão eficiente e encaminhamento

  • Implementação de unidade

  • Manipulação de erros globais com Middleware personalizado e exceções

  • Adição de validação usando Validação fluente

  • Crie um . Aplicativo de NET Core e MVC

  • Autenticação de JWT(JSON

Conteúdo e visão

Para tomar este curso, você vai precisar ter algum conhecimento sobre . Desenvolvimento principal e C#.

Este é um curso enorme curso. Mais de 10 horas de conteúdo premium, mas inteligente quebrado para destacar um conjunto de atividades relacionado baseado em cada módulo na aplicação que está construindo. Também vamos analisar de problemas e troubleshooting enquanto andamos nós, produzindo as melhores práticas, escrevendo uma lógica eficiente e entender por que os desenvolvedores fazem as coisas do modo feito. Seu conhecimento vai crescer, passo a passo durante o curso e será desafiado a ser o melhor que pode ser.

Não fazemos as coisas do modo perfeito ; que não é a realidade do código de escrita. Criamos erros e fazemos os erros e consertamos em torno deles. Ao fazer o trabalho de depuração e técnicas. Quando terminar o curso, você vai ter focado no Visual Studio e examinado erros de lógica e sintaxe para a segunda natureza para você ao trabalhar no trabalho Ambiente NET. Isso vai colocar suas novas novas habilidades aprendidas em uso prático e impressionar seu chefe e trabalhos de trabalho

O curso é completo com arquivos de trabalho hospedado no GitHub, com a inclusão de alguns arquivos para tornar mais fácil para você reproduzir o código demonstrado. Você vai ter a vontade trabalhar com o autor enquanto vai trabalhar em cada aula receberá um certificado de conclusão ao concluir o curso.

Meet Your Teacher

Teacher Profile Image

Trevoir Williams

Jamaican Software Engineer

Teacher
Level: Intermediate

Nota do curso

As expectativas foram atingidas?
    Superou!
  • 0%
  • Sim
  • 0%
  • Um pouco
  • 0%
  • Não
  • 0%

Por que fazer parte da Skillshare?

Faça cursos premiados Skillshare Original

Cada curso possui aulas curtas e projetos práticos

Sua assinatura apoia os professores da Skillshare

Aprenda em qualquer lugar

Faça cursos em qualquer lugar com o aplicativo da Skillshare. Assista no avião, no metrô ou em qualquer lugar que funcione melhor para você, por streaming ou download.

Transcrições

1. Introdução: Ei pessoal, bem-vindos ao meu novo curso, núcleo ASP.net, arquitetura sólida e limpa. Sou sua instrutora, Travolta Williams. Tenho mais de 10 anos de experiência como engenheiro de software e palestrante. Neste curso, vamos estar olhando para algumas coisas. Vamos olhar para a implementação de princípios sólidos e arquitetura limpa em um aplicativo ASP.NET Core. Ao longo do caminho, vamos trabalhar com ferramentas avançadas como mediador ou bottom-up ou Fluent API para validação, estaremos construindo Global Exception Handling e registro em log. Eu vou estar olhando para o padrão C QRS, que é um padrão maravilhoso que mantém nosso código segregado e em bite-size é para máxima integração e extensibilidade. No final deste curso, vamos entender como fazer testes de unidade, como integrar serviços de terceiros em um aplicativo e analisar como podemos implantá-lo para fins de produção. No entanto, os requisitos para este curso incluem Visual Studio 2019 e dotnet five, ou a versão mais recente. No momento em que você está fazendo este curso, tudo o que vamos fazer é à prova de futuro e esses princípios podem ser transferidos para as versões mais recentes sem problemas. Para tirar o máximo proveito deste curso, eu recomendo que você tenha algum conhecimento de programação C Sharp e dotnet, bem como conhecimento de desenvolvimento de banco de dados. De qualquer forma, eu vou fazer o conteúdo muito iniciante amigável e você deve ter absolutamente nenhum problema em seguir ao longo e saber que você tem todas as informações que você precisa. Vejo-te em breve no curso. 2. Entendendo a arquitetura limpa: Muito bem, analisamos os princípios que regem a arquitetura limpa de aplicativos. Agora vamos olhar para o que exatamente queremos dizer com arquitetura limpa. Porque arquitetura limpa não significa necessariamente um bom software. Bom é muito relativo a quem está vendo. Por exemplo, se você foi encarregado de desenvolver um sistema de gerenciamento de leads para o departamento de RH e você fez isso, e RH está feliz, então é um bom software. No entanto, se você não fez isso seguindo estes princípios, então ele poderia ser visto como software ruim, mas práticas de desenvolvimento de software bud em geral, por sua equipe ou quem quer que seja seu sucessor quando eles estão tentando manter esta aplicação. Portanto, a arquitetura limpa não é necessariamente diretamente proporcional ao bom software. Depende de quem é o destinatário e em que ponto. Então vamos apenas discutir tudo o que vai para desenvolvimento de software e os diferentes tipos de arquitetura para que possamos apreciar plenamente quando precisaríamos aumentar nossas considerações de design um pouco mais e quais os prós e contras deste são. Então o primeiro que queremos olhar seria tudo em uma arquitetura. E eu vou tudo em uma arquitetura, é mais fácil de entregar. Pode ser estável e visto como uma solução a longo prazo. Tudo em uma arquitetura poderia ser facilmente quando brigamos em novo é ser aplicação dotnet Core. Ou se esta é sua primeira vez fazendo ASP.net Core, você provavelmente está mais familiarizado com Ruby on Rails ou larva ou selva. Uma vez que você tenha esse layout geral do projeto, isso pode ser facilmente visto como uma arquitetura tudo-em-um. Você tem todas as pastas e tudo que você tem a fazer é criar seus arquivos, criar o seu completo faz que a separação de preocupações ali e tudo é bom, o software vai funcionar. No entanto, é definitivamente difícil aplicar princípios sólidos. Quanto mais você tiver que empacotar tudo isso em uma arquitetura é mais cheiros de código e práticas ruins que podem ter que ser comprometidas. Tudo bem, então à medida que cresce, torna-se mais difícil de manter e sua testabilidade. E quando sentamos essa estabilidade, queremos dizer como com depuração e por teste de unidade de extensão, a capacidade de testar duas unidades de tudo isso em uma arquitetura. Essa capacidade diminui à medida que as funções do aplicativo. Em seguida, queremos olhar para a arquitetura em camadas. E toda a arquitetura em camadas é um passo acima de tudo em um em que, em vez de separar nossos módulos ou nossos pedaços de código e arquivos, desculpe, por pastas, começamos a olhar para criar projetos e referenciar esses projetos. Assim, no ESP dotnet Core e em suas obrigações em geral, você pode desenvolver bibliotecas de classe onde você coloca todas as suas classes e você apenas faz referência a elas como você precisa. E então você acabaria com camadas diferentes. Você tem uma camada que lida com as coisas da interface do usuário. Você tem uma camada que precisa com a lógica de negócios. E você tem uma camada que afeta a inflamação entre banco de dados e lógica de negócios. E então você acaba com uma camada nossa aplicação. Agora, é mais fácil, definitivamente aplicar princípios sólidos e é mais fácil minton bases de código maiores. No entanto, isso ainda acessar um aplicativo porque todas essas camadas ainda são um pouco dependentes umas das outras. Então ainda não estamos aproveitando totalmente todo o princípio de inversão de dependência, bem como todo o princípio de acoplamento solto. E agora, finalmente, estamos olhando para a única arquitetura que é amplamente ensinada como arquitetura limpa. Agora, quando falamos apenas sobre arquitetura, estamos falando de maneiras diferentes de ver camadas. E nesta fase, queremos apoiar qualquer tipo de aplicação. Quer ter tudo muito modular para que possamos colocar em um novo módulo sem interromper o resto da base de código. Podemos tomar módulo automático e podemos fazer alterações e testar mais facilmente sem interromper as partes existentes da aplicação. Então, quando falamos sobre a arquitetura Odeon, estamos falando sobre talvez ter algum aplicativo cliente para a interface do usuário. Isso pode ser um aplicativo da Web ASP.NET. Este poderia ser um aplicativo móvel. Estamos falando sobre ambos ter serviços de API que vão ficar em cima da obrigação no núcleo. E esses serviços de API, mais uma vez, seriam de código aberto. Ele realmente não se importa com o que o cliente é e riscos é o que vamos usar. Mas não se importa se é um cliente móvel, não se importa se é um cliente web, um cliente blazer, e raiva de um cliente, é apenas taxiando dados do banco de dados para quem está ouvindo. E Buck, Não, o teste torna-se muito mais fácil de fazer porque podemos testar as diferentes camadas de forma independente e então podemos testar como as camadas interagem umas com as outras. Então, se alguma coisa for introduzida para quebrar qualquer uma dessas interações existentes, então podemos detectá-la mais facilmente. E do início nulo para a infra-estrutura estamos falando sobre o módulo. Então estamos falando de registrar o acesso a dados. Se tivermos mais de uma base de dados que temos que lidar com, devemos ser capazes de colocar em uma nova camada para falar com o banco de dados desfazer sem interromper nada que a arquitetura existente estava fazendo com o banco de dados antigo. Podemos colocar em log, podemos colocar em mapeamento, validações. Tudo pode entrar e nossa cômoda sem interromper nossa aplicação. Então contras, no entanto, há uma curva de aprendizagem porque você precisa saber o que era estranho e há diferentes interpretações deste tipo de arquitetura. Então você pode ver diferentes sabores. Se você ler duas ou três fontes diferentes, você verá duas ou três implementações diferentes de seu inimigo. Pergunto-me qual é o único que devo usar? Claro, o contexto determina muito do que você e outros desenvolvedores fazem, as decisões que você toma em sua arquitetura. E assim, você sabe, você só tem que usar isso, apenas obter o conhecimento e usar seu contexto como seu guia e outro golpe para este tipo de arquiteturas que pode ser muito demorado porque há muitos seus muito mais arquivos que estarão envolvidos quando poderíamos fazer algo com dois arquivos agora ele provavelmente vai exigir cinco. No entanto, mais uma vez, os benefícios seriam que temos carpetes soltos e mais testabilidade. Então, com tudo isso dito, tenha cuidado. Nem todos os aplicativos precisam, entre aspas, arquitetura limpa. Um bom software atende às necessidades dos negócios e o software de manutenção aumenta a vida útil do software. Então você tem que encontrar um equilíbrio o tempo todo. Não vejo que cada projeto que você tem que fazer vai precisar de arquitetura limpa, começa pequeno e estender conforme necessário. 3. O que vamos construir: Bem-vinda de volta. Neste vídeo, vamos dar uma olhada no aplicativo que queremos construir ou reconstruir. Então, na minha tela eu tenho um sistema de gerenciamento de leads que foi construído com uma velocidade nele núcleo 3.1. E você vê todas as coisas que foram implementadas dentro dessa solução. Agora, parece bom e faz o que foi projetado para fazer. Ele entregou recursos de gerenciamento de licenças para o departamento de RH. Você pode encontrar o código-fonte para este aplicativo na minha conta GitHub e você pode procurar o repositório deixar gestão traço, dash dotnet core. Na verdade, este é o aplicativo que foi construído no meu curso, completo ASP.NET Core e Entity Framework Development. Por que foi perfeito para iniciantes? É verdade com muitos cheiros de código e formas ineficientes de escrever o código que um iniciante pode pegar. Mas à medida que você começa mais intermediário para avançado, você vai começar a perceber que eles são melhores maneiras de fazer essas coisas. E isso é exatamente o que discutiremos neste curso. Agora, vou dar uma olhada na estrutura do projeto. E mais uma vez, é completamente opcional baixá-lo. Você pode simplesmente seguir adiante, mas vou mostrar-lhe alguns dos pontos fracos da arquitetura e algumas das decisões que foram tomadas durante o desenvolvimento desta aplicação. Primeiro, você verá que isso só tem um projeto. Agora, se você se lembra mais cedo quando olhamos para os diferentes tipos de arquiteturas de projeto, isso cairia direito em que tudo em uma arquitetura onde quer que a coisa seja apenas em um projeto, fácil de acessar. Então, mais uma vez, para iniciantes, tudo bem porque você quer visualizações, você começa as vistas que você quer que eu vá para os dados. É toda a sua separação de preocupações neste momento é limitada e restrita a apenas pastas. No entanto, no quadro geral, e quando você quiser adicionar mais coisas, este projeto pode ficar muito gordo enquanto você tenta estender, então será bom para quebrá-lo. Outra coisa que o nosso cheiro de código que gostaríamos de abordar é a repetição de código. Então, mesmo na construção de nossos modelos de dados, você veria que nós meio que repetimos algumas das propriedades. Nós temos ID lá, nós temos ID aqui novamente, essas pequenas coisas em alguns dos controladores, nós repetimos código quando nós não necessariamente precisamos. E então, enquanto estamos no tema dos controladores, há o que vamos chamar de controladores gordos aqui. Então estamos fazendo muita lógica de negócios, muito processamento aqui no controlador, o que o torna muito pesado. Então você quer tipo de obstruir esses processos de lógica de negócios longe de seus controladores. Agora, fora dos motivos de desenvolvimento para reprojetar e re-arquitetar esse aplicativo do lado dos negócios ou da perspectiva dos negócios, um, o RH quer estender esse aplicativo da maneira como ele é criado, certo? Não, é bastante difícil fazer isso sem perturbar o código existente. Isso é 1, 2, não é muito testável em seu estado atual. Então, mesmo se tentarmos estender, vamos ter mais propriedade fora de testes porque temos que fazer mais testes de regressão e testes manuais sobre isso. E, em seguida, três, quando fazemos isso em uma onda de arquitetura limpa, nós realmente temos a opção de estendê-lo para diferentes tipos de aplicativos cliente e potencialmente implantado como software como um serviço em que a API está realizando todos os lógica de negócios e interação com o banco de dados e o aplicativo cliente é completamente anônimo que tivemos. Este aplicativo cliente poderia ter sido um aplicativo MVC, ele poderia ter sido um aplicativo blazer, poderia ter sido um aplicativo móvel. Portanto, essa é uma das razões da proposta de valor para que a chave e a arquitetura possam ser implementadas. Voltando ao que dissemos antes, um bom software é um software que faz o seu trabalho, certo? Não, este é um bom software. O departamento de RH está quieto, feliz com ele e como ele faz, o que ele precisa fazer. No entanto, quando eles começam a pedir mais coisas, percebemos em nosso técnico disse que torna-se um pouco mais difícil estender, modificá-lo, testá-lo. Então, onde estamos protegendo para que ainda possamos fornecer todas as funcionalidades que o departamento de RH deseja, mantendo a capacidade de mantê-la de forma muito eficiente. Em nossa próxima lição, começaremos a configurar a solução para nossa nova arquitetura. 4. Solução de configuração: Bem-vinda de volta. Em nossa primeira lição prática, estaremos definindo nossa solução. Então eu tenho o Visual Studio 2019 aberto. Se não tiver o Visual Studio 2019 instalado, pode facilmente aceder ao Visual Studio dot Microsoft.com barra VS e transferir a edição comunitária. A Community Edition é gratuita para uso educativo e individual. Claro, se você é, se você é um comercial do que se espera para obter a versão profissional ou corporativa. Depois de baixá-lo, você será apresentado com um instalador. E o que você realmente precisa deste instalador, no mínimo é o ASP.net e a carga de trabalho de desenvolvimento web. Então, marcando isso, você está indicando que você quer que o trabalho através dele. Você verá todas as cargas de trabalho disponíveis. Pode levá-los, se quiser. Claro, quanto mais você toma, mais você precisa baixar. Mas para este curso você realmente só precisa deste que lhe dará todas as ferramentas necessárias para qualquer aplicativo Web ASP.net, bem como dotnet five. Então, uma vez que você tenha concluído a configuração ou se você já tinha instalado e continue junto comigo. E vamos criar novos projetos. Então o que vamos fazer é criar uma solução em branco. Eu tenho em meus modelos de projeto recentes. Mas se você fizer isso, você sempre pode procurar por solução em branco nesta área e, em seguida, você terá uma solução vazia contendo nenhum projeto. Então é isso que queremos e vamos chamar este projeto H de gestão de pontos. Agora não há nenhuma razão em particular para eu chamá-lo assim. É um aplicativo de gerenciamento de leads que está sendo construído para o departamento de RH. Se ele estava sendo construído para uma empresa, então você provavelmente iria querer dizer empresa ponto o tipo de sistema. Então, se você quiser, você pode ir em frente e usar meu nome ou mudar esse nome de acordo. Mas uma vez que você tenha colocado em um nome que é válido, então você pode ir em frente e clicar em Criar. Agora não vamos escrever nenhum código nesta lição, mas vamos colocar para fora a estrutura do projeto como precisamos para a duração deste curso ou todo este projeto. Então a primeira coisa que eu vou fazer é adicionar uma pasta e eu vou chamar este SRC, abreviação de fonte, e outra pasta que nós vamos chamar testes. Agora, sob SRC, vou adicionar mais algumas pastas. Eu vou chamar este de API, porque é isso que vai interagir com o nosso aplicativo cliente. Vou ter outro chamado núcleo, outro chamado estrutura infra, e finalmente, um para a interface do usuário. Então é só isso que estamos fazendo para esta lição. Estamos apenas montando a estrutura do projeto. Então, quando voltarmos, começaremos a criar os diferentes projetos que irão em cada uma dessas seções. 5. Criando o projeto de domínio: Muito bem, pessoal, bem-vindos de volta. Nesta lição, estaremos criando nossos projetos de domínio. Assim, nossos projetos de domínio irão abaixo da nossa pasta principal dentro da nossa aplicação, podemos ir em frente e adicionar um novo projeto. E o que vamos fazer é adicioná-lo como uma biblioteca de classe, biblioteca Docx C-sharp do tipo dotnet padrão. Tudo bem, então não está em um estibordo permite o compartilhamento de código em várias plataformas diferentes. Então vamos usar esse para todas as nossas bibliotecas de classe. E estamos chamando de domínio de gerenciamento de ponto de HR uma vez que ele será usado para armazenar todos os nossos objetos de domínio ou classes de entidade que são traduzidos em nossas tabelas de banco de dados. Então eu posso ir em frente e bater Next. E a estrutura alvo aqui é o padrão dotnet 2.1. Vá em frente e pressione Criar. Agora, uma vez que isso é feito, nós temos nossa classe padrão um, que nós podemos realmente excluir e, em seguida, começar a preencher com nossas classes. Então, voltando ao nosso projeto no GitHub, rapidamente, você veria que as classes de domínio eram mantidas dentro do projeto em uma pasta chamada dados. Portanto, nossas classes de domínio incluíram alocação de licença, solicitações de licença e tipo de licença. Se você quiser, você pode ir em frente e recuperá-los, mas eu vou estar passando por eles de qualquer maneira. Então, se você der uma olhada rápida nessas classes, você veria que cada uma tinha uma ID, e nós também tínhamos um monte de propriedades em cada uma. Então, quando as propriedades que tipo de repetição incluiriam data criada entre o tipo de folha e o registro de alocação de folhas. E então é inconsistente porque o gerenciamento de licença ou desculpe, solicitações de licença não tem realmente isso. Então vamos corrigir algumas dessas inconsistências, bem como reduzir as repetições entre elas. Então eu vou começar com tipos de folhas. Então eu estou indo apenas para ir para o projeto clique em Adicionar nova classe. Estamos chamando de tipo folha. E eu vou fazer este fórum público Não, dentro do tipo folha, o que nós vamos ter nossos campos para ID, nome, dias padrão, e cada um deles criou. Agora eu especifiquei esse campo de data, como data de criação é realmente um campo de auditoria e isso precisa ser telefone entre as diferentes classes. Então eu vou apenas ir em frente e adicionar todas as classes de entidade para que você possa pausar, replicar isso. Para a solicitação de licença, vamos ter um campo ID, início e datas de término, tipo de folha. Os dados solicitados, solicitações, comentários, data, axônio, e aprovado na forma de um booleano anulável, e cancelado na forma de um booleano. Então você pode ir em frente e replicar isso. Não, se você estiver comparando isso com o que está na referência do GitHub, há alguns campos faltando, para os quais ainda não estamos prontos na forma do funcionário, o que seria alguns dados relacionados ao usuário. Ainda não temos isso, então não estamos priorizando que possamos introduzi-lo mais tarde por meio de algumas migrações. Saiba que a terceira entidade que vamos adicionar é alocação de licença. E para este vamos ter o ID, o número de dias, a data criada, o tipo de licença, ID do tipo de folha e o período. Mais uma vez, eu meio que omitiu os campos relacionados aos funcionários também. Aquelas anotações de dados. Agora, em termos de repetição de campos versus a necessidade de ter coerência com, pelo menos, o visto precisa ser repetido, ou seja, a data criada. Normalmente, quando estamos falando sobre auditoria, queremos ter data criada, quem a criou, a data modificada e quem a modificou pela última vez, certo? Assim, podemos manter o controle de tudo acontecendo como quase todo ferrado. Nós realmente resolver algumas das coisas com toda a referência para o funcionário e assim por diante com esses sentimentos de auditoria. Então o que eu vou fazer é introduzir outra pasta neste projeto de domínio. E eu vou chamar essa pasta de comum. E então dentro do comum, eu terei uma classe que eu vou chamar essa entidade de domínio. Ninguém sabe que minha entidade de domínio base tem, bem, é bom ter todos os campos base que eu conheço cada classe ou cada entidade de domínio que vai precisar. Vou fazer disso uma classe abstrata para que ela não possa ser instanciada sozinha. No entanto, pode ser herdado por todos os outros. Então isso vai ser ID porque cada tabela vai precisar de um ID. Eu também vou ter para outros campos, um para a data criada, depois criado até então uma data-hora para os dados da Última Modificação e outro para o último modificado por. Agora, com esta entidade de domínio base, posso saber que todos os outros herdam. Eu posso apenas voltar para a minha classe de entidade real e deixá-lo herdar da entidade de domínio base, incluindo quaisquer referências ausentes usando ponto de controle. E lá você vê que esses campos que eu tenho alocação de licença INSEAD que têm os mesmos nomes que os em com base em uma entidade estão acendendo. Então isso significa que não preciso repeti-los. Tudo bem. Parece um pouco mais limpo. Tudo bem, então eu vou e deixo pedidos do que eu faço o mesmo. Vá em frente e herde incluir as referências que faltam e, de repente , não preciso ver a identificação aqui também. E, em seguida, no tipo de folha, eu faço exatamente a mesma coisa, incluindo referências ausentes. E então eu posso remover todos os campos repetidos. Então são baseados em uma entidade nos dá acesso a certos campos que são esperados para repetir em todas as entidades como todos nós queremos que eles tenham estes. Tudo bem. Então, com todas essas mudanças feitas, vamos em frente e aperte Control Shift e B para fazer uma compilação e temos uma compilação bem-sucedida. Então podemos passar para a próxima tarefa. 6. Criando o projeto de aplicativos: Ei pessoal, bem-vindos de volta. Nesta lição, discutiremos nossa camada de núcleo de aplicação. Agora, o propósito desta camada é ficar entre a nossa aplicação, aplicação sendo o que quer que esteja querendo acessar o banco de dados e o banco de dados. Assim, nesta camada será definir todos esses parâmetros de acesso para mediar entre o aplicativo de chamada e o próprio banco de dados. Então este projeto vai ficar diretamente dentro da nossa pasta principal. Então vamos em frente e adicionar uma nova biblioteca de turmas. E eu queria estar chamando este um ponto de RH, deixar aplicativo de ponto de gerenciamento. Vá em frente e adicione-o mais uma vez, estamos usando dotnet pouco abaixo 2.1 e vá em frente e crie. Então, agora que temos nossa biblioteca de classes, eu vou remover a classe padrão, e então eu vou adicionar duas novas pastas para este projeto. Então o primeiro vai ser persistência e, em seguida, encipher sistemas, vamos ter outra pasta chamada contratos. Então dentro dos contratos vamos definir todas as obstruções para nossos repositórios. Agora o júri está fora sobre quais são as melhores maneiras de implementar isso. Mais uma vez, há algumas opiniões é a arquitetura proposta, e há algumas opiniões e algumas opiniões são implementadas com base no contexto. Mas vou explicar por que estamos usando o padrão do repositório. Então, um, de acordo com os princípios secos, não queremos repetir consultas com muita frequência. Além disso, você pode ter operações especializadas que você precisa executar em qualquer um desses objetos de domínio. Então, quando você define um repositório por objeto de domínio, então você pode ter cotações personalizadas ou métodos personalizados dentro desse repositório para estes, certo? Não, não estamos implementando o repositório, estamos apenas definindo o contrato. Então o contrato aqui, o primeiro será uma interface e eu vou chamá-lo ij repositório genérico. Eu disse aula aqui, fazendo uma aula. Mas mesmo se você tomar cuidado que você pode apenas torná-lo uma interface pública. Agora vamos dizer a esta interface que ele será implementado em relação a uma classe chamada T. Então nós estamos apenas usando genéricos de acordo com o repositório genérico nome para que qualquer um de nossos objetos de domínio pode ser usado para acessar a funcionalidade relacionada ao banco de dados por meio desta interface. Então, alguns dos métodos que vamos implementar nesta interface incluem um GetMethod, então temos tarefa T. E então você pode simplesmente ir em frente e incluir quaisquer bibliotecas ausentes. Nós também vamos ter tarefa, obter tudo o que este está retornando. Eu leio apenas listas, sei se é a primeira vez que você está vendo esse tipo de dados. Normalmente, e pessoalmente eu costumo usar uma lista ou um niilista ou um daqueles tipos de dados mais populares da Coleção que eu li em uma lista. Esse é o benefício é que ele o mantém em um estado somente leitura para que ele não possa ser modificado uma vez que tenha sido retirado dos mésons de dados enviados. Assim, menos transporte e menos operações relacionadas ao banco de dados após o pool de dados. Então vamos olhar para ele em alguns, mas esse é o tipo de dados que estou usando. Mais uma vez, você poderia facilmente ter usado qualquer outro tipo de coleção do tipo T. Poderia ter sido uma lista, poderia ter sido uma coleção. Mas então eu li na lista está servindo o propósito que eu queria. Vamos ter a tarefa para adicionar onde Linda também tem tarefas para atualizar e excluir. Então você vê que os repositórios genéricos não só genéricos para t, mas também é um genérico em termos da funcionalidade fornece quais são as funções crud básicas e padrão. Há também uma convenção de nomenclatura onde as pessoas colocaram a palavra assíncrona porque você pode ver onde todos usando tarefas aqui. Então algumas vezes você veria, em seguida, defini-lo como uma pia. Então, é óbvio que isso vai ser uma função assíncrona. Então você não poderia seguir essa convenção de nomes se você quiser. Eu não vou, então podemos seguir em frente. Agora a coisa com o repositório genérico é que, mais uma vez, são apenas as funções crud genéricas que cada tabela de banco de dados pode precisar executar. No entanto, quando você tem algo específico para deixar a operação de alocação ou uma operação de solicitação de licença, você não pode criar o salt e o código pode ficar missy se você tentar construí-lo em determinadas partes do aplicativo. Então o que vamos fazer é comentarrepositórios específicos baseadosem repositórios específicos baseados nosso repositório genérico ou para estender nossa funcionalidade genérica, mas específico para qualquer um de nossos objetos de domínio. Então eu só vou voltar para os contratos e eu vou adicionar um novo item na forma de uma classe mais uma vez, mas realmente vai ser uma interface e eu vou chamá-lo, eu deixo repositório de solicitações. Uma vez criado, transformamos em uma interface pública. E então eu deixá-lo saber que ele está estendendo repositório genérico e é específico para o nosso tipo de classe de solicitação de licença. Certo, então o pedido de licença é o nosso domínio. Lembre-se que isso era relativo ao tipo T. Então este é o T que estamos passando, mas então você verá aqui que ele não sabe nada sobre digamos 70. Portanto, precisamos adicionar referência ao domínio de gerenciamento de RH. Então você pode ver que com toda a honestidade, que não funcionou muito para mim quando eu uso o lado deles, apenas ir para dependências. Deixe-me fazer isso de novo, desculpe, dependências no Project ou de um amigo. E então eu apenas pego a referência para os objetos de domínio. Clique em OK. E então eu posso saber, incluir que usando declaração aqui. Tudo bem, então dentro deste repositório, então se temos funções especializadas relativas a apenas deixar solicitações, então podemos defini-las aqui com a modelagem do repositório genérico e sem os outros repositórios específicos precisando vê-lo, queremos manter tudo tipo de contido em um só lugar. Então, seguindo este exemplo, eu vou apenas ir em frente e defender os outros repositórios. Deixo alocação e deixarei repositórios de tipos. Então, uma vez que essa atividade é feita, acabamos com duas outras interfaces. Então temos o nosso repositório genérico. Temos ou eu deixar repositório de alocação, que está implementando ou herdando ou outro repositório genérico I relativo à alocação de licença. E então temos que novamente para o tipo de folha com eu deixar tipo repositório estendendo genérico relativo ao tipo de licença. Então isso é realmente tudo para esta lição em que eles estão sentando os contratos. E esses contratos estão nos fóruns dessas interfaces. Porque lembre-se que nós não queremos interromper diretamente com o código quando estamos chamando o que vamos estar lidando com abstrações que assim podemos fazer alterações de código sem interromper muito a citação do cliente aplicação lateral. 7. Implementação de Automapper: Ei pessoal, bem-vindos de volta. Nesta lição vamos estar sentados auto mapper. Saiba que se você não sabe o que é outono superior, isso não é problema. É realmente apenas uma biblioteca que nos ajuda a converter entre um tipo de dados para outro. Mais simples, certo? Então, o contexto por trás do porquê ele será útil é que nós estaremos implementando o padrão de mediador em um vídeo a seguir. Mas isso medeia ou padrão estará atuando como um mecanismo de mensagens entre o que está vindo da planta e o que precisa ir para o banco de dados. É, de um modo geral, má prática interagir diretamente com os objetos de domínio, pelo menos antes de chegarmos ao repositório. Isso significa que não devemos permitir que qualquer aplicativo de chamada e o cliente, qualquer aplicativo que esteja falando com nosso aplicativo no núcleo nos envie diretamente ou direcione objetos fora do tipo de objeto de domínio. Em vez disso, criamos obstrução. Então, criamos objetos de transferência de dados ou modelos de visualização. Você pode chamá-los de qualquer um, mas eles são realmente apenas cruzamentos que tipo de olhar como o objeto de domínio, mas têm restrições baseadas na operação. Então editar operação tem requisitos diferentes de talvez uma operação de criação. E assim você apresentaria o id 1 e id não seria apresentado no outro. Mais uma vez, tudo o que você tem são obstruções para isso. Você pode obter granular ou você pode mantê-lo geral. Isso é com você. O ponto é alter mapeador ajudará com a conversão entre o obstruído ou a versão amigável do cliente deste objeto e a versão amigável do banco de dados deste objeto. Isso vai promover o acoplamento solto em toda a nossa aplicação. Então, com tudo o que disse, a configuração não vai ser muito complicada para este, o que eu vou fazer dentro deste projeto de aplicativo é criar uma nova pasta e nós vamos apenas chamá-lo de perfis embora. Perfil é basicamente apenas um arquivo de configuração para túnel automóvel que é permitido converter entre um tipo de dados para outro. Então eu vou criar um vestido novo dentro desta pasta. E eu vou chamá-lo de mapeamento de perfil. E então eu preciso apresentar e eu vou tornar isso público, claro, mas eu preciso ir para NuGet e pegar nossa biblioteca de mapeadores de altar. Então eu vou apenas clicar com o botão direito do mouse em dinheiro. Pode pegar a biblioteca? E então eu vou procurar o autor final. E o que me interessa é a última extensão Bardot para injeção de dependência. Nós vamos vir com todas as dependências, incluindo a biblioteca de PR final base e qualquer outra coisa necessária para que ele possa ser usado para injeção de dependência em conformidade. Então eu vou apenas ir em frente e instalar esse. Claro, aceitando e permitindo quaisquer problemas que surjam uma vez que esteja instalado. Em vez de mapear perfil, vou deixá-lo herdar de uma classe chamada profile. E esta classe é chamada em Auto Mapper Library. Certo, então temos a configuração do perfil. Isso é bom. Bem, a próxima coisa que eu vou definir seria meus objetos de transferência de dados. Então eu criei uma nova pasta dentro deste projeto de aplicativo. E nesta pasta eu tenho alguns arquivos. Um, eu tenho um arquivo ou pasta comum outro com um arquivo comum chamado detalhe base. Tão semelhante ao haul e estamos sentados em objetos de domínio de bordo, temos um comum e, em seguida, onde a entidade de domínio base, que tinha algumas propriedades de base que deveriam estar em todos esses objetos de domínio. É da mesma forma que acabei de fazer detalhes baseados. E a propriedade comum seria ID. Eu não preciso da data criada e assim por diante com as DTLs, isso é apenas para auditoria, então isso é em segundo plano. Então o que eu realmente preciso ser compartilhado entre todos eles seria a identificação. E, em seguida, dentro de cada um destes, que eu ainda não os fiz, eu vou então ter outras propriedades que eu sei que cada um deles precisa ter a fim de taxiar com sucesso informações úteis para mim. Então esta parte é tão fácil como ir deixar o tipo e tomar as propriedades que você conhece, você gostaria de permitir que seu aplicativo ou seus usuários para ser capaz de interromper. Então isso deixaria pedidos. Estas são todas as propriedades obrigatórias. Eu estou literalmente, como você vê, eu estou apenas copiando e colando a parte difícil realmente foi apenas definir o detalhe base e deixar a herança colocar essas identificações e não detalhes, falar com detalhes. Então você vê aqui que o tipo de folha está sendo retido. Você vê que o tipo de folha está sendo retido. Você não deixa o DTO saber sobre o domínio. Tudo bem, então isso deve ser tipo folha DTO, e isso também deve acreditar que DTO, e como regra geral, detalha velocidades e DTLs. Outono superior saber é o que permitirá a conversão entre um ou o DTO e o domínio. Então, em vez de mapear perfil, vamos ter um construtor. Então você pode apenas salvar CTO banheira, banheira que gera nosso construtor. E então eu vou ter uma linha que diz Criar mapa. E criar pode ser dizer entre uma fonte e um destino. Então a fonte T seria, digamos apenas que o pedido de licença seria a minha fonte. Esse é o objeto de domínio. deixe o pedido, DTO, e esse seria o meu objeto de transferência de dados. Tudo bem, então estamos criando uma configuração de mapeamento entre a solicitação de licença e o DTO de solicitação e apenas fechar com os parênteses. E então eu posso estender isso novamente e dizer que ele pode reverter MOP. E o PR final é variável porque eu vi aplicativos onde as pessoas colocam alguma quantidade de lógica de negócios no outono superior em si quando se trabalha com aplicativos complexos e provavelmente entre domínios, você provavelmente quer um domínio ou um detalhe para ser capaz converter em objetos de domínio em um conjunto e objetos de domínio em outro. Então você pode realmente ter várias configurações de mapeamento de um objeto para outro. Você também pode criar conversores personalizados para ver este membro vai diretamente para aquele membro correspondente do outro lado, há uma série de coisas que você pode fazer com isso. Isso poderia ser um curso inteiro por si só. Mas hoje vamos apenas mantê-lo simples com nossos requisitos de configuração simples. Então temos que deixar um local e então temos o DTO correspondente. E, finalmente, temos o tipo de folha. Agora eu quero apontar algo para fora realmente aludido a ele anteriormente, mas eu quero mencionar isso novamente. Há momentos em que você quer obter um pouco mais granular ou ter detalhes específicos para um determinado propósito. Então vamos olhar para pedidos de licença. Deixar pedidos detalhe tem alguns campos. O objetivo de um DTO é limitar o número de campos. Assim, reduzir o excesso de postagem e estão sob postagem ou fornecer muita informação para o usuário. Então o que estou tentando ver é que no caso de você querer ver um pedido de licença, então todos esses dados se tornam relevantes. Mas então, no caso em que você realmente só precisa listá-lo ou mostrar uma lista de todos os pedidos de licença. Você provavelmente não precisa de todos esses dados que o usuário não precisa ver todos esses dados quando ele está solicitando apenas a lista. Eles definitivamente não precisarão ver os comentários nesse ponto. Eles provavelmente não precisam ver a ação de data aprovada ou cancelada quando estão publicando. Então, nesse caso, o que tende a acontecer é que você provavelmente quer quebrá-lo um pouco mais. Então, às vezes, você acabaria com uma pasta dentro dos detalhes. E essa pasta seria específica para talvez deixar o pedido. E, em seguida, dentro de pedidos de licença, você tem todos os detalhes que diferem. Certo. Então, sim, deixe o pedido de detalhes. Isso é bom. Este seria para os detalhes que bem, talvez eu tenha outros detalhes específicos para listar. Então você teria pedidos lista D2, que sim, teria o BSD TO também. Mas então ele tem muito menos propriedades nele. Então você provavelmente só precisa digitar folha a data que foi solicitado e se ele não foi aprovado ou não. Tudo bem. Então, mais uma vez, tudo isso é relativo ao que você acha que precisa fornecer. Mas eu só estou vendo que nesta situação, você provavelmente não quer colocar cada coisa em um detalhe e, em seguida, sempre usar esse detalhe cada vez que um pedido é feito, não importa quão minúsculo seu pedido é ou quão poucos dados realmente precisam nessa situação. Então esse é o propósito do DTO. Então, na verdade, com essas mudanças, eu não sei, eu quebrei algum código. Vamos primeiro, deixe-me atualizar o namespace neste detalhe de solicitações de licença. Então é isso que sabe que é novo local e, em seguida, eu tenho atualizar meu mapeamento para saber que ele tem pedidos de licença, lista, DTO, rasgou um barco também. Então vá em frente e atualize-os. E então vamos fazer uma compilação ou eu construo um sucesso. A última coisa que vamos fazer aqui é configurar no método de registro de coleta de serviço AI. Então o objetivo disso é, bem, de acordo com a injeção de dependência, queremos ser capazes de ter todos os nossos componentes, todos os nossos componentes injetáveis definidos em vez do nível de aplicação. Mas, em seguida, qualquer aplicativo cliente pode ir em frente e apenas chamar o método e tê-lo registrado dentro de si mesmo. Quando chegarmos lá, você vai ver, mas eu vou fazer isso certo? E também isso seria aplicativos, serviços, registro. Então, esta vai ser uma classe estática pública e vai ter um método que eu vou chamar public static void Configure Application Services, que leva um parâmetro da coleção de serviços de AI. Então podemos ir em frente e incluir quaisquer referências que faltam. E, em seguida, dentro disso, podemos ver pontos de serviços adicionar, auto, mapeador. Ou eu diria que se você está familiarizado com dotnet Core e injeção de dependência, você veria que este é apenas um serviço chamado ação que você teria visto no arquivo inicial para qualquer aplicativo dotnet Core. Então a coisa é que nós estamos abstraindo isso apenas para este projeto de modo que quando nós temos esse aplicativo dotnet Core, nós podemos simplesmente chamar esse método. E então ele iria em frente e registrar cada serviço que é definido dentro desse método. Então, estamos adicionando mapeador automático e, em seguida, eu vou dizer ponto de montagem, obter montagem de execução. Vá em frente e adicione as referências que faltam. Agora, se você está familiarizado com o automático ou você trabalhou com ele antes, mas você não está necessariamente familiarizado com isso. Você provavelmente estaria mais familiarizado com ver algo como tipo de um então iria encontrar o perfil de mapeamento e , em seguida, que nos permitiria registrar este perfil tem a configuração superior outono em geral. A coisa com isso é que para cada perfil de mapeamento que você tem, você provavelmente tem que repetir esta linha. E você, com base no tamanho do seu aplicativo, você pode acabar com vários perfis de mapeamento porque eu vi onde você pode ter perfis de mapeamento por objeto de domínio e pr, pr detail objeto de domínio com base em o número de bancos de dados são domínios que estão presentes, certo? Portanto, você está mesmo em um nível de aplicativo, um aplicativo ou um aplicativo cliente pode ter requisitos de mapeamento diferentes de outro para que você os mantenha separados. Então, meu ponto é que, dizendo o ponto assembly get executando assembly, ele vai apenas atravessar para cada perfil de mapeamento que tem essa herança praticamente e ele vai apenas funcionar. Tudo bem, não há maneira mais fácil de ver isso. Então é assim que estamos registrando nossa parte superior de outono em nossa injeção de dependência. E isso é configurar mapeador de outono em geral. Então, se construirmos e for bem sucedido, então voltamos em seguida e continuamos nossa configuração de aplicativo. 8. Crie perguntas com MediatR: Bem-vindos de volta, rapazes. Nesta lição estaremos implementando dois padrões que nos ajudam a promover o acoplamento solto através de nossa aplicação. Eles são o padrão mediador e o padrão C QRS. Saber que o padrão mediador é visto como um padrão comportamental porque permite que você defina exatamente como um conjunto de objetos interagem uns com os outros. Em termos mais simples, você faz uma solicitação e você obtém um resultado com base em sua solicitação. Toda vez que você faz essa solicitação, você pode esperar esse tipo de resultado que é um tipo de consistência que ajuda você a implementar. Ele também ajuda você a obstruir toda essa lógica associada a essa solicitação do aplicativo de chamada. Agora, para ver o padrão QRS e ver QRS é abreviação de comando e Segregação de Responsabilidade de Consulta. Ele ajuda você a separar as operações de leitura e gravação de qualquer armazenamento de dados. Então, no comando name e comando query é qualquer coisa que vai aumentar os dados, qualquer operação de gravação, qualquer operação de atualização. E uma pergunta sou eu lendo os dados. Então você sempre pode saber que quando você está fazendo algo que vai aumentar os dados, é um comando. Se você ler em dados, é uma consulta. Então vamos começar. Nós vamos para o novo get primeiro, e nós vamos pegar o pacote mediador, que é interessante o suficiente, autoria da mesma pessoa que nos deu todo o mapeador. E esse é Jimmy BullGuard. Então vamos em frente e instalar isso. E quando isso for feito, voltaremos ao nosso método Configurar Serviços de Aplicativo e faremos algumas alterações aqui. Alguns desses foram descuidos da minha parte inicialmente, e peço desculpas. Então estamos mudando isso de uma voz para um serviço de IA chamado elétron, esse é um. E então estamos adicionando essas duas linhas. Estamos vendo serviços ponto adicionar mediador, assembly, dot gif execução assembly, basta deixar o mapeador automático e estamos retornando serviços. Então, para o termo imediato ADD, apenas indo para ir em frente e incluir as referências que faltam. E lá vamos nós. Então é assim que este registro de serviço ou método de coleta de serviço de AI deve ser parecido. Agora que fizemos essa parte, vamos voltar atrás e reunir nossos pensamentos e pensar o que precisamos fazer, precisamos implementar os padrões PQRS. Então o CQ são pontos são, e mais uma vez separa comandos de pedreiras. Em outras palavras, precisamos de pasta para comandos, precisamos de uma pasta para nossas consultas. Qualquer comando ou consulta será tratado pelo que chamamos de manipulador. Então, quando você faz uma solicitação, ele é tratado eo manipulador vai ser ou um comando para aumentar os dados ou algo para retornar dados. Então você vê que há algumas partes móveis neste ponto. E é por isso que isso pode ter tantas opiniões sobre como ele é implementado. Então, mais uma vez, eu não estou prescrevendo um método de implementação ou estrutura de pastas, mas eu estou apenas ajudando você a visualizá-lo. Você pode alterá-lo com base em suas necessidades. Mas este é o mundo inteiro foi para abordá-lo tanto que cria uma nova pasta dentro do projeto ou obrigação, eu estou chamando de recursos. E, em seguida, dentro dos recursos, vamos ter pastas por tipo de domínio. E a razão pela qual eu digo tipo de domínio é que o recurso do aplicativo é relativo ao que você vai estar fazendo contra o nosso objeto de domínio contra as ações destes, certo? Então eu vou estar fazendo isso em pedaços com base na tabela ou tabelas características específicas que o aplicativo oferece. Então vamos começar com um simples como tipos de licença. Dentro de recursos vamos ter tipo licença. Eu vou apenas perceber este tipo de folha. E, em seguida, dentro da pasta de tipos de folha, eu vou ter algumas outras pastas. Eu vou ter manipuladores de solicitação, em seguida, dentro manipuladores sobre quando ter comandos e consultas. E essa é a estrutura de pastas com a qual estarei trabalhando. Agora, como eu disse, opiniões diferem em espera. Uma estrutura polar poderia olhar. Algumas implementações teriam realmente o nível superior para o fictício no nome do recurso. E então eles teriam comandos e consultas. E, em seguida, dentro de comandos ou consultas, não é onde eles teriam todas as solicitações ou têm uma pasta, desculpe, por consulta, digamos dentro de consulta, eles teriam uma pasta para a consulta específica, digamos get tipo folha que será a consulta. Então, dentro de que você tem a solicitação de tipo de folha boa, obter tipo de folha requestHandler e o BTO específico para ele. Então, mais uma vez, há muitas maneiras de você ver isso implementado, mas os conceitos permanecem os mesmos. Você só quer ter certeza de que você pode identificar comandos de forma diferente de suas consultas e saber onde suas solicitações estão. As solicitações são relativas a um 100. Então, agora que temos a estrutura de pastas no lugar, vamos começar com alguma codificação. Então, dentro dos pedidos, o primeiro pedido que eu quero é obter a lista de tipos de folha. Então a convenção de nomes sábios, você sempre quer sugerir para que é o pedido ou que tipo de pedidos no nein, certo? Então obter lista de tipo de licença e eu vou especificar solicitações. Tudo bem. Então, obtenha solicitação de lista de tipo folha. E esta é uma classe pública e vai herdar de solicitações de E/S. Então, isso é cortesia do mediador, e ele vai então perguntar, o que esse pedido deve esperar em troca? Então, quando solicito o uso deste tipo de dados, o que devo receber de volta? Bem, você não deve estar recebendo de volta um tipo de folha de lista DTO, porque mais uma vez, os objetos de transferência de dados R1 entrarão e o que nunca os objetos de domínio. Portanto, são esses os nossos pedidos, no entanto. Pode haver momentos em que você pode ter parâmetros que eles podem colocar em solicitações e assim por diante. Mas este é muito simples. Não vou entrar em nenhuma dessas complicações ainda. Então esse é o nosso primeiro pedido. Em seguida, precisamos de algo para lidar com este tipo de pedidos. Agora esta é uma solicitação GET que torna consulta. Então, dentro da seção do manipulador, eu vou para a pasta de consultas e eu vou dizer adicionar uma nova classe e eu vou chamar este um os manipuladores de solicitação. Então essa é a minha convenção de nomes. Então eu tenho um pedido por um nome e, em seguida, eu apenas anexar manipulador. Então vamos em frente e adicioná-lo como uma classe pública, que vai herdar um manipulador de solicitações mais uma vez, cortesia do mediador. E então eu solicito manipulador diz, Ok, o que solicita-los idealmente largura, então seu pedido é os pedidos GET. Certo, então essa é a convenção de nomes que eu gosto de usar. E mais do que isso, você vê que convenção de nomenclatura muito porque então você pode especificamente vincular nossa solicitação a um manipulador por que da mesma forma, um é o pedido, um é o manipulador de solicitações. Então você pode ir em frente e incluir quaisquer referências ausentes. Então ele diz o que pedidos que meu manuseio eo que eu deveria estar esperando para retornar. Portanto, o tipo de retorno da solicitação deve ser o tipo de retorno. Você esteve aqui. Portanto, é esperado para retornar o tipo de licença DTO. O que eu listei fora da diabetes foliar. Muito bem, agora que está feito, ainda temos a nossa linha vermelha. Esta linha vermelha é porque precisamos implementar a interface. Então quase automaticamente, nós realmente obter um método aqui que diz tratado. Ele recebe a solicitação como o parâmetro. E então aqui é onde escrevemos todo o código para lidar sempre que este pedido entra. Agora, antes de começarmos a lidar com qualquer pedido aqui, temos algumas dependências. Primeiro, precisamos falar com o banco de dados. Não implementamos nada, mas temos nossos contratos de persistência. Então estes são contratos que vão realmente falar com o banco de dados. Então ainda não estamos interagindo diretamente com o domínio aqui. Certo, preciso injetar as referências que faltam. Então, usando S3 ou banheira, banheira, eu vou obter construtor e, em seguida, eu vou injetar e eu deixar repositório tipo. Então eu vou apenas para ir em frente e adicionar quaisquer referências que faltam. E depois de ter digitado no construtor, eu posso saber, dizer criar e atribuir um campo. Tudo bem, lá vamos nós. E eu costumo usar o sublinhado porque eu gosto de ver o sublinhado. Então eu sei que este é definitivamente o campo privado da turma, então essa é a minha convenção de nomes. Você não tem necessariamente porque você vê que o código gerado automaticamente não lhe deu um sublinhado, então tudo bem. Agora outra coisa que eu gostaria de injetar é I mapeador, porque eu preciso fazer algum mapeamento quando eu obter os dados do banco de dados, quando este repositório retorna os objetos de domínio, eu preciso convertê-los em detalhes para enviar o Buck. Então eu preciso automaker também, então eu sou superior, incluir referências ausentes também ir em frente e injetado ou cria NSA no campo. E lá vamos nós. Então temos tudo injetado e pronto. Agora, para implementar este código manipulador, o que eu vou fazer é executar uma consulta contra o repositório tipo folha. Então eu vou dizer var folha fetch é igual a 08, deixar o repositório de terapia ponto obter tudo. Isto é uma espera. Então isso significa que este método precisa ser assíncrono. E então você verá que o único erro desaparece pelo menos. E então o que precisamos retornar é a lista do tipo de folha ETL. Então eu vou dizer retorno mapeador ponto mapa. E então é aqui que isso vem a calhar em detalhes do tipo de folha, mas é uma lista do tipo de folha D2 ou outro. E o que eu vou mapear para que será a lista de objetos de domínio provenientes da consulta. E lá vai você. Todo mundo está feliz. Então sempre pedi para dizer que eu quero as listas de tipos de folhas, então nós temos o manipulador dizendo, Ok, eu posso lidar com este pedido para você. Então é isso que queremos dizer definindo comportamento do aplicativo ou definindo como os objetos se relacionam uns com os outros. Este pedido sempre se relacionará com este caçador. Eu acredito que se você experimentá-lo, vários manipuladores para as mesmas solicitações, você realmente correria para erros de tempo de execução por causa de alguma ambiguidade. Então é assim que podemos definir claramente que quando você fez este pedido, você sempre pode esperar o comportamento. Agora vamos olhar para outro pedido e ainda vai ser uma consulta. Mas desta vez quero uma lança. Tipo de folha. Então eu estava dizendo que você pode ver solicitações ou você pode acabar tendo campos ou propriedades dentro de seus pedidos que serão necessários para lidar com a operação específica. Então, e se quiséssemos obter o tipo elif, não a lista inteira, mas o detalhe do tipo de folha. Então vou criar outra pergunta. E este vai ser bom. Deixar solicitações de detalhes do tipo. Mais uma vez, lembre-se de torná-lo público. Agora, nesta situação, eu vou somar propriedade e eu vou dizer id. Então nós estamos recebendo o detalhe, o que significa que nós queremos um registro específico. E a melhor maneira de especificar um registro é enviando o ID. Então precisamos de um encarregado para este pedido. Então eu vou adicionar esse manipulador e a outra classe ou recebe os pedidos de detalhes do tipo 100. Lá vamos nós, torná-lo público. Não, um passo que perdi dentro dos pedidos que eu precisava herdar de I solicitações. E ele só está esperando um tipo de folha DTO um desta vez, certo? Tantos pedidos DTO, vá em frente e atender em todas as referências faltantes. Lá vamos nós. Então, o manipulador agora vai herdar de eu solicitar manipulador e ir em frente e adicionar referências ausentes. Ele vai ser lidar com solicitações para boas solicitações de detalhes do tipo Leave, e é esperado para retornar o tipo ETL. Então, uma vez que todas essas referências faltantes desapareceram, vá em frente e implemente a interface, e então começamos com isso. Agora vamos precisar basicamente das mesmas injeções que tivemos que usar. Eu só vou agilizar isso e copiar e colar esse código e apenas mudar o nome do construtor e ir em frente e adicionar todas as referências que faltam. E uma vez que você tenha feito tudo isso, você pode começar com o código específico. Então, nesta situação eu diria var tipo de licença é igual a e estamos com a chamada de método. Então deixe o repositório dot get e recebe o seu esperando um ID. Então eu tenho o objeto de solicitação aqui dentro do portal manipulado métodos. Agora posso dizer pedido ponto i e. Tudo bem, novamente, onde estamos ensinando? Então este espaçamento, mas eu estou apenas mostrando que é assim que você usaria esses campos em sua consulta, em seu repositório genérico ou próximo, desculpe. Então, quando você tem métodos específicos definidos dentro do repositório tipo folha, então você pode ter campos mais específicos para suas solicitações que são necessários para lidar com esses tipos de operações. Então, uma vez que obtemos isso, a próxima coisa que precisamos fazer é retornar os objetos DTO tipo folha. Então eu vou dizer mapeador, mapeado em detalhe tipo folha e estamos mapeando o tipo. Então, mais uma vez, apenas detalhes. Agora uma coisa a observar é que em manipuladores que têm uma separação clara entre os comandos e as consultas. Mas nos pedidos não há separação clara. Então, quando os pedidos começam a ser criados para os comandos, temos que confiar em nossos olhos. Temos dois OK. Não estamos cansados para não nos confundirmos quanto ao pedido de água. E eu não acho que isso seja muito eficiente. Então eu vou ter comandos dentro de minhas solicitações, e eu também vou ter consultas. Então eu sei que sempre que eu quero qualquer pedido, tristeza e indagações, eu sei exatamente para onde ir. E o mesmo para comandos. Então, como eu disse, eles são estrutura de pastas diferentes. Algumas pessoas mais uma vez teriam dito apenas deixar tipos. E então eles teriam os comandos. E então, em vez dos comandos que teriam os diferentes comandos com todos os recursos necessários para esse comando específico, o detalhe, o manipulador, a solicitação, tudo nessa subpasta. Então, à medida que você quebra este inodoro que você vai precisar de mais arquivos, mais pastas porque você quer ver uma separação clara tanto quanto possível. Mais uma vez, disse que isso é implementado é relativo ao criador. Então eu vou apenas mover minhas consultas que eu criei até agora para essa pasta específica. E, claro, depois de atualizar esse namespace. E uma vez que eu fizer isso, eu vou ir em frente e atualizar meus manipuladores para saber a nova localização de seus pedidos correspondentes. Então, com tudo isso, Dawn, eu vou fazer uma construção e construir foi bem sucedida e você vê como tudo está se juntando. Então, se você quiser, você pode ir em frente e implementar os outros recursos que começamos com tipos de folhas. Você pode, pelo menos, implementar o diferente, os dois ler ou as duas operações de consulta relativas à alocação de licença e relativo à solicitação de licença. 9. Terminação consultas para MediatR: Bem-vindo de volta caras que estão continuando na mesma linha de configurar nossas consultas para nossos recursos adicionais. Então já passamos por fazer isso para tipos de folhas. E a tarefa era fazer isso para pedidos de licença e alocações de licença. Então eu já fiz isso e eu vou apenas te guiar. Então, se você não completou, eu vou devagar o suficiente e explico tudo o que estou fazendo para que você possa replicá-lo. E se não, então nós podemos apenas comparar notas e sinta-se à vontade para me dizer se você fez algo diferente de como eu fiz isso. Então, o primeiro, Vamos começar com alocações de licença. Então eu tenho as consultas e eu tenho o, o que eu tenho os manipuladores e os pedidos, e eu tenho as consultas em qualquer um. Agora seguindo o padrão até agora você veria que ou missões parecem bastante semelhantes ao que eles pareciam para um tipo de folha. Temos a solicitação detalhada de alocação de licença get, que leva o ID. E também tenho um para a lista. Tudo bem, então na pergunta é, eu tenho uma pequena surpresa para você. Eu não sei se você fez isso dessa maneira, mas eu vou te explicar exatamente o que foi feito de forma diferente. Então, é claro que estamos incluindo a saudação correta, O repositório de alocação de licença em vez do repositório tipo folha porque estamos lidando com locais Levi direito. Agora, em termos de nossa manipulação, você veria que eu tenho um método aqui que nós não passamos em nosso, em nossa configuração de repositório. Tenho alocação de licença com detalhes. Saiba o propósito de me especificar isso é que quando obtemos os detalhes da alocação de folhas e se você precisar de um lembrete ou deixar alocação realmente tem uma propriedade de navegação do tipo folha, que significa que se eu quisesse mostrar Que licença tem, que número de b depois, mostrar o nome do ícone da folha, mostrar o ID que é inútil, certo? Ou o cliente ou outro controle o id, eles precisariam de alguma quantidade de detalhes do tipo de folha em seu lado. Então, quando eu digo com detalhes, o objetivo desse método é fazer isso incluir essa propriedade de navegação e tudo que pelo tempo que eu recebo, mas que alocação de licença, eu teria toda essa lógica não A fórmula está pronta e tudo o que tenho a fazer é mapear e voltar. Então, neste ponto eu vou apenas pausar e 0 que você veria padrão de design às vezes onde eles realmente fazem toda essa lógica complexa bem aqui no manipulador. Então eu vi onde eles realmente se conectariam diretamente ao contexto aqui no manipulador. E, em seguida, fazer todas essas consultas cruas aqui mesmo no manipulador e, em seguida, massagens e, finalmente, retornar o que eles precisam para retornar. Então esse é um padrão de design que você pode ver. E o outro é onde abstraímos todas essas lógicas , consultas complexas e lógica de negócios. E depois mythos para o repositório. Não, eu não estou dizendo que um é melhor do que o outro porque eu tinha a abordagem tem seus prós ou contras em termos de fazer métodos que especificamente lidar com um cenário como obter a alocação de folhas com os detalhes. Em termos disso, poderia ser bom colocar isso em nosso repositório, um método onde você tem uma referência direta para onde esse tipo de operação de arte lógica volta está acontecendo porque você pode precisar reutilizar esse mesmo tipo de lógica em vários manipuladores. Então isso realmente reduziria a repetição dos mesmos tipos de consultas e os mesmos tipos de inclusões e tudo em vários manipuladores. Se você tiver apenas em um espaço de repositório. A desvantagem dos repositórios, no entanto, é por causa de como as coisas podem ficar específicas? Sim, nós temos o material genérico, mas obviamente este não é um comando genérico que cada recurso que nosso domínio me objeto, use da mesma maneira. Nós temos que ter um método específico e então nós provavelmente vamos acabar em um buraco de coelho de ter muitos métodos específicos em nosso repositório. Então esse é um dos sites não, o padrão do repositório sabe, como eu disse, se você fizer tudo aqui no manipulador, funcionaria. Mas, mais uma vez, a desvantagem disso é que você pode precisar repetir esse tipo de operação em vários manipuladores. E então você acaba repetindo código em vários lugares. E então a modificação pode se tornar difícil a longo prazo. Então essa é a surpresa Alpha. Então, se você der uma olhada em nossa interface, você veria aqui que realmente tem tanto para a lista quanto para o indivíduo. Agora o júri está fora se você precisa de ambos. A razão pela qual eu incluí o 14 e a lista, é claro, é que na lista, as alocações de licença, Eu quero mostrar o nome da licença e o d, O nome da licença e o nome do tipo de folha morta e o dy. Então eu precisaria incluir os detalhes aqui. E então, se você estiver visualizando um deles, você gostaria de ver os detalhes também. Então eu fiz isso e fiz a mesma coisa. E quando você está trabalhando com muitos de nós, você precisa navegar rapidamente. Então eu vou apenas usar esta seta azul para cima aqui para sincronizar armazenar este documento é rapidamente e, em seguida, deixar solicitações. Você vê que eu tenho métodos semelhantes porque nos pedidos de licença precisamos saber que tipo de licença está sendo solicitada. E se eu estiver vendo a lista, você gostaria de ver este tipo de folha foi solicitado nesta data, etc. Tudo bem. Agora, em termos de nossos pedidos de licença, eu tenho outro slide surpresa e espero que vocês tenham percebido e feito isso já. Mas as consultas parecem bastante iguais. Mas em termos de solicitações em vez, mas em termos do tipo de retorno, você notaria que eu tenho obter solicitação de detalhes de solicitação de licença mostrando as solicitações de licença DTO, no entanto, para a lista e discutimos por que iria separar os detalhes Mais cedo. Temos detalhes da lista de pedidos de licença. Então a lista está determinando uma lista dos detalhes especializados para a lista. E então os detalhes estão retornando o detalhe com muito mais detalhes nele. Para as consultas. Preocupações semelhantes para a lista de solicitações de licença, manipulador de solicitações. Claro que ele está retornando a lista de solicitações de licença DTO. E o manipulador parece palavras bastante semelhantes chamando um repositório de solicitação de exclusão e chamando as solicitações de licença get com detalhes similaridade. Quando estamos olhando para o manipulador de detalhes, é a mesma coisa, exceto que estamos retornando apenas os detalhes pedidos folha, o laboratório configurando isso, você pode ter notado que você está recebendo um monte de linhas vermelhas quando você são tipos incompatíveis. E se você tivesse o tipo de dados errado aqui ou o errado solicitaria o tipo sendo referenciado, tudo quebraria. Então é muito, muito rigoroso. Se você me disse que a solicitação está esperando DTO tipo de licença, você não pode colocar nenhum outro tipo de dados aqui nesse manipulador que você está dizendo que deve lidar com essa solicitação. Tudo bem, então você pode ter muito, muito cuidado com isso. E uma vez que você se acostumar com o padrão, essas coisas virão mais naturalmente. Eu só posso atribuir se for um pouco frustrante inicialmente. Mas, mais uma vez, você tem o código a ser referenciado para que você sempre possa apenas pausar quando precisar e replicar esses bits de código em seu aplicativo de acordo. Agora, em nossa próxima lição, vamos olhar para configurar nosso primeiro comando. E o comando mais uma vez aumentaria os dados no banco de dados. Então vamos olhar para o que é preciso para configurar, criar comando para qualquer um de nossos objetos de domínio. 10. Crie comandos com MediatR: Bem-vindos de volta, rapazes. Nesta lição, vamos dar uma olhada na configuração de comandos. Então, os comandos mais uma vez aumentam os dados e vamos começar com ou criar comando. Agora, se você estiver olhando para o meu Solution Explorer, você notaria que eu tenho mais alguns arquivos e eu tenho uma pasta D2L reestruturada. Então deixe-me derrubar todo o resto para que você possa se concentrar nessa seção. Então, nos estágios iniciais do planejamento deste tipo de arquitetura, você sempre estará mudando as coisas ao redor porque é bom obtê-lo direito de null em vez de mais tarde quando você tem muitos arquivos diferentes e qualquer mais, para , as atualizações quando você move, esses outros arquivos são de propriedade. Então, nos estágios iniciais da configuração dos detalhes, eu indiquei que você provavelmente gostaria de ter uma pasta para os detalhes e, em seguida, ter os diferentes tipos de detalhes lá. Então fizemos isso com as solicitações em que tivemos as solicitações de licença D2 e excluir detalhes da lista de solicitações em vez deixar a pasta de solicitação. Então eu acabei de estender esse conceito para os outros detalhes onde eu tenho uma pasta de alocação de licença e elif tipo pasta e nomear esta folha que detalhes profundos. Deixe-me corrigir isso. Então, dentro dessas pastas, vamos ter os diferentes detalhes. E mais uma vez, não é absolutamente necessário que ele tenha vários detalhes ou detalhes específicos para um propósito. Mas vou mostrar a vocês por que é benéfico fazer isso às vezes. Assim, com o tipo de folha, o risco é baixo. Temos detalhes de folhas. Tudo o que requer é um nome e o número padrão de dias. Para mim, isso é simplesmente o suficiente. Estes dados correm muito pouco risco de sobrepor nossa subexposição de qualquer coisa para qualquer das operações que podemos criar facilmente usando este detalhe, podemos listar facilmente e podemos olhar para os detalhes. É muito simples. No entanto, com solicitações de licença, discutimos que solicitações de licença DTO tem muito mais detalhes nele. Em uma configuração de lista, não precisamos de tantos detalhes. Você realmente só precisa dos detalhes do tipo de folha solicitado, a data em que foi solicitado, e se ele é aprovado. Agora, no Criar, mais uma vez não precisamos pedir ao consumidor que forneça todos esses detalhes. Porque se você comparar pedidos de licença dentária criar, nós realmente não precisamos da opção de data. E quando alguém está criando um pedido de licença, quando estou pedindo uma licença, não há ações de data. Então isso não precisa ser fornecido. A data solicitada que pode ser colocada por nós, pelo sistema. Não precisamos obter isso do usuário ou do consumidor. A data de início e término abreviada. Esses são essenciais. Precisamos saber o tipo de folha. Não precisamos saber todo o objeto do tipo folha. Só precisamos do identificador do que está sendo solicitado. E nesse ponto, não é aprovado nem cancelado. Então eu posso ter um detalhe específico e enquanto eu estou falando, eu estou vendo que eu tenho uma fusão extra isso, mas eu tenho um criar solicitações de licença DTO, que vai ter a data de início, a data término, o identificador para a folha de morrer sendo solicitada. E mais uma vez, o sistema pode ver a data solicitada. E eu preciso fazer isso realmente um anulável. Então eu vou usar esta oportunidade para ajustar isso. Então isso precisa ser anulado, mas eu não preciso do remetente no Creates. Eu tomo tudo junto, criar no pedido de licença, eu vou torná-lo anulável porque regra de dedução realmente significa quando foi aprovado ou cancelado. Certo? E então, da mesma forma, eu vou apenas fazer isso direto para o domínio. Mais uma vez, é bom ver essas coisas cedo e ajustá-las porque nós fizemos o banco de dados ainda, então não temos que nos preocupar com isso rasgando muito. Tudo bem? Então é por isso que eu tenho um DTO específico para criar a solicitação de licença, diferente da listagem, diferente dos detalhes. Em outro, quando temos a alocação de licença e desalocação tem um número destes, os detalhes do tipo de folha que está relacionado a ele, identificador e o período. É semelhante ao pedido de licença. Eu não preciso dos detalhes do tipo de folha no tipo de tempo de criação. Então, quando falamos sobre postagem excessiva, isso significa que estamos dando ao aplicativo cliente a oportunidade de fornecer muitos dados. E então é aqui que hacking e dados ruins e pessoas introduzindo anomalias em seu banco de dados, é assim que isso acontece. Portanto, esta é uma boa maneira de restringir o que pode acontecer em uma operação. Então saiba disso. Tenha uma boa compreensão de por que temos mais detalhes introduzidos. Vamos dar uma olhada nos comandos. Então eu vou começar com o mais fácil, que é os comandos de tipos de folha. Vou pedir e vou criar uma nova classe. E este Gaumont vai ser muito específico criar tipo folha pedido. Então essa é a solicitação para criar um tipo de folha e foi para ir em frente e adicioná-lo e torná-lo uma classe pública. E então este está herdando como sabemos do que eu pedi. E ele vai retornar, eu vou fazê-lo retornar um inteiro 0. Este inteiro será. O nome ou desculpe, o ID do valor ou o registro foi criado. Tudo bem, então você cria, nós vamos apenas dizer-lhe o ID do que você criá-lo. Não sabemos o que o cliente pode precisar fazer após a criação, mas estamos dando a eles, mas o ID salvo, eles precisam ir para a página de detalhes depois. Isso é com eles, mas estamos dizendo que foi um sucesso. Aqui está a identificação do novo disco. Agora no comando, o que vamos ter, como sabemos que o meu nulo é o nosso manipulador correspondente para este pedido. Então herdamos de eu solicito manipulador. E eu solicito manipulador vai estar implementando a solicitação de tipo folha de criação. Vá em frente e inclua qualquer coisa que esteja faltando. E ele verá que está retornando um inteiro. Agora, quando implementamos a interface, você verá que obtemos essa tarefa retornando um inteiro e nosso manipulador. Agora vamos voltar para os pedidos deles por um tempo. E há poucos padrões que você pode ver no pedido de criação. Um padrão é que as pessoas realmente escreveriam todos os campos que quando você está prestes a criar um registro para este ano, enviando sobre as solicitações para criar registro para esse tipo. Eles colocaram nos campos na solicitação real para ver essas são as taxas que você está autorizado a enviar com a solicitação. E então, naquele momento, esse pedido basicamente serve o propósito do meu detalhe que acabei de definir aqui. Não, eu, pessoalmente, não gosto de misturar e combinar. Eu não gosto de ter detalhes aqui, mas quando eu crio, eu tenho os campos aqui. E então, você sabe, eu não sei para onde ir e eu preciso mudar o que acontece às vezes eu não me lembro. Em vez disso, eu mantenho tudo em um nível de detalhe e o pedido é realmente apenas um mecanismo para transferir os dados. Então o DTO representa os dados e a solicitação é apenas esse transporte. Com tudo isso dito, vou apresentar nossa propriedade neste pedido de licença tipo DTO. Portanto, esta propriedade é o que o consumidor irá preencher com o pedido e enviá-lo para cima. Então, em nosso comando, sabemos que dizemos solicitar diabetes folha de ponto, que é onde os dados estão. Então, é claro, se vamos interagir com tipos de folhas e mapeador automático, então vamos precisar de nossos suspeitos habituais em nosso construtor para ser injetado. E para velocidade novamente, aqueles voltam para um dos manipuladores existentes e apenas copiam e colam, alteram o nome do construtor. E depois incluímos todas as referências que faltam. Tudo bem, para trabalhar de forma mais inteligente, não mais difícil. Agora que temos todas as ferramentas que precisamos, como configuramos nosso manipulador para criar esse registro? Mas antes de seguir em frente, vou fazer um ligeiro ajuste. Então um outro padrão que você verá, e eu acho que vou usá-lo desta vez só porque é para mim, é mais limpo em vez de pedidos. Então, quando estamos lidando com comandos, não, não vai ser nosso pedido porque eu peço é quando você está pedindo algo, esse comando é quando você está dizendo algo. Você quer um comando. Então, em vez de nós usando solicitação no nome aqui onde dizemos criar folha tipo comando. Tudo bem, então, renomeando a fonte, eu posso carregar o IntelliSense para renomeá-lo através da placa, mas eu vou renomear o arquivo manualmente. Então nós temos criar comandos tipo folha, então nós sabemos com certeza que este é um comando e é obviamente o manipulador deve estar carregando todo o seu comando. Então Command Enter, tudo bem, e atualizar quaisquer outras referências estão no lugar. Então eu acho que isso é realmente mais limpo e mais fácil para os olhos. É um distinto entre o que eu peço aulas sobre o que nossas classes de comando resolvem para nossa operação. O que vamos fazer é definir o tipo de folha para ser igual. E então nós vamos apenas usar o mapeador automático para mapear em tipos de licença. Então, estamos mapeando do detalhe para o objeto de domínio desta vez nosso próprio. Então mapeador tipo de folha de Dartmouth, intercalado toque nosso olhando para o tipo de folha de ponto pedido BTO. Certo, então vá em frente e inclua qualquer coisa que esteja faltando. Lá vamos nós. Então agora dizemos que tipo de licença é igual para obter a versão limpa do objeto de domínio. Então nós realizamos o nosso, isso vai dizer tipo de licença é igual a e nossos pesos em nós vamos chamar nosso repositório tipo folha dot adicionar blocos de método, certo? Então lembre-se que ele está realmente retornando o objeto ou algo fora do mesmo tipo de dados, certo? Então o tipo de licença agora vai ser atualizado porque depois Entity Framework, que é o que vamos usar como nosso RM. Depois que ele faz sua operação vai atualizar o ID. Então, estamos retornando o objeto com ID atualizado e sabemos que temos esse ID. Podemos dizer retorno, tipo de licença, ID de ponto. Lá vamos nós. Então saiba que o comando foi tratado. Nolan, olhamos para ele, vemos que não era tão complicado de fazer. São apenas três linhas onde obter o pedido com os dados. E então vamos mapeá-lo para os objetos de domínio. Nós vamos então chefes ou dentro de um repositório ou para que a operação ocorra. E então nós estamos apenas retornando a idéia e é isso para o comando create leaf type. Então você pode parar aqui e pedir-lhe para fazer isso com os outros. Eu vou fazer isso e depois podemos comparar notas. Tudo bem, então eu pulei em frente e eu fui em frente e implementei os comandos que criam comandos para os outros dois objetos de domínio. Então, se você olhar para ele com cuidado, você vê que é praticamente a mesma citação além dos nomes e repositórios envolvidos, é praticamente o mesmo código. Então este é o manipulador de comando leave allocation. Você pode pausar, você pode replicá-lo se precisar. Mas esse é o nosso manipulador de criações e nossa busca de carreira. Apenas pegando que criar detalhes alegação de licença em vez do detalhe alegação de licença. Tudo bem. Da mesma forma para o pedido de licença, mesmo código, mesma estrutura, certo? E, em seguida, o comando, é apenas tomando o detalhe de solicitações de licença para criar o detalhe da solicitação. Então você vê que todos esses tipos de parecem muito semelhantes. Então você pode ir em frente e replicar aqueles em seu código. E quando voltarmos, vamos olhar para os outros comandos que incluiriam atualização e exclusão. 11. Finalizando comandos com MediatR: Muito bem, pessoal, bem-vindos de volta. Como você notou, minha tela está em branco. Nesta lição, vamos falar sobre adicionar os manipuladores de atualização e exclusão e todos os ativos que acompanham eles. Então minha tela está em branco porque eu adicionei alguns ativos e eu vou passar por eles um por um com você e você pode ir em frente e replicá-los. Mas quero que entendamos as decisões que estamos tomando neste momento, pois são decisões críticas. E esse tipo de arquitetura, as coisas que você coloca lá, tudo baseado em decisões. Mais uma vez, eles são relativos ao que você está trabalhando, sua equipe e o aplicativo geral sobre o que você espera realizar. Então vamos começar olhando para os detalhes. Onde é que eles estão? Passamos pelos detalhes e nós meio que os separamos por pastas para que possamos ver todos os detalhes relativos a um tipo de domínio com bastante facilidade. Mas então, neste ponto, nós tínhamos um VT0 para o tipo de folha, e nós dissemos que, ok, isso era de baixo risco porque ele poderia ser usado para muitas operações diferentes. Desde então, dividi-o em dois. E a razão para isso é que você criou folha tab2 diferente do tipo de folha D2 e tudo. Por quê? Como o detalhe do tipo de folha herda do detalhe base e da base D2, lembre-se dá-nos o ID, saber o risco disso. E mais uma vez, o objetivo do detalhe é reduzir o que chamamos de postagem. Se estou criando um tipo de folha, não preciso de um ID. Eu não quero dar ao consumidor a capacidade de fornecer um ID porque isso apenas daria problemas. Estou a dar-lhes exactamente o que precisam para passarem pela operação. Então eu criei um novo detalhe para o tipo de folha onde eles só obtêm nome e ações padrão. Eles não podem fornecer um campo de ID. Detalhes do tipo de folha pode ser usado para todo o resto, para edição, para visualização, porque bem, ele tem esses campos, bem como BCE, que é o ID. Agora, como você pode acabar recebendo mais e mais detalhes e você tem sentimentos repetindo através dos diferentes detalhes, então você pode querer considerar ter uma pasta comum dentro dessa sub-pasta já para tipo de definir esta propriedade é que este detalhe deve ter de qualquer maneira. Assim, qualquer tab2 folha que irá surgir com a maioria do háfnio e deve ter dias padrão. Você pode definir uma classe base se precisar dela. Tudo bem, agora nós podemos passar para as alocações de licença tem três detalhes de alocação de licença neste momento, e eu vou apontar um erro que eu cometi em um deles. Esse erro era ter cria detalhes de alocação de licença herdando desse detalhe. Tudo bem, então você tem que ter cuidado com essas coisas se estamos tentando ser rigorosos. Então isso foi um erro da minha parte. Criar detalhes de alocação de licença mais uma vez não deve ter absolutamente nenhuma referência a qualquer chave primária. Mas então precisamos dos outros campos. As atualizações, no entanto, precisam de acesso ao DTO base para nossos propósitos de atualização. Agora, pode ser que nós dissemos, ok, bem, mais uma vez, criar o detalhe base de que todos herdam. Ou podemos apenas morder a bala e dizer que vamos usar 14 criar ou atualizar se o ID for fornecido e sabemos que é uma atualização se não for impedido e assumimos que é eu criar, esses poderiam ser facilmente argumentos que eu não estou vendo, Não, não estou vendo sim. Depende de quão granular você deseja obter e estas são suas decisões a tomar com base em seu contexto. Só estou apontando as diferenças e os riscos de acordo. Então eu vou estourá-los assim. Não Para pedido de licença passa ainda por outro nível. Então nós temos o detalhe do pedido de licença quando familiarizado com isso. Temos o detalhe da lista que já estabeleceu por que isso é diferente. Nós temos o Criar que mais uma vez é incorretamente, pelo menos no meu contexto herdando disso, que eu vou caracterizar nulo. E então eu tenho que ter atualizado o detalhe da solicitação diferente do detalhe de aprovação da solicitação de licença alterado? Não, você vai perguntar. Ok. Então, por que os dois? Porque ambos estão falando sobre aumentar os dados. Tudo bem. Bem, mais uma vez, é uma questão de host enganado que você quer ser para que a atualização serve o propósito de permitir que o usuário ou o consumidor para permitir que o usuário final para atualizar suas solicitações. Eles queriam talvez mudar as datas de início ou o fim talvez eles escolheram férias quando este deveria ter escolhido doente. Talvez queiram colocar novos comentários ou simplesmente cancelá-los. Então eu estou dando a eles exatamente o que eles podem fazer usando este DTO se eles enviarem sua solicitação para atualização. Estas são as únicas coisas que podem ser atualizadas. No entanto, altere a aprovação da licença. Solicitar, desculpe, deixar detalhes de aprovação de solicitação, desculpe, teria apenas a capacidade de alterar. É aprovado DSR nulo. Então o aprovador está realmente dizendo sim ou não. Quero dizer, se você tivesse mais campos como comandos adicionais e qualquer coisa que você poderia adicioná-los ao DTO. Claro, eles teriam que ser apresentados os objetos de domínio. Mas o que quero dizer é que estou usando os detalhes aqui para me ajudar a impor certas regras de negócios e certos comportamentos que meu aplicativo é capaz de fazer. E, e mais uma vez, eu vi situações em que há um plano D cerco e decisões são tomadas nos 100 que, com base nos dados presentes, talvez na solicitação estejam nos detalhes. Este é o tipo de operação a ser realizada. Então depende de quanto você quer quebrar ETL para ter esse nível de granularidade. Então você sabe, se é uma aprovação solicitada, saiba exatamente qual manipulador ir. Ou você pode ter um grande manipulador de comando que está tomando os dados e um monte de instruções if para ver se ele é, se o ID está presente, então se ele não está presente, então ele, Mas, em seguida, se ele está presente e este sinalizador não é nulo, então suponha que é uma aprovação. Você poderia fazer desse jeito, mas eu não vou fazer dessa maneira. Prefiro saber que quando é um pedido de aprovação, tenho o comando de alteração de aprovação. Se for uma atualização, é um comando de atualização e saber exatamente onde ir para fazer o quê. Então, agora que temos essa explicação detalhada fora do caminho, eu vou saltar para os recursos, pastas em futuros, em alocações de licença e tipos de licença pelo menos eu já defini os novos manipuladores e seus comandos. Então vamos dar uma olhada no mais simples. Então, temos o comando update leave type. E este comando para o tipo de folha está apenas tomando nossos pedidos estão herdando de Eric Quest como sabemos, mas então ele está retornando o que vamos chamar de unidade. Então, se você apenas passar o mouse, você precisa ver que é uma construção fornecida por mediador que não representa nada como vazio, certo? Sem conteúdo. Então, no design da API, quando você faz uma atualização, você geralmente retorna em 202, se não estou enganado, o que é abreviação de nenhum conteúdo. Significa que foi bem sucedido, mas não tenho nada para te mostrar. Isso é basicamente o que a unidade é. E então nós estamos tomando esse tipo de folha DTO como a propriedade. Ainda não implementei os comandos nos manipuladores, então podemos fazer isso juntos. Só estou mostrando que temos a mesma construção para o comando update leave allocation, onde estamos pegando o detalhe de alocação de licença de atualização e devolvendo essa unidade. E temos esse comando definido de acordo, também vazio. Então vamos fazer esses dois juntos porque esses são bem simples. E então vamos passar algum tempo explorando os pedidos de licença e as regras de negócios lá. Agora o fluxo de trabalho para o nosso manipulador, e eu vou começar com o manipulador de comando tipo folha. Tudo bem, o fluxo de trabalho aqui é que precisamos querer recuperar o registro original para atualizar que a origem são necessários e, em seguida, três, enviar tudo para o banco de dados e, em seguida, retornar a unidade, ou pelo menos algo para dizer que foi bem sucedido. Então, duas abordagens. Primeiro, você pode usar o repositório para ter esse método específico porque, no caso das solicitações de licença, pode haver métodos específicos. E então, mais uma vez, você vai descer aquele brinquedo de coelho. Ter métodos muito específicos em cada repositório ao longo da linha. Ou você pode apenas fazer a maior parte do trabalho dentro de um manipulador, que é o que serve de qualquer maneira. Tudo bem. Então eu só vou dizer var tipo de licença é igual a deixar tipo repositório, Git. E então nós estamos olhando no pedido, olhando na folha para estar olhando para a identificação. Agora, outro padrão de design que eu vi é quando é um comando update leaf type, eles usariam o tipo de folha regular, digamos aquele que não tem o ID, mas então coloca a propriedade ID dentro da requisição ou do comando para que nós, quando você está fazendo o atualizado para incluir o ID dentro deste objeto. E então o detalhe é apenas em si. Há tantas maneiras de fazer isso. E mais uma vez, aqueles que você entende o que está fazendo, você pode me fazer a melhor implementação com base no seu contexto. Aqui. Tipo de licença será recuperado com base no ID da carga que vem com a solicitação. E então podemos ver mapeador não MOP. E, em seguida, mapeador ponto mapa é praticamente apenas indo para, nesta situação, obter a solicitação pensamento folha tipo D2. E observe que eu não estou especificando, eu preciso digitar desta vez. Estou usando parênteses, mapa de pontos do mapeador, parênteses abertas. E então vejo que esta é a fonte dos dados. E eu quero que o tipo de folha que acabou de ganhar do banco de dados seja o destino dos dados. E eu estou recebendo essa linha verde porque eu falhei com ela na linha. Peço desculpas. Então lá vamos nós. Então mapeador ponto mapa e, em seguida, ele ver por favor apenas atualiza o que está à direita com o que está à esquerda, que pode ser diferente se é diferente ou não, este, por favor atualizá-lo porque a atualização vai enviar mais. E é por isso que nossos detalhes precisam ter tantos campos quanto os dados, o próprio objeto de domínio possível. É bom. Nome Dava vai ter dias padrão. Não sabemos o que mudou, então é por isso que estamos vendo outono superior, basta atualizar todos os valores. Se esse Blanco é o nome, então vamos atualizá-lo para um nome em branco. Espero que não tenham. No entanto, se eles não mudaram de nome, então a expectativa é que o mesmo nome vai voltar. Então, mais uma vez, não podemos explicar o que poderia ter sido queixo. Então, estamos apenas vendo, por favor atualize o tipo de folha com os valores correspondentes provenientes do objeto à esquerda. E então vamos pesar nossa atualização do repositório de neve. E, em seguida, este é o lugar onde nós enviamos sobre nosso tipo de folha post mapeamento ou enviá-lo para a Atualização. E então nós apenas retornamos o valor do ponto da unidade. E é isso. Essa é a nossa operação de atualização. Bem, eu tenho esta linha vermelha aqui em cima porque eu tenho int e não unidade. Então, depois de mim essa mudança, tudo está bem. Então isso é para a obesidade no tipo de folha ou o quê? O tipo de folha. Então, na verdade, vou copiar isto. Não vou me dar muito trabalho. Vou pular para atualizar a alocação de licença. E a única coisa que vamos estar fazendo diferente aqui é que em vez de usar o repositório tipo folha, eu vou estar usando o repositório de alocação de licença. Em vez de ver o tipo de folha DTO, estou vendo alocação de licença BTO. E em vez de chamar o tipo de folha de objeto, eu estou chamando isso de alocação de licença, todo o resto é praticamente padrão e praticamente o mesmo. E isso vai lidar com nosso pedido de atualização. Tudo bem, então eu fui em frente e completou os comandos leave request para atualizar LaCo, não vemos que não é tão complicado ou então eu fui em frente e fiz o comando update leave request e correspondente manipulador. Então, nossa licença solicita manipulador de comando retirado da unidade de retorno de comando. E é apenas saber a diferença mais uma vez, é o repositório que está sendo usado, mas é praticamente a mesma operação. Agora, uma coisa que você pode querer considerar são as regras de negócios específicas, nossa própria este tipo de operação. Então, sim, o código, parece o mesmo, mas ao atualizar um pedido de licença, pode haver outras coisas que precisam acontecer. Certo. Assim, no caso da alteração, solicitação, alteração e aprovação do pedido de licença, onde só somos aprovados ou não. Também precisamos definir a ação que também precisamos para atualizar algumas outras coisas. Então eu acho que você seria bom se tivéssemos uma função específica em nosso repositório para lidar com a solicitação de alteração. Agora, a coisa legal sobre solicitações é que nós não necessariamente temos que ter nossas solicitações por hora por todo o tempo. Eu poderia realmente reutilizar o mesmo pedido e manipulador para lidar com este tipo de operação. Então vamos olhar para esta situação. Então, dentro da atualização, deixar, não deixar alocação, desculpas, dentro do comando de solicitação de licença, poderíamos ter a licença requisições DTO, mas eu também poderia ter uma propriedade do tipo alteração licença solicitação DTO aprovação. Portanto, este pedido é capaz de ter qualquer um desses objetos. Agora, no manipulador, eu posso tomar uma decisão e chamar o método apropriado baseado nisso porque ele ainda é um comando de atualização, certo? Então, dentro deste manipulador de comando de atualização, eu posso colocar em um pouco mais de lógica. Eu posso ver se o detalhe do pedido de licença ponto não é igual a nulo, então esta é a rota que eu gostaria de tomar. Consigo ver outra coisa. E eu vou acelerá-lo muito explícito com isso porque eu não sei se talvez no futuro eu possa ter algumas outras regras de negócios. Então eu vou apenas me contentar com essas duas situações explícitas onde é ou que o isso deve ser else-if desculpas, senão, se else if request dot change, request approval D2 não é igual a null, então faça Isso, certo? E depois as horas extras iam tentar e a rotina de um retorna. Então eu vou pegar tudo isso e dizer que você executa esta operação quando o detalhe de pedidos de licença não é igual a nulo. Então isso significa que quem está consumindo quem está interrompendo com este manipulador enviando sobre seu pedido precisa garantir que o preenchimento. Os campos apropriados de acordo com o que eles querem. Alguns apenas mostrando diferentes sabores porque ele poderia ir o RequestHandler peering para cada situação, cada cenário, mas então você pode tipo de massa juntos, como eu disse, o manipulador. Algumas pessoas colocam muita lógica de negócios nesta seção. Então, mais uma vez, isso é com você. Portanto, se o DTO de aprovação de solicitação de licença de alteração não for igual a nulo, temos uma decisão a tomar. O que exatamente vamos fazer? Sabemos que recuperamos e deixamos pedidos de uma forma ou de outra. Nós não vamos fazer o mapeamento abrangente que realmente queremos fazer é eventualmente chamado de barcos de atualizações com outras coisas acontecendo. Então eu vou chamar espera, deixar solicitações, repositório, alterar status de aprovação. Não. O que fazemos? Eu poderia dar a identificação. Eu poderia dar-lhe o objeto de solicitação de licença, bem como o status para o qual ele deve ser alterado. Há uma série de abordagens que podemos tomar. Não. Sempre falamos em repetir código, certo? Digamos que eu faça isso, vou buscar os pedidos de licença. E então isso seria relativo à alteração, o ID dos detalhes da aprovação da solicitação. E então eu posso dizer dar a esta operação os pedidos de licença que foram recuperados também. O valor do campo de detalhes para a aprovação, seja ela aprovada ou não. Tudo bem. Não, estou a repetir esta chamada para obter um pedido de licença. Não, eu só posso fazer essa chamada em relação a se foi a solicitação que o TOR mudou detalhes de solicitações de licença que veio porque se isso é conhecido, então eu não posso obter esse ID. E se isso é nulo, então depois de tomar uma decisão. Então você vê todas essas outras coisas? Não. Certo, vamos refatorar. Então, para facilitar a nossa vida, vamos voltar para o comando. E então eu fui dizer, bem, não, eu vejo uma boa razão para até que o consumidor inclua a identificação. O ID deve estar presente de qualquer forma, mas inclua o ID aqui. Então, quando você incluir o ID lá, eu posso facilmente dizer ID do ponto de solicitação de fora do bloco if. E então eu sei que tenho os pedidos de licença que precisam ser modificados. Agora, se é que todo o detalhe GameOver, então tudo bem. Sei exatamente o que fazer se for apenas o pedido de alteração. Eu não tenho que ir e encontrá-lo especificamente, mas então eu já tenho e eu posso apenas passar no status de aprovação. Então este método pode ser implementado em nosso eu vou deixar repositório. E eu só vou torná-lo nulo. Então é só essa tarefa. E os parâmetros seriam DV, solicitação e um booleano. Bem, tem que ser booleano anulado de aprovação. Tudo bem, então quando chamamos isso, estamos apenas passando esses dois comandos apropriadamente. Então esta é uma maneira de escrever o código. Eu tenho certeza que você provavelmente está sentado lá e dizendo, ok, nós provavelmente vamos ter feito isso desta maneira ou eu preciso fazer isso desta maneira para a minha situação, tudo bem. Mas desde que entendamos a flexibilidade que temos quando se trata todo esse pipeline de manipulador de solicitações e como podemos lidar com diferentes cenários. Podemos usar o manipulador um para lidar com os diferentes cenários potenciais com base na solicitação, com base nos dados fornecidos na solicitação. E, você sabe, você não precisa ter emparelhamento para cada cenário que você pode ter, mas você pode ter um manipulador para cobrir vários cenários. Tudo bem, então agora que você tem o jeito, eu quero que você vá em frente e implemente o delete commons e manipuladores. Então eu fui em frente e fiz isso. E temos o comando Delete leaf type, que está herdando de solicitações de E/S. Então observe que eu não tenho pedido e tipo de dados da última vez que usamos as unidades. Então este é apenas o 0 que você não precisa necessariamente colocar nesse tipo de dados se ele não for destinado a estar retornando nada. Portanto, este comando delete terá um parâmetro para o ID. E, em seguida, dentro do manipulador, tudo o que estamos fazendo é recuperar o apropriadamente com base no ID, e então estamos enviando para a exclusão e, em seguida, estamos apenas retornando unidade. E neste ponto esse é o tema geral para o shopping. Então é a mesma coisa para o pedido de licença. Saiba se você realmente vai expor a funcionalidade para excluir uma solicitação de licença. Isso é inteiramente até suas regras de negócios, porque pode ser que não há exclusão difícil, é apenas uma exclusão suave ou exclusão realmente significa cancelar, certo? Então, seria apenas sinalizá-lo que foi cancelado, ignorado, mas manter o registro. Então eu estou apenas mostrando a vocês como colocar na funcionalidade. Mas, mais uma vez, as regras de negócios e a sua aplicação são relativas à sua situação. Então isso é para configurar os manipuladores de exclusão e atualização para nossos objetos de domínio. E praticamente essa é a essência de todo o padrão mediador acoplado com o C QR é pulverizado. Então, à medida que avançamos, o que vamos explorar é tornar isto um pouco mais à prova de balas, certo? Saiba que tudo pode acontecer, qualquer um pode vir e criar qualquer coisa, e não há regras reais para governar o que é válido versus o que é inválido. Então vamos tentar e olhar para esse todo nós lidamos com dados inválidos chegando e como podemos torná-lo um pouco universal e infalível. 12. Adição: Muito bem, pessoal, bem-vindos de volta. Nesta atividade estaremos configurando a validação para nossos detalhes e nossos comandos. Agora, antes de seguirmos em frente, há um carrinhos rápidos em nós que eu queria fazer para o código que escrevi no comando update leave requests. Eu tinha inadvertidamente usado o detalhe de pedidos de licença. Então, se ele está na atualização, então você deve ser adotado folha Pedido detalhe. Então, se você pegou esse erro e o carrinho fez a si mesmo, então parabéns para você. Se não, então você pode ir em frente e se encontrar. Isto muda-me. Sem problema. Agora, o que estamos falando quando nós, sobre o tema da validação é a capacidade de garantir que os dados que estamos recebendo antes que eles vão para o banco de dados são bem válidos porque como ele está, não há nada aqui para nos impedir de comprometendo, invalidar um banco de dados de brinquedos. E uma coisa que é muito, muito, muito importante é a integridade dos dados. Então você não quer criar dois registros com dados vitais ausentes alocação de licença. Não sabemos que tipo de licença. Ele ainda é plano nisso, então você vai querer validá-lo e, em seguida, rejeitado, é claro, se ele não atender aos padrões. Agora, quando você está se acostumado com MVC e você acha que a validação TBL e você está vendo que nos modelos podemos facilmente colocar nossas anotações de dados, o que é muito verdade. Achei que isso seria útil. Mas então quando você quer estender além dos padrão, você tem que começar a construir extensões antigas e sal, que é, o que também é muito bom. Mas nesse programa em particular, vamos usar validações fluidas, que é uma biblioteca que nos permite usar a sintaxe fluente e regras muito, muito poderosas e estruturas de validação são propriedade de nossas propriedades em nosso classes. Tudo bem, então para começar, vamos pular para o novo Git e eu suponho que muito procurado por fluente. E você vê todos esses maravilhosos resultados de busca aparecendo. Nenhum ponto de informação. A documentação para esta biblioteca é muito boa e você pode encontrá-lo no site para invalidação dotnet, e você verá como podemos estender isso e massageá-lo e usá-lo para sua capacidade total para ajudar com suas necessidades de validação. Então eu vou em frente e instalar esta biblioteca para as extensões de injeção de dependência. E uma vez que isso é feito, podemos fechar NuGet e, em seguida, passar para a nossa configuração. Mas uma coisa a notar, acho que nunca mencionei isso antes. Quando você clica nesses arquivos CSB, você realmente vê quais pacotes estão instalados em sua versão. Então, alternativamente, se você souber o nome exato do pacote e a versão que deseja, você pode realmente colar alinhado assim dentro de sua compilação de blob de arquivo CSV e ele receberá automaticamente esse pacote do NuGet para você. Então essa é uma maneira que você também pode instalar, resolver esses pacotes no futuro. Então vamos começar com nossos validadores. Sabe que eu me pergunto onde colocar esses validadores, eu só vou derrubar tudo. Então podemos ver todas as nossas pastas meio compactadas, certo? E então, claro, temos os detalhes. Os detalhes são onde nossas validações precisam acontecer porque eles são os únicos presos vendo a inflamação em nosso nome. Não precisamos validar os que estão sendo usados para as consultas. Isso é meio inútil, certo? Porque as operações de leitura não precisam de validações. As operações certas ou as operações de aumento, no entanto, fazer. Então eu vou, em uma das pastas, deixe-me começar com a mais fácil. Vou adicionar e nova pasta. E eu vou chamar isso de validadores. E então dentro disso, vou adicionar uma nova classe. E, em seguida, este vai ser criar folha tipo D2 validador. Claro, para torná-lo público. E então eu vou deixá-lo herdar de um validador abstrato. E então eu vou passar em nome da classe exata a que ela é relativa. Então vou em frente e incluir as referências que faltam. E então acrescenta que usando a biblioteca de validações fluentes e, em seguida, estamos prontos para ir. Então o que temos é um construtor. Então CTR banheira, banheira e nós pegamos aquele construtor e então podemos começar a definir regras. Então deixe-me dar uma olhada rápida no tipo de folha de criação D2. O que quereríamos validar nisto? Bem, gostaria de ter certeza de que os valores de nome fornecido direito. Provavelmente também podemos limitar o número de caracteres que esta propriedade de nome pode ter. Sabe, a maioria deles não sabia, e deve ter um comprimento máximo. E provavelmente iria querer mensagens personalizadas para a situação para o número padrão de dias, provavelmente podemos ver que ele é hostil, ser mais, mais de um, deve ser maior que 0, pelo menos para o número padrão de dias. Então, há uma série de coisas que poderíamos validar. Então o que veremos é a regra quatro. E então você vai notar que isso parece apenas deixar as mesmas expressões lambda que estamos acostumados. E se você não está acostumado com eles, tudo bem. Vamos nos acostumar com eles, eventualmente. Então é regra para e então podemos ver o nome. E a coisa legal sobre a validação do Flint é que você pode encadear as coisas junto. Então você pode acorrentá-lo e dizer, Ok, esta regra e aquela regra e aquela regra e aquela regra. Então, a regra para o nome do ponto P. É, digamos, não vazio. Então isso significa que deve ter um valor. E então eu posso dizer com mensagem, então se ele vem mais m2, então nós queremos que esta mensagem seja impressa. Então eu posso fazer algo como este nome de propriedade para que não queiramos conversar. O nome do tipo deve ser o seu nome é obrigatório, certo? Porque então eu estou fazendo dinâmica. Se mudarmos o nome na própria classe, então podemos esquecer de atualizar a mensagem de acordo. Então, apenas fazendo isso, ele irá automaticamente herdar qualquer nome ou qualquer que seja o nome que está fora da propriedade, que é realmente também. Certo. Então, diremos que o nome da propriedade é obrigatório. Essa é a nossa mensagem de validação. Outra validação que poderíamos colocar não é nula. Então estamos informando que isso não deve ser nulo. E eu coloquei meu ponto e vírgula prematuramente, tão terrível que por isso também não deve ser nulo. Vamos ver o que podemos ter. Podemos também dizer que o comprimento máximo da propriedade nome é talvez 50. Não deve haver tipo de licença com um nome que exceda 50, certo? E então podemos adicionar outro com mensagem para que com a mensagem. Tudo bem, então eu só estou te dando idéias. Quero dizer, você pode ter requisitos diferentes para sua validação do que eu tenho, mas essas são diretrizes gerais que eles podem seguir. Então vamos olhar para o, o ponto p padrão é. Portanto, para padrão é que você notaria que, como o tipo de dados é diferente, algumas das validações podem não se aplicar necessariamente. Então eu não posso falar sobre o comprimento máximo com o padrão é que não tem nada a ver com um inteiro, certo? Você vê que as flechas se foram, então eu estou vendo que deve estar presente, mas então é inteiro, então ele sempre, praticamente sempre estará presente, mas podemos deixar isso em paz. Mas não deveria estar vazio. Então nunca poderá ser nulo. Realmente intuitivo porque inteiros são padrões 0 e valores nulos fornecidos. Mas depois vimos que isso deve ser sempre maior que 0. E então eu tenho certeza de que há um menos que. Então vamos dizer que queremos ver no sistema não deve haver nenhum tipo de folha que é Putin que tem qualquer número destes Greta do que um 100 ou até um 100. E deve ser pelo menos um. Assim, os diferentes tipos de dados podem obter regras diferentes e podemos encadeá-las sozinhos, conforme necessário. Podemos colocar nossas mensagens de acordo para que eu possa colocar minha mensagem aqui com mensagem aqui. Então, com essas validações no lugar no tipo de folha DTO, vamos ver como podemos fazer com que essas validações sejam nossas próprias. Então, no comando que cria o tipo de folha, certo, nós temos essa folha, que BTO do nosso objeto de comando, certo? O que eu vou fazer antes mesmo de fazer o mapeamento embora, porque eu não quero desperdiçar recursos em uma operação com dados inválidos. Então eu vou fazer a validação primeiro. Então eu vou dizer var validator é igual a New Leaf type DTO validator. Então, enquanto ainda é um detalhe antes de eu tentar mapeá-lo até mesmo para o tipo de domínio, eu vou invocar esse validador que eu vou dizer var resultado de validação é igual a. E eu vou esperar meu validador fazer a ligação para validar. E nós temos a opção assíncrona, portanto, usando o aguarde. E, em seguida, passamos o objeto a ser validado, que será uma solicitação pontos deixar tipo DTO. Neste ponto, o resultado da validação vai ter setas não são. Então eu vou ver se o ponto de resultados de validação é válido, então nós obtemos que ou é válido ou não com base nas regras. Vai ser válido ou não. Se for. Digamos se não é válido. E então para legibilidade, eu queria dizer se é válido é igual a falso, certo? Porque às vezes com toda a justiça, quando usamos apenas sinal de exclamação, às vezes quando você está cansado, emitem até mesmo perdê-lo quando você está revisando o código e assim por diante. Então eu só vou ser um muito explícito se é válido é equivalente a falso, então eu vou simplesmente lançar uma nova exceção. Então, se você está acostumado a manipulação de exceção, exceção é lançada, é isso, basicamente trava. O programa vai saber mais tarde vamos olhar para uma melhor manipulação de exceções e tudo isso pode realmente nos ajudar a escrever um código pouco mais limpo. Em vez de ajudar um monte de declarações se para verificar um monte de coisas, nós só temos exceções. Esse é o nosso ser através e estrategicamente para ajudar o fluxo do aplicativo. Então, nesta situação, se não for válido, então vamos lançar uma exceção. Vamos olhar para como podemos fazer exceções personalizadas também, que podem ser tratadas diferentes das exceções fetais reais. Então é basicamente isso. Estamos adicionando validação aqui para garantir que ele não vá mais longe. Não chega perto do banco de dados. Não queremos que ele se torne um objeto de domínio se ele não for válido. Agora vamos tentar provavelmente o mais complicado. Então eu vou desafiá-los a acertar validadores para a alocação de licenças, que realmente não é tão diferente. Você só precisa ter certeza de que o número de dias está presente em É mais do que 0. O ID do tipo de folha não pode ser nulo, ele tem que ser maior que 0 também. E então você pode ser estendido para se certificar de que o ID do tipo de folha existe no sistema. Porque se alguém tentar falsificar e Central Valley tipo ID que não existe em nossa tabela, então isso também é uma seta de validação que podemos realmente pegar antes de tentar confirmar o banco de dados. Vindo para o banco de dados, podemos fazer isso durante o período. Então eu vou desafiá-los a fazer isso, mas nós vamos trabalhar nos pedidos de licença juntos porque este vai ter mais algumas coisas nele. Então, mais uma vez, vou adicionar um novo validadores de pasta e, em seguida, vamos começar com as solicitações de licença Cria, validação DTO. O que precisamos para validar? Bem, nossos encontros precisam ser datas válidas. Ainda precisamos obter o ID do tipo de folha, então vamos fazer isso juntos. E isso é opcional, então tudo bem. Então vamos entrar nessa. Então ele começa com a nossa classe cria licença solicitações detalhe validador. Eu torná-lo público. E então eu estou herdando do validador abstrato relativo ao nosso detalhe Criar solicitações de licença. Tudo bem, então eu já escrevi algumas das citações para você e nós vamos passar por isso. Não está concluída porque quero que façamos certas partes juntos, mas regra para começar precisa ser menor que o fim. É agora que vimos que também poderíamos usar o valor escalar aqui. Então eu poderia ter colocado um inteiro, mas então um inteiro seria uma comparação incompatível com o tempo. Então eu poderia ter colocado a hora da data, não. Certo. Apenas certifique-se de que a data de início não é antes de hoje são principalmente antes de hoje, que não é necessariamente o caso, certo? Portanto, com base na regra de negócios, você pode querer comparar adequadamente, mas essa regra de negócios afirma que as datas iniciais devem sempre ser menores que a data final. E então será a mensagem que eu posso dizer nome da propriedade deve ser Antes do valor de comparação. Então, em nossa criação de detalhes tipo folha, nós tínhamos codificado o 50, nós codificado duro o, o um e o 0 aqui, mas nós poderíamos facilmente substituí-los e ele falou no pároco corretamente. Poderíamos facilmente substituir essas áreas por comparação. Vou deixar o codificado para nulo, mas só estou mostrando suas opções, certo? Então eu estou vendo que a data de início deve ser antes NDI ele semelhança para a Índia ele, ele deve ser maior do que o início limpo e nome da propriedade e valor de comparação. Tudo bem? Não, em relação ao ID do tipo de folha, eu disse que nossa validação poderia assumir várias formas. Primeiro, você quer ter certeza que é maior que 0, ok, tudo bem. E o mais importante, porém, seria que você quer ter certeza de que existe. Agora, se nós apenas verificar se ele existe, mesmo se eles enviaram mais de 0, 0 nunca existiria como um ID de tipo folha no banco de dados. Então nós poderíamos acorrentá-lo porque então nós poderíamos desperdiçar o banco de dados chamado apenas fazendo isso. Então eu poderia dizer maior que. E então eu vou ver 0. E então também vou ver que deve existir. Então eu estou usando o que você chama de delegado aqui, e eu vou apenas apagar tudo isso e redigitá-lo do zero para você possa ver exatamente o que eles vão dizer a maioria dos parênteses assíncronos, abertos e fechados, é uma visão, Então vamos esperar, mas então vamos definir um delegado. Desculpe, não estamos usando, estamos informando que é um delegado assíncrono que leva alguns parâmetros. Neste caso, precisamos do ID, que é o valor. Então, estamos tomando esse valor como um parâmetro número 1. E então Tolkien é um token de cancelamento como ferramenta de parâmetro. E, em seguida, eu estou usando uma seta Lambda para, em seguida, definir algum bloco de objeto ou bloco de método. Então este bloco método é onde vamos realizar essa verificação para ver se ele existe. Agora você provavelmente está se perguntando, ok, isso significa que precisamos de um banco de dados chamado como exatamente eu chamo o banco de dados de apenas um validador? A coisa legal sobre isso é que ele nos permite injetar diretamente ou dependências. Tudo bem, então podemos continuar injetando nosso repositório para que saibamos como injetar ele irá colocá-lo no construtor. Podemos usar o ponto de controle para inicializar o campo. Eu já mudei para os meus sublinhados, o que é opcional, claro. Mas usando isso podemos inserir desta função delegado mais acing verificar para a existência do repositório folha I. Então, duas coisas a observar aqui são três coisas. Primeiro, estamos injetando o validador nos permite injetar outras dependências, como nossos repositórios. Isso é uma ferramenta. Podemos realmente ter uma função personalizada fazendo validação personalizada para alguém digitar este IN para ele a partir do zero. Então aqui vemos um ponto. A maioria eu teria musselina assíncrona. Isso é bom. Tão assíncrono. E então porque estamos usando assíncrono, temos que deixar o modelo delegado, ele está apagando. Então o delegado é quando tomar dois parâmetros. Id que representa a própria ID que estamos validando ou o valor que estamos validando. E tolkien seria representativo do token de cancelamento que usamos são lambda R0 e, em seguida, abrir e fechar chaves. Então, dentro dessas chaves nós temos nossa lógica. Assim, a primeira linha da nossa lógica é verificar ou repositório se o tipo de folha existe e, em seguida, retornar que não existe. Tudo bem, não, esta função que eu acabei de criar, então eu acabei de estender nosso repositório genérico para ter um método que retorna um booleano. Ele é chamado existe e ele leva int id. Então, isso, você pode adicionar isso ao repositório genérico e você pode usá-lo em cada um deles. Mas o ponto é que podemos saber, usar isso para verificar se alguma coisa existe em uma tabela específica. E nesta situação, é um bom sapato para verificar se ou elif tipo ID existe. Então saiba que você está equipado com espera para lidar com esse tipo de folha ID. Eu vou desafiá-lo a ir e configurar validadores para a alocação de licenças. Aperte a pausa, tire uns instantes, configure os validadores da alocação de licenças Ford e qualquer outro detalhe que ainda não tenhamos analisado. E então quando você voltar um pouco mais, apenas mostrar-lhe outra maneira de refatorar nosso código para meio que reduzir a repetição. Tudo bem, então eu espero que você realmente tenha seguido o conselho que você foi embora, você tentou fazer a si mesmo e que você teve algum sucesso. Isso é bom. Mas depois quero mostrar-vos apenas mais um nível que podemos fazer isto. Então, quando estávamos configurando os detalhes, percebemos que acabaria repetindo nossas propriedades em vários detalhes. Por exemplo, o tipo de folha de criação D2 e o detalhe de tipo de folha, eles realmente têm as mesmas propriedades barra a fonte. Ninguém se baseia na identificação que servimos através dos detalhes básicos. Assim, as regras de validação para ambos serão realmente as mesmas exceto talvez a que diz o ID1 para o hub de validação para ele. Então, porque um tem um ID, um não tem, e o validador até agora tem sido fortemente digitado porque quando temos o detalhe do tipo de folha de criação, apenas quatro para criar detalhes e atualizações do tipo de folha, D2 teria para ter seu próprio validador. Então o que eu fiz foi estender um pouco. E isso é o que eles chamam de desenvolvimento impulsionado por pinos. Significa fazer o que puder até que não seja mais prático, então você refatora, certo? Então, quando você está aplicando esses princípios sólidos, às vezes você não vê isso imediatamente. Mas então, em certo ponto, você percebe que isso está ficando tedioso ou isso não é prático, isso não está de acordo com o princípio. E então você refatora seu código para tirar o máximo proveito do principal nesse ponto. Então, neste ponto, estamos analisando que estamos tendo as mesmas regras de validação divididas em vários arquivos, o que é bom. Ou pelo menos ter vários arquivos para validações é bom. Mas ter as mesmas regras repetidas pode ser perigoso porque então se a regra precisa ser mudada em uma, podemos mudá-la em uma, estou perdendo a outra. Conhecemos esse risco. Então o que eu fiz foi ter uma interface que é uma obstrução de nossos campos. Tudo bem, então como deixar o tipo de detalhe que eu criei, eu deixo esse detalhe e isso tem os campos que sabemos que a folha tab2 precisa ter. Então, no tipo de folha DTO, Eu tenho relacionado herdar. Deixo esse detalhe. Então esses dois campos são apenas as implementações do que foi definido na interface. Da mesma forma no elevador IB2, enquanto ele herda do detalhe base, ele também herda do detalhe do tipo elif. Então deixe que o BTO teria o ID, bem como as propriedades que vêm de nossa interface. Agora. Ok, então, o próximo passo é que podemos criar um validador de detalhes de tipo I leave, que significa que eu estou validando contra a interface. Então minhas regras não são mais aplicadas diretamente ao tipo de folha DTO. Podem ser, tudo bem. Mas então, como vimos, temos que ter múltiplos porque teríamos que ter um tab2 folha cheia no 14, o Criar. Em vez disso, posso configurar validações contra a obstrução. Ambos os detalhes herdam da obstrução. Portanto, estas regras aplicar-se-ão a ambos. E então quando eu tenho que ser personalizado, eu tenho minha folha, aquele validador de detalhes em que eu digo criar folha. De detalhe validador e tudo o que já sabemos. Mas, em seguida, no construtor eu estou simplesmente chamando um método de inclusão. Então esta é fluente API é que estamos nos seguindo para ter validadores que se aplicam a outras coisas, aplicar a outra classe. Então isso realmente se aplica à interface, o que eu estou vendo quando estou fazendo isso criar um validador de detalhes de tipo de folha, incluir as regras do validador de detalhes do tipo I deixar. E então eu posso ter meus métodos de fantasia também. Então, no detalhe da atualização, eu poderia ter o mesmo tipo de sintaxe, mas então, são as atualizações, o que significa que eu também preciso da nossa regra para. E então eu posso dizer que eu preciso de uma regra para os campos de ID. Posso dizer p dot. E então veja que ele está me dando todas as propriedades, incluindo ID porque é contra esse tipo. Então minha validação para o ID é que ele não deve ser nulo e deve vir com um nome de propriedade de mensagem deve estar presente porque, claro, quando você está atualizando, você precisa enviar o ID do registro que você está atualizando, que é por isso que precisamos dessa regra de validação para a atualização e é por isso que eu teria que ter o arquivo separado para a atualização. Mas isso é muito mais limpo porque pelo menos não temos que repetir as regras para o nome e o tipo ou o nome. E o padrão é, desculpe, não precisamos repetir isso em ambos os dados. Então você vai ver que realmente fez isso já para a solicitação de licença e para a alocação de folhas, mais uma vez, para a solicitação de licença, eu tenho que deixar solicitações DTO, e é o mesmo código que acabamos de olhar quando as solicitações de licença detalhes dados válidos com injeção. E neste caso temos que inicializá-lo e então fazemos as regras. Mas quando olhamos no validador de detalhes da solicitação de licença Cria, vemos que temos que fazer a injeção. Então ainda temos que fazer a injeção e temos que inicializá-la. E então passamos sobre essa injeção para o método de inclusão porque, é claro, o validador de detalhes da solicitação de E/S precisa ter essa injeção. Então Kant chama de nós temos que fornecer esse valor para o construtor. Então é só aquela cadeia de margarida, mas eu acho que isso é muito mais limpo de qualquer maneira. E não temos que acabar repetindo todas essas regras em toda a linha. Assim, você notará que a criação e a atualização são muito semelhantes, exceto o fato de que a atualização tem essa regra adicional para o ID. E só para finalizar, temos os detalhes da alocação de olhos. Eu tenho o ID tills, as interfaces não mostraram isso. Então, qualquer coisa que é comum em todos, eu apenas coloquei isso na interface e então qualquer outra coisa pode ser colocado diretamente nos detalhes conforme necessário e validado de acordo. Mas então, para criar uma atualização, essas são todas as coisas que realmente precisamos. Nós não temos que necessariamente fim de semana senso de regra de validação tipo de solicitação comentários talvez limitar o comprimento. Não precisamos necessariamente fazer nada por cancelado. Mais uma vez, só estou te dando as diretrizes. Suas regras de negócios e requisitos podem ser diferentes, mas você configura suas validações conforme necessário. Então, nossa atualização licença pedidos detalhes herda da base, e eu deixo detalhes pedidos. Não precisamos fazer isso para a lista porque não estamos validando a lista. Também não estamos validando os detalhes, mas isso cria definitivamente tem que herdar. E então a aprovação da solicitação de alteração que tira desse detalhe, mas não estamos em algum momento podemos validar isso. Não estou priorizando isso. Mas, em seguida, sobre atualizar e criar, nós definitivamente precisa ter já, tudo bem, não, Para a nossa criação de um local, então eu deixar alocação e, em seguida, ambos cria uma atualização herdar de I deixar alocação. Então eu vou pular para o validador de alocação I deixar onde temos regras para o número desses. Portanto, este é simples e à medida que o aplicativo cresce, as regras de negócios mudam. Podemos facilmente colocar nossa validação aqui sem modificar as consultas personalizadas e quaisquer outras operações de clientes em torno das referidas regras de negócios. Então regra para um número de dias agora eu só tenho que ser maior do que 0. E minhas mensagens de validação foram vítimas de copiar e colar. Então eu só estou vendo o nome da propriedade deve ser maior do que o valor de comparação para a regra maior do que para o período. Então o período realmente deve ser o ano, certo? Então, para o período do ano 2020, este era o número desses que você obteve. São os pontos de pólo da tabela de alocação de folhas no caso de não ter sido explicado anteriormente. Portanto, a regra para um período é que ele deve ser maior ou igual ao tempo ponto 10 ponto ano. E podemos reforçar isso um pouco mais por enquanto, vamos usar isso. Então vamos ver o nome da propriedade da mensagem deve ser depois deste ano. E então todos nós vimos e escrevemos juntos a regra de validação para o ID do tipo de folha e não para os dados válidos Criar alocação de licença onde simplesmente injetar o repositório de folhas e inicializá-lo e passando-o em nosso método de inclusão. E para as atualizações estavam fazendo o mesmo, exceto que também temos essa regra para o ID. Então isso é realmente para validação. Sim, demorou um pouco para chegar lá. Havia alguns refletores ao longo do caminho, mas eu tenho certeza que você pode ver como tudo está se juntando para tipo de reduzir uma repetição em vários arquivos e tipo de ajuda também, manter tudo estruturado. Então, uma consequência do seguinte, os princípios sólidos, é claro, é que você vai acabar com muitos mais arquivos que discutimos anteriormente. Mas está se unindo bem e nos ajudando a reduzir quantas vezes colocamos a mesma coisa em vários lugares. 13. Adição de exceções personalizadas e objetos de resposta: Ei pessoal, bem-vindos de volta. Da última vez que estivemos aqui, estávamos sentando nossas validações para manipuladores e para nossos vários detalhes. E em poucas palavras, percebemos que precisávamos colocar algumas regras para que sempre que obtivermos o comando create leaf type com o create leaf type D2 ou qualquer detalhe. Podemos executá-lo contra o validador e, em seguida, nós retornaria uma exceção se ele não é válido. Então nós deveríamos ter feito isso em todos os manipuladores para atualização e criar qualquer coisa que precise de uma validação deve ter o mínimo essas linhas. Então eu vou apenas clicar e você pode apenas ir em frente e copiar caso você não tenha terminado isso. Então isso é para a atualização. Nós apenas olhamos para a criação para a atualização tipo folha totalmente pedidos praticamente todos eles se parecem com a mesma coisa. Tudo bem, eles estão validando e inserindo uma exceção. Agora, eu quero falar sobre exceções personalizadas e respostas MRD, certo? Porque no final do dia agora, tudo o que estamos fazendo é abrir uma exceção. Uma exceção pode ser lançada com base em nosso lançá-lo manualmente. Ele multi também pode ser jogado por causa de outra coisa. Ele pode ser um problema de redirecionamento de banco de dados, pode ser outra coisa, certo? Portanto, é sempre bom que o aplicativo de consumo ou o que está chamando o manipulador tem uma boa idéia sobre o que através desta exceção. Então, a coisa legal sobre exceções é que você pode estendê-las. Então, o tipo de dados base para uma exceção é a exceção que vamos lançar aqui o que vamos criar o nosso próprio para os fins específicos. Então vamos começar criando uma nova pasta em nosso projeto. Vamos chamar de exceções. E nele vamos ter exceções de solicitação incorreta, não encontrada e exceção de validação. Então você pode ir em frente e criar essa pasta. E esses três arquivos, lembre-se de mim eles públicos, é claro. E o que vamos fazer é deixar cada um deles herdar de exceções de aplicativos. Então exceção é o tipo base de uma exceção de aplicativo é usado como um tipo de base para aplicação definido exceções arte. Então nós vamos apenas ir em frente e deixar cada uma de nossas classes herdar daquela manteiga solicitada exceção será mais tarde quando quisermos definir que os pedidos que foram centrais versus ruins, tudo bem, mas por enquanto vamos inicializá-lo ou ler o código para conectá-lo. Então todos eles terão um construtor. E para este, o construtor vai tomar mensagem string e, em seguida, nossa base tem que herdar a mesma mensagem que é passada a base sendo a nossa extensão obrigação. Então é assim que essa exceção se parece. Exceção de aplicativo. Desculpe por isso. Não, seguindo em frente. Podemos fazer o mesmo com nosso telefone NAACP, mas então podemos ser um pouco mais explícitos com certas coisas. Por exemplo, se vamos estar vendo não encontrado, provavelmente vamos querer ver o nome do que estava sendo procurado e talvez o valor chave. Certo, então estamos passando Nome no teclado, então a base requer string, então tem três sobrecargas. Quero passar uma corda aqui. Então podemos passar nossa mensagem que sabemos que queremos imprimir. E minha mensagem vai dizer que o nome, o que quer que seja e sua chave não foi encontrado. Tudo bem, então se a busca por algo, não é formada através de exceção não encontrada, para a exceção de validação. Vamos ficar um pouco mais chiques. Então a exceção de validação vai querer R, vamos querer que ele devolva a lista de todas as coisas que estavam erradas com o pedido ou os dados que enviarão em sua busca, certo? Então eu vou ter uma lista de cordas e eu vou chamá-lo de erros, certo? E, em seguida, no construtor, vamos ter os resultados de validação, os dados sendo passados dentro. Portanto, os resultados de validação do resultado da validação vem da validação fluente. Então vamos apenas passar esse objeto inteiro lá dentro ele está usando resultados de validação fluentes. Tudo bem, e então podemos ver que podemos inicializar ou erros. Quero dizer, inicialize isso aqui. E, em seguida, podemos ver para cada erro de validação nos erros. Ou eu posso apenas encurtá-lo e dizer para cada erro em erros de ponto de resultado de validação, queremos adicionar esse erro. Então eu só vou dizer urls.py. E então nós apenas ponto de erro e nós temos uma mensagem de erro. Lá vamos nós. Então essa mensagem de erro seria o que tínhamos configurado em nossos validadores como a mensagem a ser retornada quando não é válido. Então agora temos nossas exceções personalizadas. Nós realmente vamos nos concentrar na exceção de validação, certo nodal. E assim, em nossos manipuladores, podemos realmente atualizar isso de lançar nova exceção para lançar nova exceção de validação. Então, se o resultado da validação não é válido, lançamos esta nova exceção e passamos em nossos resultados de validação e você deseja incluir quaisquer referências ausentes. Então você vê aqui ele está pedindo por esses livros. Sabemos que o definimos. Em nossas exceções personalizadas. Tudo bem, então você pode ir em frente e atualizar cada linha que estava apenas lançando uma nova exceção para saber lançar essa exceção de validação. E lembre-se de cada vez que estamos incluindo nossa exceção personalizada e não a validação fluida ou a validação de dados na arte. Então vá em frente e atualize-os todos e certifique-se de que você está incluindo a biblioteca de carrinho. Neste momento, imagino que esteja se perguntando, como posso usar as outras exceções? Bem, vamos olhar para a exceção não encontrada. Então, em C, a operação de exclusão, temos que encontrar o registro, depois fazer o deletar e retornar bem, as unidades, certo, mas e se não encontrarmos esse registro? Bem, então essa é uma oportunidade perfeita onde dizemos se o objeto que estamos procurando retorna nulo, ou se a operação retorna nulo, então lançamos a exceção não encontrada. E o que passaríamos para a exceção não encontrada? Lembre-se que é preciso dois parâmetros. Leva o nome e a chave, para que pudéssemos facilmente dizer o nome. E então esta é uma boa maneira de mantê-lo fortemente digitado. Então estamos procurando um tipo de folha. Então nome fora tipos de folha ou dizer no tipo de folha com o id que foi passado em não era telefone ou outras solicitações. Dot ID, certo. Lá vamos nós. Tudo bem, então você pode começar a decorar seus manipuladores Delete com essa linha. Então, no caso das solicitações de licença, que será a mesma coisa, exceto que estamos verificando se a solicitação de licença é nula, e então isso seria um pedido de licença não telefonado. Vá em frente e atualize. Então você pode fazer isso com alocação de licença também. Tudo bem, então uma vez que você está pronto com isso, então você tem um bom tratamento de exceção pelo menos ou manipulação de exceção personalizado em seu handless. Outra coisa que queríamos ver são as respostas dos clientes. Então, o que acontece quando há um resultado positivo? E mesmo quando há resultados negativos, certo? Então é aqui que suas necessidades arquitetônicas podem diferir das minhas em termos do que você quer fazer. Mas aqui está um conceito. Podemos definir tipos de resposta personalizados ou ter respostas base onde podemos retornar dados com base na situação. Então, se falhar, podemos lançar a exceção com certeza. Ou podemos ter uma resposta do cliente que tem um sinalizador falso de sucesso, ele contém os erros de validação. E assim o cliente sempre saberá que eu estou esperando uma resposta desse tipo de dados que devemos sempre ter esses dados. Se a bandeira é falsa, que eu sei campo de TI, se é verdade que eu sei que ele passa. Então, vamos olhar para algo assim. Então uma espécie de alternativa para apenas lançar uma exceção ou retornar apenas o ID, o que poderíamos fazer é definir uma nova pasta. Então temos uma nova pasta aqui chamada respostas e inits temos uma resposta de comando baseada em arquivo. E terá três propriedades. Sucesso, que é uma mensagem booleana, que é uma string, e uma lista de erros, se precisarmos enviar de volta os erros, certo, então depois de termos essa resposta de comando base, podemos estender para facilitar o operações específicas. Então, por exemplo, um resultado provavelmente vai querer estender isso é que queremos retornar certeza a cada vez que um tipo de folha é criado ou atualizado, certo? Então a resposta da base pode não ser suficiente. Assim, podemos criar uma resposta personalizada associada a tipos de folhas. Então, já temos essas solicitações da web. Então você poderia criar outra pasta chamada respostas, e então poderíamos estender isso. Não vou ficar tão complicado. No entanto, o que eu vou fazer é apenas adicionar outra propriedade aqui e eu vou chamá-lo de ID, certo? Ou podemos chamá-lo de ID de registro. Então isso significa que sempre que algo acontece, nós criamos, em vez de apenas retornar o id, o que eu poderia fazer é, e isso é uma grande mudança. Então vamos passar linha por linha e eu vou abordar as linhas vermelhas quando chegarmos lá. Então inicialmente estávamos apenas dizendo para me dar os resultados de validação, lançar uma exceção, caso contrário continuar e então retornar a alavanca. Deixar. Nesse caso, deixe o ID da solicitação. Tudo bem? Sei que o que estou fazendo é que estou vendo primeiro, inicializar a resposta, então temos uma resposta básica, tudo bem. Então eu estou vendo se o resultado da validação é falso, definir esses geradores pensamento sucesso para quedas. A mensagem que você pode colocar em uma mensagem personalizada, se desejar. E então os erros que gostaríamos de preencher com os mesmos erros de validação. Então eu estou apenas selecionando-os da lista de erros são desta coleção de erros. Então esta seleção tem uma linha vermelha porque eu preciso de uma biblioteca extra, que é links System.out. Então, certifique-se de que podemos ver isso juntos. E então ele só recebe as mensagens de erro, coloca-as em uma lista, e então isso entra. Então isso é um bom forro em si o para cada loop certo? Então mais tarde conhecido, vemos se o anúncio foi bem sucedido e alma, o que acontece é que se isso se sente não excepcional teria sido através de um automaticamente por Entity Framework de qualquer maneira. Então, se isso não acontecer, então teremos uma exceção. Assim, nunca chegaria tão longe se isso não fosse bem sucedido. Então, o sucesso é verdadeiro. Nossa resposta é a criação bem-sucedida e, em seguida, definimos o ID. Então é isso que eu vou ver você em toda a linha, nós estamos apenas devolvendo identificações, certo? Só estávamos retornando o ID do registro recém-criado. Você pode ter um requisito onde você precisa retornar o registro inteiro. Nesse ponto, você poderia apenas estender resposta de comando base cria uma nova classe chamada cria resposta de solicitação de licença. E que ele não machucou a partir deste e dar-lhe o parâmetro DTO para uma solicitação de licença DTO, você faz o seu mapeamento, você retorná-lo. Como eu disse, não vou ficar tão complicado, certo? Não, não podemos olhar para isso em nossas considerações futuras ou lições de considerações adicionais, mas eu só queria obter esse conceito de resposta do cliente. Então retornamos a resposta. Agora isso tem nossa linha vermelha porque tínhamos definido nosso comando para retornar int. Tudo bem, então podemos ir para o nosso comando. Avise que peço que devolva a resposta do comando da besta. Tudo bem, e então nosso erro aparecerá e nós pulamos fanfarrão e foram bucking ou manipulador, vemos que podemos retornar resposta assim que também atualizamos o manipulador, certo? Então lembre-se que temos esse comando e tipo de retorno peer-to-peer. Então deixe-me atualizar isso. E, finalmente, o tipo na tarefa para a alça. Tudo bem, então, quando você quiser mudar, alterar suas divs de retorno, isso é tudo que você tem para fazer todas essas mudanças mais uma vez, certo? Sem resposta de comando bs. Então, se você quiser obter granular, eu continuo dizendo que você não tem que obter livro tão granular com base em suas necessidades, você precisará ser você pode não precisar. Eu não estou fazendo disso um requisito para ouro e criar respostas de comando para cada controlador solitário ou manipulador de comando que eu tenho. Neste momento, vou usar a resposta da base. E eu também vou fazer essa alteração no pedido de licença por enquanto, pelo menos, para que você possa ver a idéia de como você pode ter exceções personalizadas e, ou como você pode melhorar essa parte superior de suas respostas personalizadas. 14. Refatoração e considerações adicionais: Ei pessoal, bem-vindos de volta. Esta é mais uma sessão de revisão do que uma sessão de codificação e apenas algumas considerações adicionais. Então, gargantas ou atividades podem ter mencionado que você tem alternativas e você sempre tem alternativas. Se essas alternativas são boas ou ruins ou aspas, as melhores práticas às vezes são relativas ao que você está fazendo e ao que você precisa realizar. Dito isto, é claro, existem princípios fundamentais que você quer aderir independentemente e aqueles que terão esses princípios como seu guia, então você é mais do que provável que você vai tomar decisões melhores. Então, uma coisa que queremos ver é a separação de preocupações, certo? Então separação de preocupações nos levou a ter vários projetos e muito mais arquivos do que provavelmente tivemos em outros projetos como eu sou fato conjunto, eu acho que já temos mais arquivos neste projeto do que fizemos em todo o aplicativo que ambos vamos reconstruir, certo? Então, apenas neste projeto sozinho, tivemos várias DTLs. Por que temos vários detalhes? Bem, nós queríamos esse tipo de separação porque pode haver regras de negócios que regem o que pode ocorrer em qualquer tipo de operação. Então vamos olhar para mim deixar pedidos detalhes. Deixar os detalhes dos pedidos. Tínhamos um para a lista que tinha apenas os dados que eram absolutamente necessários para quando precisávamos de apresentar a lista de pedidos de licença. Temos um DTO que tem todos os campos que correspondem ao que está na tabela. E isso pode ser visto como o DTO detalhado. Também tivemos a atualização, que tinha apenas alguns campos necessários para uma operação de atualização. Tivemos o Cria onde tivemos poucos campos para uma operação de criação, et cetera. Então nós os dividimos em vários arquivos. Portanto, esta é uma das consequências que eu gostaria de dizer de aderir a esses princípios de separação de preocupações. Mas você vai acabar com muito mais difusa do que você provavelmente está acostumado. E você vai ter que separá-los de uma forma que você sempre pode encontrá-los. Então eu comecei com detalhes e então em detalhes, eu os separei pelo tipo. E depois disso, em seguida, você começa a ver os arquivos também irá configurar os validadores. E, em seguida, devido às diferentes regras de validação que podem ser necessárias para os diferentes DTUs, temos vários validados, um solo para Criar, temos 14 atualização. Mas, ao mesmo tempo, vimos onde precisávamos nos consolidar porque era meio arrogante e começamos a nos repetir. Então você tem o princípio DRY. Por causa do princípio DRY, o que fizemos foi criar uma interface que tinha os campos base. Por isso, permitam-me que veja, talvez, a atribuição de licenças seja um melhor exemplo disso. Então nós temos, eu vou deixar alocação, que tem todos os campos que são necessários para alocação de férias anuais. Então temos nossos detalhes herdando desta interface, certo? Então, sim, você vê a implementação novamente ou você vê os campos aqui em cima. E novamente, o que eles realmente estão sendo conduzidos por este requisito da herança da interface. E então poderíamos configurar um validador contra a interface. Então todos os campos comuns, certo, resolvidos pela interface estão sendo validados. E, em seguida, os outros validadores estão apenas incluindo as validações e, em seguida, implementando suas validações personalizadas conforme necessário. Isso nos ajuda a reduzir a repetição de código. E, mais uma vez, à medida que seu projeto cresce, você corre o risco de esquecer de atualizar uma parte do seu projeto quando você faz uma alteração em algum lugar. Saiba outra coisa a notar em nosso validador, inicialmente, inicializações em nossos manipuladores, e eu não acho que eu apontei isso anteriormente, alguém para ter certeza que eu sei é que quando estamos inicializando esses validadores, nós tem que passar em um objeto do tipo que ele está esperando, certo? Porque lembre-se que este validador precisa do I leave type repositório e, em seguida, temos o construtor vendo que eu preciso do repositório tipo elif. Então não há como instanciar isso sem passá-lo. Eu gosto que temos feito aqui. Então, se você tinha direcionado linha e todo esse tempo, eu peço desculpas, eu ignoro esse, mas você pode ir em frente e fazer isso porque o que você precisa fazer é injetado no manipulador e, em seguida, ter injetado no um 100 e você apenas passá-lo junto semelhante a como, quando precisamos dele para incluir o validador base, nós tivemos que fazer a mesma coisa. Certo, este é o mesmo princípio, injeção de dependência. Tudo bem, então espero que isso tenha esclarecido um erro e se você não teve esse erro, então parabéns para você. Agora outra coisa que negligenciamos e podemos abordar saber é a inclusão de todos os detalhes que são necessários para que qualquer operação de mapeamento seja bem-sucedida. Agora só temos mapeamentos para o tipo, para como solicitar o cerco para a lista são estes são os únicos domínios para o detalhe. Então, é claro que vamos precisar, uma vez que estamos fazendo mapeamento, como neste manipulador, estamos mapeando a partir do detalhe Cria alocação de licença para deixar alocações. Então isso significa que temos que ter representação dela dentro do nosso perfil de mapeamento. Aqui eu adicionei os mapeamentos adicionais, todos aqueles para solicitações de licença que eu gosto de agrupá-los para que eles não se confundam em todo o lugar. E toda a idéia de agrupamento é um pode provavelmente apenas criar nossa razão, nossa própria as seções para que você saiba exatamente onde estão, qual set começa ou cidade você pode chamar tal aplicação cresce. Talvez queiras fazer algo assim. Certo, então essa é outra coisa que precisamos resolver antes de seguirmos em frente. Uma das coisas que eu quero falar 0 estrelas é a nossa estrutura de pastas. Então eu tinha mencionado várias vezes que sua estrutura de pastas pode diferir com base no seu temperamento ou seu Outlook ou seu visual. E quatro mantêm esses arquivos precisam ser arranjados, certo? Então eu gosto de pensar em ver QRS ou a implementação do cavalo-marinho, nossos próprios cenários. E, em seguida, todos os cenários, temos ativos específicos que são necessários. Então, quando eu digo que é um cenário, quero dizer, criar uma alocação de licença, esse é um cenário que é necessário para criar e avaliar? Você precisa do seu comando. Você também precisará do seu objeto de comando e talvez precise de alguns outros detalhes. Então você pode querer criar e você apenas incluir, você pode querer criar uma pasta dentro de alocações de licença que tem talvez em vez de recursos que você teria criado alocação de licença. E então você tem seus manipuladores e todos os seus ativos dentro dessa pasta. Portanto, a estrutura de pastas pode diferir, desde que a organização seja tal que você possa encontrar seus ativos quando precisar deles, então você está no caminho certo. Agora, enquanto eu estou no comando Cria licença alocação, outra coisa que você poderia considerar, então você vê que há tantas considerações, isso não está definido na pedra, certo? Outra coisa que você poderia considerar outra é que dentro do comando, é um padrão bem conhecido apenas usar o objeto de comando para seus campos para executar os comandos. Em vez de ter um DTO inteiro dentro do comando, você poderia realmente colocar os campos do detalhe dentro do comando. E então você apenas validar o comando em si, a solicitação em si, o objeto que entra no manipulador seria apenas este objeto. Você não teria que dizer ponto de solicitação, deixar alocação, dto ponto este campo, você apenas diz solicitação ponto este campo, esse campo, etc Então, há um número de opções disponíveis para você, mas eu vou ficar com o detalhes com tudo o que disse e feito por meio de conclusão, o núcleo ou o projeto de aplicação como nós temos, contém a funcionalidade principal do aplicativo. Então você vê que tudo é abstrato neste momento. Vamos passar para o próximo módulo onde vamos começar a colocar algumas citações reais, algumas carnes nos repositórios e qualquer outra lógica que seja aplicável. Analisamos como funciona o padrão mediador que promove acoplamento solto acoplado com o padrão C QRS onde podemos saber exatamente qual arquivo está fazendo o quê. E este manipulador vai lidar com este comportamento, este cenário. E podemos esperar essa resposta em particular por causa desse tipo de relacionamento ou comportamento que implementamos. Nós também olhamos para o layout baseado em recursos, que na minha opinião ajuda você a ver que, ok, o recurso relacionado a tipos de licença, você pode encontrar tudo dentro disso. E isso para mim ajuda com o layout. Pode ter outras ideias, mas esta é a minha recomendação. E então analisamos a validação usando API Fluente ou validação fluente. Certo, então essas são as coisas que vimos neste módulo. Então, quando voltarmos, definitivamente vamos dar uma engrenagem e começar a colocar um pouco mais de funcionalidade. 15. Visão geral de seção: Ei pessoal, bem-vindos de volta. Nesta lição, vamos começar nosso módulo onde configuramos nossa camada de infra-estrutura que você provavelmente está se perguntando, ok, qual é a camada de infra-estrutura? Bem, primeiro, ele vai ficar dentro desta pasta chamada infra-estrutura. E segundo, é o projeto no qual vamos realmente implementar todas as nossas obstruções que foram definidas na seção central. Então, vamos configurar nossos contextos de banco de dados que estaremos usando Entity Framework Core como nosso ORM para se comunicar com nosso banco de dados sob nosso aplicativo. Mas nesta camada, você configurar tudo está resolvido. O registro você, nós vamos implementar os repositórios que vamos colocar na carne real, o aplicativo. Então vamos começar. Então vamos criar duas novas bibliotecas de classe. Um chamado HR dot DV infra-estrutura de gerenciamento e um chamado HR dot leave management pensamento persistência. Conheça o projeto de persistência ou camada de persistência, irá lidar com a nossa comunicação com o nosso banco de dados. Então é aqui que nosso contexto de banco de dados ou bibliotecas EF Core e referências, tudo isso. Se fosse lá, em vez de infraestrutura, é aí que nossas implementações ficarão. Tudo bem, então entre estes dois estará implementando o repositório. Estaremos configurando quaisquer outras implementações de terceiros que sejam necessárias. E também vamos configurar serviços para serem inicializados nos serviços chamá-lo de colegas de serviços de AI Sean ou o recipiente de injeção de dependência para ASP.NET Core. Lembre-se de que as bibliotecas precisam ser feitas. É trovejada. 2.1. E você já passou por criar todo o colapso da diversidade pode seguir os mesmos passos. E quando voltarmos, vamos começar com a configuração em núcleo de trabalho diferente ou camada de persistência. 16. Adição de núcleo de Entity: Certo, então estamos de volta e vamos montar nossos projetos de persistência. Então vamos começar adicionando uma referência aos nossos projetos de aplicação. Então temos o projeto de domínio que tem todas as entidades. E o projeto do aplicativo final tem uma referência ao projeto de domínio. Então nosso projeto de persistência vai ter uma referência ao nosso projeto de aplicação começa para que possamos apenas clicar aplicativo para igual k. e, em seguida, isso é uma dependência. Não vamos também para os pacotes NuGet. Vamos procurar Entity Framework, mas o que vamos estar recebendo é entidade Framework, Core dot SQL Server. Então este quando vier para baixo, virá com todas as dependências que precisamos. Então podemos simplesmente ir em frente e instalar a última versão estável. E ainda em você começa, vamos apenas ir em frente e procurar extensões de configuração e instalar extensão de configuração de ponto da Microsoft não opções. Então isso vai ser útil quando vamos estar sentados em algumas das nossas coisas. Então, depois de tudo isso, podemos ir em frente e criar uma nova classe. E eu chamei a minha idade, nossos principais contextos BB de gestão. Então crie essa nova classe. Pode chamá-lo de outra coisa. Você provavelmente pode chamá-lo de gerenciamento de licença, contextos EB ou contextos DVI, tudo bem. Mas será herdar de contextos BB agora DVI contextos comentários para nós cortesia off microsoft dot Entity Framework Core. Então podemos ir em frente e fazer essa referência. E então podemos tornar nosso contexto de banco de dados ciente das diferentes entidades que tínhamos definido. Então, se você está familiarizado com EF Core, então você sabe exatamente o que eu quero dizer. Então neste arquivo temos algumas coisas. Temos um construtor onde inicializamos nosso contexto de banco de dados para ter um parâmetro de contextos DVI, opções fora de seu próprio tipo, e o nome é Opções, e passamos isso para a base, que é contextos DVI . Então temos nosso banco de dados em relação às nossas diferentes entidades. Então eu posso ir em frente e incluir as referências que faltam para eles e tudo deve ser verde. Em seguida, vamos substituir alguns métodos. Então o primeiro que estamos substituindo seria a equipe de criação de modelo. Na verdade, é mais rápido começar a digitar sobre ele e, em seguida, você pressionar Espaço e, em seguida, você verá todas as opções. Então, estamos substituindo o modelo em criação. Então este método é executado sempre que o banco de dados está sendo gerado, certo? Para que possamos estabelecer certas regras. Então, a regra que vamos configurar aqui com certeza, pelo menos, certo? Não. Se quisermos ver o banco de dados, podemos fazê-lo a partir daqui, mas não estamos prontos para semear, pelo menos ainda não. Queremos aplicar configurações de montagem. E então vamos dizer tipo de gerenciamento DV, contexto DV. E eu vou dizer montagem de pontos. Tudo bem? Então isso é tudo o que estamos colocando no nosso modelo criando, pelo menos, certo? Não. Como eu disse, se quiséssemos semear o banco de dados com configurações espaciais para tabelas, então poderíamos sempre dentro deste método para que eles sejam aplicados sempre que for gerado no modelo de banco de dados. Muito bem, outra coisa que queremos substituir na costa é a nossa Guardar Alterações. Alguém para escolher salvar alterações com o cancelamento Tolkien como seu parâmetro. E eu vou equipar este salvar alterações com algum código bonito, algum bom código útil que vai nos permitir fazer alguns logs de auditoria automaticamente. Então lembre-se que nós tínhamos configurado uma entidade base para cada deles que veio automaticamente com como um usuário criado, são criados por ou outro, cria um dado, etc. Então eu vou definir o loop foreach para percorrer cada entrada na mudança de entradas de ponto estrutura. E estamos apenas fazendo uma entidade de domínio baseada em custo de dados implícita. E eu posso simplesmente ir em frente e incluir a declaração de uso para ele. E então, para cada um, o que eu quero fazer é definir a data, adicionado, data, modificado em todos os momentos. Então eu sempre posso ver uma vez que você está prestes a ver alguma mudança, eu quero entidade de ponto de entrada, vidro de ponto modificado por nossos dados Last Modified, em vez disso, estamos lidando com a data, certo? Não. Tempo. Não. Certo. E então eu fui fazer uma verificação e eu vou apenas dizer se o estado de entrada é equivalente a entidades, Estado DOT adicionado, o que significa que é batidas sendo adicionado, é um novo registro. Em seguida, gostaríamos de sentar o criado para datetime dot null. Então nós permitimos é a nossa data criada em vez, então vamos sempre definir o Last Modified. Ele quer que algumas coisas sejam mudadas. Uma tensão que estamos sentados modificou-a. Mas então só quando ele está sendo adicionado, nós definimos o criado e é assim que é. O código básico mais básico para implementar a auditoria que você pode encontrar. Mais uma vez, isso é automatizado, então toda vez que pressionamos Salvar alterações, ele faz tudo isso. E então ele só causou a base c de g e g é o método em segundo plano. Então é isso para adicionar na estrutura à nossa camada de persistência. Quando voltarmos, começaremos a trabalhar em algumas implementações. 17. Implementação a camada persistence: Bem-vindos de volta, rapazes. Nesta lição vamos implementar nossa camada de persistência. Então, quando eu falo sobre implementar a camada de persistência, estou me referindo especificamente ao nosso repositório genérico, certo? Então só temos a abstração, mas não temos código para fazer isso. Então vamos em frente e fazer isso. Então, adicionamos uma nova pasta. E eu vou chamar esses repositórios de pastas. E, em seguida, nesta pasta, vamos adicionar uma classe que irá representar a implementação do repositório genérico em relação ao tipo T. Células degeneradas na classe. Nós, como de costume, torná-lo público, e então nós torná-lo relativo a t0. E, em seguida, ele herda do repositório genérico IJ, que também é relativo a T onde T classe dois-pontos. Tudo bem, vá em frente e inclua quaisquer referências faltantes e então permita que ele implemente a interface. Então eu vou em frente e escrever a citação e então vamos passar por isso juntos. Agora, antes de continuar, eu percebi que eu superei Zillow, Suíça para copiar e colar telefone. Estamos sentando na interface. Assim como alguns desenhos animados para a atualização e a exclusão, podemos remover o T, certo? Não falamos para retornar nada quando fazemos uma atualização ou excluímos. Então esses dois devem ser apenas tarefas, então você pode ir em frente e fazer essa mudança. E então, claro, isso afetará nossa implementação. Portanto, nosso repositório genérico começa com um construtor que está aceitando um parâmetro de contextos DVI de gerenciamento de licença de tipo. Claro, o contexto DB é basicamente nossa conexão com o banco de dados. Então precisamos dele em nosso repositório, a fim de realizar nossas operações ou adicionar método. Ele começa com nossa ponderação de uma chamada de contextos de banco de dados para adicionar um coletor onde ele apenas passa na entidade EF Core é inteligente o suficiente para inferir que entidade está sendo passada em relação a todos os conjuntos de banco de dados que foram definidos em nosso contexto DV. E por db sit quero dizer estes. Portanto, seja qual for o tipo de dados passado, ele saberá se é um dos conjuntos de banco de dados que ele reconhece. Então vamos apenas ir em frente e adicionar a entidade, salvar as alterações no novo retorno, essa entidade. Para Excluir, mais uma vez, remova o parâmetro type da tarefa. Mas tudo o que ele vai fazer é olhar e DB contexto, encontrar o conjunto relativo a t0 que ele está sendo dado e ele vai remover essa entidade daquele sit. Tudo bem, e depois disso ele salva as alterações. Então você vai notar que nada realmente acontece até que você veja se muda. Este é o commit final para o banco de dados. Temos o método existe onde obtemos uma identificação para o nosso registro. E o que eu vou fazer é procurar a entidade usando o método GET local, que veremos em alguns. E então retornamos que não é igual a nulo. Então, quando não é igual a nulo, então sim, ele existe caso contrário isso é falso. Claro que, no gueto, o que estamos fazendo é que estamos retornando uma chamada não ponderada para o conjunto de pontos de contexto DB t. Então, mais uma vez, estamos olhando para o conjunto específico e estamos encontrando o registro relativo ao ID. Tudo bem, para o nosso eu li na lista T, que é obter tudo que é o que ele está retornando. Tudo o que estamos fazendo é olhar no set e estamos fazendo uma lista assíncrona duas nesse set. Então nós estamos apenas recebendo tudo desse conjunto e enviando-o para a lista e retornando isso em nossa guitarra para as atualizações, o que estamos fazendo é definir a entrada no estado para modificá-lo para que o EF Core, vamos começar a rastreá-lo e então vamos em frente e salvar as alterações. Então isso é muito bonito para a nossa implementação para o repositório genérico. Tudo bem, então agora que temos nosso repositório genérico implementado, agora precisamos implementar nossos repositórios específicos para que possamos ir em frente e adicioná-los. Então, começando com o repositório tipo folha, vamos olhar para o que a implementação se parece. Então eu criei o repositório tipo folha. É uma classe pública chamada repositório tipo folha, herdando da implementação do repositório genérico em relação ao tipo folha. Tudo bem, e então vamos em frente e dizer que é também para herdar do repositório tipo elif. Então as linhas vermelhas aqui indicam algumas coisas. Primeiro, precisamos trazer o namespace ausente para, precisamos colocar na implementação real este, este cisne, certo, esta interface não tinha nenhum método adicional, então isso é bom para nulo. E então isso está reclamando porque precisamos ter o contexto DB presente. Para o repositório genérico. Então lembre-se que quando você está herdando algo que tem uma dependência, você tem que colocar essa dependência no herdeiro também. Então essa é uma solução simples. Pegamos o construtor e depois fazemos nossa injeção de dependência. E isso é para o contexto DB, é claro, mas então também precisamos deixar o baixo observar que ele também pode usar esse contexto DB que está sendo injetado. E é isso para o repositório de tipo folha. Então o contrato não tinha nenhum método adicional. Não há nada extra para implementar. E porque ele está herdando do repositório genérico em relação ao tipo de folha. Usando esta implementação, temos acesso a todos os métodos que foram definidos aqui. Agora vamos olhar para alguns mais complicados. Então vamos olhar para pedidos de licença. Deixar requisições repositório sem isso parecem requisitos de dependência. Então temos que nos certificar de que injetamos o contexto DB possível para as abelhas. Vá em frente e incluir quaisquer namespaces ausentes, e então temos que implementar a interface. Então esta interface realmente tinha alguns métodos, extra. Tivemos status de aprovação de alteração, tivemos solicitações de licença com detalhes, e adicionamos outro para obter solicitações de licença com detalhes por ID. Poucas coisas estão acontecendo neste particular. Assim, as implementações aqui serão diferentes das genéricas porque estas são específicas para algumas operações relacionadas a solicitações de licença. Assim, as implementações são as seguintes. Para a solicitação de aprovação de alteração, estamos recebendo um parâmetro de solicitações de licença e status de aprovação. Estamos ajustando o estado aprovado da busca da alavanca para qualquer valor que tenha chegado e o parâmetro. E então estamos definindo contextos de banco de dados não solicitações de licença de entrada. Então você vê que desta vez não é uma entidade, não é genérico. É muito específico porque estamos neste repositório específico. Então, estamos definindo o estado de entrada ou o estado da entidade, modificá-lo para essa solicitação de licença e, em seguida, salvamos as alterações para que ele comece a rastreá-lo e, em seguida, ver se a alteração de acordo. Agora você vê que esta é uma operação muito específica em vez da atualização geral onde não podemos explicar o que está sendo alterado. Então nós apenas configuramos tudo para modificá-lo e permitir que ele caminhe. Mais uma vez, estas são apenas idéias porque talvez suas regras de negócios sejam muito mais complicadas ou a operação que você tem que realizar dentro do repositório é muito mais complicada do que apenas sentar um campo. Então você pode precisar de uma função especializada para isso. Agora para as solicitações de licença do get com o método de detalhes, tudo o que realmente estamos fazendo é consultar a tabela de solicitações de licença. Portanto, var leave requests é igual a aguardar contextos DVI não deixar solicitações. E então estamos incluindo o tipo de folha. Portanto, nem sempre queremos incluir o tipo de folha. Não sabemos em que circunstâncias podemos precisar. Então nós temos este relativo aos detalhes que são necessários juntamente com o registro para o genérico regular que não está incluindo está apenas retornando dados da tabela. Então, desta vez vamos incluir detalhes. Poderia ser este tipo de folha, poderia ser mais como muitos inclui que você pode precisar. E então estamos empurrando todos para listas. E então estamos voltando para o final onde estamos recebendo apenas um pedido de licença com detalhes baseados na identificação. Estamos fazendo algo semelhante, exceto que estamos fazendo o include e, em seguida, dx no primeiro ou padrão foram o ID da fila corresponde ao ID Boston. Agora estamos fazendo primeiro nosso padrão aqui em vez da descoberta, um coletor que fizemos no repositório genérico por causa de como esses métodos funcionam, você não pode fazer uma inclusão quando você faz uma descoberta, ele simplesmente não funciona. Então, quando você tem que fazer uma inclusão, você tem que usar o primeiro ou o único ou padrão, qualquer que você se sentir mais confortável com. E então devolvemos o pedido de licença que foi encontrado. Então podemos saltar para deixar alocação e vemos que é uma implementação relativamente semelhante. Temos métodos semelhantes. Então eu coloquei esses métodos aqui apenas para apontar que você pode ter métodos personalizados nesses repositórios. Você pode não necessariamente precisar deles em seu aplicativo, use-os como você precisa deles. Eu também manter essa linha vermelha, porque no caso de você estar entrando em tudo que você precisa é incluir essa referência, que EF Core e, em seguida, isso é bom. Tudo bem, então nós temos uma grande atividade esquerda e então nós terminamos com a camada de persistência. E isso é configurar a classe de registro para a persistência. Então, apenas serviços de aplicação local, distribuição Hadar. A persistência definitivamente precisará de um. Então vá em frente e adicione esta nova classe. Estou ligando para serviços persistentes ou distribuição. Deve ser uma classe pública estática. E então nele teremos. Um método que retorna eu sirvo como coleção e estamos chamando de configurar serviços persistentes. Então, é claro, como de costume, vá em frente e instale qualquer ou qualquer outro Qualquer usando instruções que são necessárias. E então dentro deste método, o que vamos fazer é escrever código para vagar. Você armazena o contexto do banco e adiciona nossa ferramenta de repositórios, a coleção de serviços. E este é o método completo de, é claro, o que as linhas vermelhas, porque sempre gosto de mostrar-lhe o que Redlands me existir e como você pode resolvê-los. Mas é assim que esse método precisa se parecer. Então você pode ir em frente e começar a incluir nas instruções usando que estão faltando. Então, em primeiro lugar, temos o contexto ADB services.js onde passamos no tipo que é o banco de dados contextos deixar o contexto de banco de dados de gerenciamento e opções ponto SQL Server. Então lembre-se dos contextos de banco de dados que dissemos a ele que precisamos, no contexto de banco de dados na criação de modelos, dissemos a ele que sentiria muito, no construtor, certo? Tomamos opções de contextos BB. Então essas opções estão realmente vindo de quaisquer opções que são definidas aqui dentro, uma distribuição. Então vamos em frente e usar EF Core para a configuração de uso do SQL Server está chegando porque vamos passar sobre a configuração do aplicativo cliente que está implementando isso chamado de bootstrapper serviços. E então nós definitivamente precisaremos passar. Isso não é conflito. configuração I precisa ser a configuração do ponto de extensões da Microsoft, não a parte superior do outono. Então tenha muito cuidado com isso. Então podemos ir em frente e incluir esse namespace. E, em seguida, para depositários, temos adicionar escopo. Então, estamos adicionando todos eles são escopo. Mas, em seguida, para o genérico, observe que estamos adicionando tipo de repositório genérico ij com nossos colchetes angulares tipo vírgula de repositório genérico, colchetes angulares. Mas, em seguida, cada outro é a interface para o peer de implementação sem quaisquer colchetes angulares. Mas vou em frente e adicionar quaisquer referências que faltam aqui. E com isso, e oh, desculpe, eu escrevi o código erradamente aqui para este, adicionar escopo é parênteses abertas e nenhum colchetes angulares para o anúncio educado. Tudo bem, então deixe-me carregar isso para que você possa ver. Lá vamos nós. Então é entre parênteses com escopo, tipo de repositório genérico olho com colchetes angulares, tipo vírgula de repositório genérico com colchetes angulares. Eu não mais uma vez, aqueles estão entre parênteses enquanto os outros terão os colchetes angulares torno da interface e implementação emparelhamento. Depois de tudo isso, é claro que devolvemos os serviços. Então, apenas para retroceder um pouco para o que esta cadeia de conexão será, nós não temos uma configuração de aplicativo ainda, então isso vai viver nas configurações do aplicativo que vai chamar este método. E assim, quando ele está chamando configurar serviços persistentes, ele é esperado para ser possível com esse objeto de configuração, que então dará acesso às configurações do aplicativo. E nós seremos capazes de obter essa cadeia de conexão para possível Qual é o nosso contexto de banco de dados? Então é isso que toda a linha ou toda a seção está fazendo. Agora, o propósito da força usando escopo, existem três modelos de injeção disponíveis para nós. Temos na escola para ter singleton e adicionar transiente. Singleton significa que em uma instância deste serviço existirá, lançar todo o aplicativo. Isso pode ser perigoso com base na natureza do serviço. E poderia ser útil, por exemplo, talvez um serviço de registro que poderia ser um no sensor ou em toda a aplicação. Você provavelmente não quer algo assim para suas transações de banco de dados. Porque quando você tem várias transações de banco de dados, você meio que quer que elas aconteçam em silos. Então é por isso que usaria o escopo, que significa que durante toda a nossa missão, estou solicitando algo. Estou escrevendo para o banco de dados, estou ligando para o seu serviço durante toda a vida dessa operação. Em seguida, adicionar escopo irá invocar e conexão com o banco de dados ou uma instância deste repositório tipo folha ou qualquer um desses repositórios, como é chamado durante a nossa solicitação. Assim que o pedido estiver terminado, ele não estará mais na memória. Isso reduz as chances de conflito. E, em seguida, adicionar transiente significa que cada vez que ele sempre vai fazer algo novo, que significa que você pode acabar com mais do que você realmente precisa para completar uma solicitação, que também pode levar a conflitos. Então, mais uma vez, você pode usá-los com moderação, mas dentro desse contexto, adicionar escopo é o que queremos para nossas operações relacionadas ao banco de dados. Agora, com tudo isso feito, vamos fazer um projeto de lei rápido para garantir que estamos no caminho certo e que não temos erros e que construímos com sucesso nossos projetos. Então, quando voltarmos, começaremos a implementar ou a infraestrutura. 18. Adicione projeto de infraestrutura (serviço e-mail (: Bem-vindos de volta, rapazes. Nesta lição, estaremos configurando projetos de infraestrutura agora nosso projeto de infraestrutura é praticamente onde as implementações de todos os nossos serviços de terceiros estarão presentes. Nesta lição, implementaremos um serviço de e-mail com a ajuda do SendGrid. E vamos configurá-lo no projeto de infraestrutura. Agora, a primeira coisa que precisamos fazer é configurar uma abstração para os remetentes de e-mail, mesma forma que tivemos obstruções para nossos repositórios. Temos uma obstrução ao nosso contrato para o serviço de e-mail. Agora, com essa nota, eu estava olhando para trás e percebi que a estrutura de pastas aqui não é muito intuitiva para o longo prazo. Então eu fui refatorar aqui porque eu tenho persistência e então eu tenho contratos. Mas contratos é o termo mais universal porque então você tem contratos para a persistência em seus contratos para a camada de infra-estrutura e assim por diante. Então eu vou ter que virar. Essas pastas são de propriedade, o que não será muito difícil neste chamado contratos de pasta de persistência. E depois vou chamar a persistência dos contratos. Agora isso vai ter um efeito ondulado para todo o namespace é porque queremos que nossos namespaces sejam completamente representativos do que eles realmente são. Então nós temos contratos de persistência, não, nós vamos ter que mudar isso para contratos persistência pensamento. E então isso vai perder com todas as referências de namespace. Sinto muito, terrível isso. Mas é um fator que é definitivamente necessário para termos uma estrutura de pastas intuitiva, certo? Então, depois de fazer tudo isso, se fizermos uma compilação, ele irá apontar todos os namespaces de extremidade que foram referenciados em todo o nosso projeto. Então, você sabe, maneira rápida de ir em frente e consertar isso. Mas namespaces seria procurar contratos de ponto persistência em todos os lugares e, em seguida, substituí-lo com contratos ponto br sistema. Então você pode apenas fazer isso e meticulosamente passar e substituir cada termo faz para mim certeza que você não sobrepõe nada que possa ser importante. E uma vez que você tenha esgotado essa pesquisa, você pode ir em frente e fazer outra conta apenas para ter certeza que você não tem mais nenhum erro de compilação. E assim que isso for feito, eu vou fechar todas as banheiras e que foram abertas naquela operação e então podemos ir de novo. Então, nos contratos, queremos uma nova pasta, nossa chamada de infraestrutura. E, em seguida, dentro desta pasta vamos adicionar um novo contrato ou interface. E eu estou chamando-o eu email remetente, sei que eu email remetente vai ser interface pública com um método que vai ser chamado enviar e-mail. E será preciso um parâmetro do tipo de e-mail chamado e-mail. Agora precisamos definir como esse e-mail se parece. Então eu vou criar outra pasta para modelos, certo? Então deixe-me adicionar essa pasta. Estamos chamando de modelos. E, em seguida, dentro da pasta deste modelo, estamos adicionando uma nova classe que estamos chamando de e-mail. Então este vai ser o nosso modelo, nosso modelo para o que qualquer e-mail deve ser parecido. E, em seguida, este e-mail terá as propriedades típicas de qualquer e-mail que para o assunto e o corpo, todas as propriedades string. Então, agora que temos esse modelo definido, podemos ir em frente e adicionar a instrução de uso e ter isso resolvido. Antes de seguirmos em frente de nossas definições de modelo, temos outro modelo que precisamos, e este será para as configurações de e-mail. Tudo bem, então ele vai mangueira propriedades para uma chave API de endereço e o nome de de, todos os quais são string. Agora que temos algumas coisas novas com nosso remetente de e-mail, você provavelmente está se perguntando, ok, por que eu preciso de e-mail? Então o coloca em contexto porque acabamos de começar a construir o serviço de e-mail sem contextos reais. Quando alguém se inscreve para folha ou talvez seus status de aprovação alterem algo assim, você gostaria de notificá-lo de que esta ação ocorreu. Não há ações estranhas acontecem bem em relação aos recursos, temos nossos manipuladores. Então, quando você cria uma nova alocação ao vivo, ok, talvez você não precise enviar um e-mail, mas então uma solicitação de licença justificaria que um e-mail seja enviado sempre que um for criado ou um for atualizado. Tudo bem, então vamos olhar para o manipulador Criar solicitação de licença onde podemos simplesmente injetar ou eu enviar e-mail remetente. E eu vou fazer isso usando o IntelliSense. Rápido, inicialize o campo. E depois dada a nossa convenção de nomes, vou mudar o nome usando o sublinhado dentro nosso manipulador depois de tudo ter sido bem sucedido, antes de voltarmos e matarmos toda a operação. Então o manipulador ainda está indo para esta linha. Então, aparecerá um objeto de e-mail e, em seguida, tentar enviá-lo fora. E lidaremos com uma exceção. Então vamos olhar para isto devagar. Então var e-mail é igual a um novo e-mail, que é o nosso modelo que acabamos de definir. Nós temos os dois, eu apenas colocar em um e-mail fictício lá quando chegamos a toda a autenticação do usuário e ter usuários reais enviar. E veremos como obtemos os endereços de e-mail reais. Temos o corpo. E o corpo deste e-mail apenas diz que o seu pedido de licença para e eu estou apenas colocando usando interpolação para colocar no início de conteúdo precisa terminar. Ele foi enviado com sucesso e o assunto é solicitações de licença enviadas. Se você quiser, você pode ajustar ainda mais a data colocando em dois pontos D. Então, tradicionalmente você diria toString e, em seguida, especificar o formato. Mas quando estamos usando interpolação nesta versão de C Sharp, nós podemos apenas colocar em dois pontos e a formatação, bem, a string de formatação no final dela. E isso vai cuidar disso para nós. Então, daria a você o nome longo. Segunda-feira, Junho desta data, este ano. Tudo bem. Então é isso para ou manipulador saber que todo o nosso aplicativo sabe sobre o remetente de e-mail olho precisamos trabalhar na implementação para que a implementação deste vai viver em nosso projeto de infra-estrutura. Então, para começar isso cria uma nova pasta dentro do projeto de infra-estrutura chamado refeição. E, em seguida, crie uma classe lá chamada remetente de e-mail. E então essa classe, que é claro que estes são o público, herdará do remetente do e-mail. Então podemos ir em frente e então você percebe que ele precisa de uma referência para o aplicativo. Então precisamos ir em frente e adicionar isso. E com essa referência nisso, podemos ir em frente e implementar a interface. Então, antes de avançarmos, precisamos pular para o novo Git. E precisamos de alguns pacotes. Swan é as mesmas extensões de configuração que teríamos usado dos outros projetos. Então, uma maneira rápida de gerenciar projetos comuns é simplesmente ir a esta solução e dizer pacotes Managed NuGet para a solução, certo? Então já temos alguns pacotes instalados em alguns projetos que precisamos em outros como este, as extensões de configuração. Então eu posso clicar nele e eu vejo que ele já está nos projetos de persistência, mas eu queria no projeto de infra-estrutura também eu posso marcá-lo, clique em Instalar. E isso pode reduzir a quantidade de tempo que você gasta no NuGet tentando encontrar o mesmo pacote várias vezes. Agora, o próximo pacote que me interessa é o SendGrid. Então você pode saltar para os manos e apenas entrar no SendGrid, e então você pode obter as versões mais recentes. Então, você deve clicar nele, certifique-se de que você está tomando o projeto correto e, em seguida, clique em Instalar. Então, depois que isso for instalado, vamos começar a ligar esta classe. Então, uma coisa que eu vou fazer é configurar um campo privado de tipo configurações de e-mail e sobre suas configurações de e-mail sublinhado tornando somente leitura. Mas, em seguida, eu estou inicializando-o no construtor com este i opções Email Settings parâmetro. Agora deixe-me explicar o que isso é semelhante a como nós tínhamos configurado nosso banco de dados. E dissemos que temos um arquivo de configurações do aplicativo que forneceremos a cadeia de conexão quando chegar a hora. É da mesma forma que podemos realmente passar por cima. Opções são pedaços de opções são configurações do, de todo o arquivo de configurações do aplicativo, que pode ser desserializado em um objeto inteiro para nós. Então, o que estamos fazendo você ver me pegar do, a partir das opções são as configurações do aplicativo, as configurações de e-mail, JSON equivalente, e enviá-lo sobre como este parâmetro. E então nós podemos apenas injetá-lo e, em seguida, tê-lo como nossa variável local, nosso campo em nossa classe. Então essa injeção de dependência é tão legal porque torna tudo tão frouxamente acoplado e maleável. Então vamos continuar com a configuração de nossos métodos de envio de e-mail. Então, a primeira linha que vamos ter é um cliente que vai chamar ou inicializar uma reivindicação do SendGrid. Então, vamos apenas ir em frente e adicionar usando instruções que estão faltando. Depois que pegarmos o cliente, teremos que pegar todo o assunto e os dois e o corpo do e-mail do nosso objeto de e-mail. Mas os dois e o de especialmente precisam ser um tipo de dados especial. Então eu vou dizer var 2 é igual a novo endereço de e-mail. E o endereço de e-mail aqui está vindo do Sin Grid. Então, novo endereço de e-mail. E então nós vamos ter que passar em e-mail dot tube. E então nós vamos ter que fazer a mesma coisa para o de. Então eu vou dizer var from é igual ao novo endereço de e-mail. E nesse, nós vamos tipo de colocar você em um pouco mais na definição onde eu vou ver o e-mail está vindo das configurações de e-mail ponto de endereço. E, em seguida, o nome seria as configurações de e-mail ponto a partir do nome. Tudo bem. Então temos o de e o para definido. E depois de fazer tudo isso, precisamos ver. A mensagem é igual a ajuda masculina. Então Male Helper é, que vai ser uma classe estática dada a nós pela grade do pecado que nos permite criar um único e-mail. Lá vamos nós. E você vê que você tem opções diferentes para vários destinatários e vários e-mails. Vários destinatários estavam apenas fazendo um único e-mail nessa situação. Mas você pode ver que talvez você tenha enviado e-mail, enviar e-mail para vários enviar e-mail com um anexo, etc. Assim, você pode definir diferentes métodos dentro do remetente de e-mail E. Você não está confinado apenas a este que estamos fazendo. Tudo bem? Então crie um único e-mail. E então nós vamos ter que preencher este velho de acordo com a OMS eles declararam isso no, nos parâmetros para o construtor. Então o Fromm vem primeiro. E então nós dizemos também, nós temos esses. E, em seguida, o assunto, eu posso ver e-mail lote assunto aqui. E o conteúdo de texto simples seria o corpo do e-mail. E você pode ver que eles têm o conteúdo de texto sem formatação versus o conteúdo HTML. Baseado em como codifica seu e-mail, você poderia juntar esse e-mail de acordo, certo? Mas por enquanto eu só vou dizer e-mail ponto corpo para ambos os parâmetros. Então, agora que temos o objeto de mensagem formulado, eu vou dizer var resposta é igual a clientes enviar e-mails. Então é aqui que vamos enviar essa mensagem que acabamos de criar. Claro, estamos recebendo a linha vermelha porque precisamos ser uma pia. E uma vez feito isso, não precisamos retornar um booleano baseado na resposta. Eu posso apenas dizer retorno se resposta pensamento código de status é equivalente a e eu posso apenas dizer system.in é código de status HTTP. Está bem. E eu acredito que o SendGrid também atende a alguém aceito para fazer os dois, alguns retornando. Só estou voltando. Ou está tudo bem ou aceito. Então isso vai acontecer se é que qualquer um deles é verdade. Se não for nenhum deles, então é falso e eles saberão se o e-mail foi bem-sucedido ou não. Mas a questão disto, mais uma vez, vou voltar ao nosso Tumblr criar e a forma como o envolvemos em um try catch, a API que está chamando este manipulador ou qualquer código que está chamando este manipulador não deve ser interrompida se Tudo o resto. Então esta é a parte mais importante criar as solicitações de licença se os campos de e-mail, isso não significa que ele deve travar o programa. Então é por isso que estamos pegando a exceção, mas não estamos fazendo nada para jogá-lo dito são através de toda a aplicação. Agora, para completar tudo, vamos ter um arquivo de registro de serviços de infraestrutura, assim como todos os outros projetos antes dele. Então, temos a classe de registro de serviços de infraestrutura sendo adicionada a esses projetos de infraestrutura. E então temos a mesma forma que todas as outras classes de distribuição tiveram. Mais uma vez, a configuração I está sendo injetada. E o tipo que somos, o namespace que precisamos é a configuração de extensões da Microsoft, não outono superior e eu vou trazê-lo para cima toda vez porque ele pegou mais de um, desculpe. Então, vamos ver os serviços ponto configurar as configurações de e-mail. Então isso é tudo estudando que queremos Email Settings. Eu só vou trazer esse para B em relação a um servidor de configuração MouseY e-mails configuração quando fazemos as opções de ponto, estamos vendo dar-me um pedaço da configuração que se parece com as configurações de objeto EMEA. Bem, o que realmente vamos ver é configuração ponto recebe seção. E ele vai olhar nas configurações do aplicativo para nossa seção com o nome. Vamos me chamar de configurações de e-mail quando chegar a hora. Então, dessa forma, ele vai saber que vamos formular essa seção para se parecer exatamente com o que estamos esperando a classe para se parecer. Então, ele será apenas serializado automaticamente em que a classe codificada dura são fortemente tipado vidro em vez. Próxima parada vamos ver serviços que adicionam transiente. Agora lembre-se que eu estava falando sobre os diferentes modelos. Nós temos. Singleton, esculpir e transitório. Então, transiente significa que toda vez que eu sou chamado, eu vou ser uma nova instância. Então estamos vendo que toda vez que eu enviar e-mail remetente é chamado, me dê uma nova instância do, da classe de remetente de e-mail. Tudo bem, então vá em frente e inclua quaisquer referências faltantes. E depois podemos fechar esse e depois devolvemos os serviços. Então é isso para nós sentarmos nossa infraestrutura, pelo menos isso é um nível muito básico. Mais uma vez, quaisquer contratos que teremos que definir para uma operação de terceiros serão definidos em nossa aplicação, mas implementados em nossa infraestrutura. 19. Crie e configure a API de aplicativos: Bem-vindos de volta, rapazes. Nesta lição, estaremos configurando nossos projetos de API. Portanto, temos a base já na forma de infraestrutura, os projetos de persistência ou domínio e nossos projetos de aplicação. A coisa é que estes irão evoluir com a sua aplicação. Então essas camadas são esses projetos. Eles não são definidos em pedra, mas pelo menos estabelecemos a base para construir uma API em cima dela que realmente será responsável por informações tóxicas entre qualquer aplicativo cliente e essas camadas para nós. Então vamos começar a configurar esses projetos de API. Vamos colocá-lo em nossa pasta chamada API. Vamos para Adicionar novo projeto, encontrá-lo facilmente, pode apenas procurar na lista para API. E estamos usando o modelo de projeto de API C-sharp, e estamos chamando essa API de ponto de gerenciamento de um ponto de HR. Vá em frente e aperte Next, e estamos usando dotnet cinco são a versão mais recente, porque.net é muito compatível com versões anteriores. Assim, a maioria, se não todo o que estamos fazendo este curso será compatível com futuras versões do dotnet e vamos continuar com as configurações e criar. Agora, este projeto de API é bastante bare bones. Ele nos dá algum código de exemplo na forma deste controlador de previsões meteorológicas, que não precisaremos necessariamente. Antes de avançarmos, vamos adicionar as dependências que este projeto de API terá. E essas dependências incluem nosso projeto de aplicação ou projeto de infraestrutura e/ou projeto de persistência. Praticamente qualquer um dos projetos que nós criaríamos esses métodos de serviços de registro. Essas serão dependências para a API porque a API precisa ser capaz de registrar esses serviços em sua base de código. Então podemos ir em frente e adicionar essas referências de projeto. E uma vez feito isso, podemos continuar nossa configuração. Então, quando falamos sobre criação e configuração que criamos não, precisamos configurar. Então, em termos também das coisas que têm dependências sobre o que vamos estar sentados na API. Estamos falando sobre as configurações de e-mail. Portanto, lembre-se que em nossa infra-estrutura teríamos feito menção do remetente de e-mail ou teria implementado o remetente de e-mail outro e é dependendo de Configurações de e-mail vindo através de opções de AI, configurações de e-mail, que já discutido vai vir do nosso arquivo de configurações do aplicativo. Outra coisa que precisamos configurar é para nossa camada de persistência. Desculpe, eu só estou escolhendo descontroladamente para camada de persistência ou DB. Contexto depende uma cadeia de conexão que será exibida mais uma vez a partir da API. Então, nosso arquivo de configurações do aplicativo aqui, teremos blocos ou seções que têm essas definições. Então vamos trabalhar no primeiro, e essa é a nossa cadeia de conexão. Então, acima desta definição de log aqui, eu só vou pressionar Enter e, em seguida, eu vou colocar na minha seção de strings de conexão. Então cordas de conexão. E então ele tem o mesmo nome que nós teríamos referido na redistribuição de persistência, certo? Obter cadeia de conexão. E então é deixar cadeias de conexão de gerenciamento. Então cadeia de conexão sabe procurar no aplicativo settings.js ON procurar cadeias de conexão, obter esse pelo nome. E sua definição aqui é que estou usando o servidor de banco de dados local MS SQL, então você tem que digitá-lo exatamente como você vê isso na tela aqui. Isso é incorporado no Visual Studio. Banco de dados é igual a, e eu estou chamando meu HR sublinhado licença de gerenciamento sublinhado DB. Pode chamar de outra coisa, se quiser. E além disso, e cada um é separado ponto e vírgula e, em seguida, temos conexão confiável é igual a verdadeiro ponto e vírgula vários conjuntos de resultados ativos é igual a verdadeiro. Então essa é a sua cadeia de conexão. Agora, para as configurações de e-mail, vamos ter uma nova seção chamada Configurações de e-mail e, em seguida, temos essa chave de API. Então eu preciso, precisamos ir com o SendGrid, em seguida, obtém a nossa chave API de repente, colocando um lugar titular para nulo. E então temos o nome de origem, que é de onde o e-mail vai parecer vir e, em seguida, o endereço de partir será nenhuma resposta em leave management.com ou leave reply. Sem resposta, desculpe, em Ahrq.com, o que quer que você queira lá. Agora, no caso de você não estar muito familiarizado com o que é SendGrid. É um produto de dois níveis que nos permite acesso sobre Paul para o sistema de API de e-mail. E você pode começar de graça. É grátis até certo ponto, claro, e você não quer abusar disso. Mas uma vez que você se inscrever, eles lhe darão essa chave de API, que é o que você pode manter ali mesmo nas configurações de e-mail, no aplicativo settings.js IN. Podemos fazer isso mais tarde. Claro, eu não quero que você veja minha chave porque a chave é privada, então você quer ter certeza de que você mantém a privacidade com isso. Então, agora que temos o nosso AP settings.js, arquivo JSON pelo menos o equipado com o mínimo de quatro ou distribuição de nossos serviços. Vamos pular para o startup.js. Então, eles não são alguns do arquivo startup.js. É basicamente o contêiner que diz que essas são todas as dependências que meu aplicativo precisa saber sobre. E estou a torná-los acessíveis através de injecção de dependência. Tudo bem. Estamos falando de injeção de dependência há algum tempo. E cada um desses arquivos de registro é basicamente nos permitindo registrá-los como dependências em um aplicativo. Então, o que precisamos fazer é deixar nossa API saber que essas são dependências que cada um deve saber sobre. Então, quando falamos sobre a figuração do ícone, você percebe que ele está sendo passado para a inicialização enquanto ele está sendo injetado diretamente na inicialização. E isso nos permite então passar esse objeto de configuração para outras partes de nossa redistribuição. Então teríamos visto na infraestrutura se não me engano, lá vamos nós. I configuração precisa da configuração e nós precisamos dela para a persistência também. Chega de conversa, vamos entrar na ação. Portanto, em nosso método configure services, queremos incluir essas três linhas, que são os Serviços de Aplicativo Configurar, configurar serviços de infraestrutura e configurar serviços persistentes, e configurar serviços persistentes, todos os quais sabemos barco proveniente de nossos serviços ou à distância, arquivos de redistribuição de serviços nos diferentes projetos. Então aqui está a pega-tudo. Então ele vai apenas ir em frente e adicionar quaisquer dependências e namespaces ausentes para cada um deles. Observe também que temos que passar em que objetos de configuração. Tudo bem, então nós o injetamos na inicialização e então podemos passá-lo para que quando esses métodos estão sendo chamados em seus respectivos projetos e eles tenham as ferramentas necessárias para acessar o que eles precisam acessar do nosso aplicativo configurações. Outra coisa que queremos configurar nesta API é, ou o que vamos chamar de política CORS. Portanto, nossa política de curso determina basicamente como a API permite que outros clientes interajam com ela. Por isso, neste momento, esta política é bastante aberta. Onde é que vendo serviços ponto-ponto núcleos construtor permitir qualquer origem, permitir qualquer método, permitir qualquer cabeçalho. Em seguida, em nosso método de configuração, vamos descer e eu vou apenas colocá-lo aqui entre Autorização de Uso e usar endpoints. E isso é amenizado nem deve utilizar essa política em toda a parte. Agora viemos um bom caminho com todas as configurações. Temos mais um passo para esta lição, que é gerar nosso banco de dados. Então fizemos tudo isso. Nós temos a camada de persistência agora nós realmente tê-lo ligado. Não, estamos passando a cadeia de conexão. Então agora ele sabe que quando ele existe, em qual servidor ele deve existir e qual o nome do banco de dados deve ser. Então vamos ter o nosso próprio para vir configurando nosso banco de dados. Então precisamos executar migrações. E eu só estou fazendo uma construção rápida que foi bem sucedida. Então, antes de passarmos para as migrações, precisamos ter acesso à nossa ferramenta EF Core. Então vá para o Gerenciador de Pacotes, tudo isso. Ele vai procurar ferramentas. E com certeza, Microsoft dot Entity Framework Core ferramentas é a segunda nos resultados da pesquisa. Então eu vou ir em frente e instalar isso no meu projeto API. E com essa configuração, eu também vou definir o projeto de API como meus projetos de inicialização. Então eu posso fazer isso a partir desta lista suspensa, Muitos acima, ou eu poderia clicar com o botão direito do mouse nele e dizer definir como projeto de inicialização. Agora, com tudo isso feito, podemos prosseguir para o nosso Console do Gerenciador de Pacotes. Então, se você não tem isso em seus itens de menu ou como uma barra de ferramentas como eu tenho, então você sempre pode ir para Ferramentas, ir para o gerenciador de pacotes NuGet e você verá o console listado lá. Neste console do Gerenciador de Pacotes, vamos adicionar migração SHE e podemos dar-lhe um nome para que eu possa chamá-lo de migração inicial de criação, algo que indica que foi a primeira, certo? Outra coisa que você gostaria de fazer é alterar os projetos padrão. Portanto, o projeto padrão precisa ser o mesmo projeto onde seu contexto de banco de dados é alguma configuração que seja o projeto de persistência. E para contextos, lembre-se que em nosso projeto de persistência ou em contextos de banco de dados, dissemos que o modelo na criação não-modelo, dissemos aplicar configurações de assembly e onde quer que seja esse assembly, isso é praticamente o que que a linha estava especificando. Então precisamos do nosso diretório de migrações aqui. Então certifique-se de que isso está definido. Se você não fizer isso, você vai ter um erro desagradável. Um barco que está sendo definido para o projeto alvo errado. Então, quando avançarmos e acrescentarmos que a migração vai fazer a sua magia. E então obtemos esse arquivo de migração, que está nos dando todas essas tabelas que criamos inicialmente. tour rápido do nosso arquivo de migração, se você não estiver tão familiarizado, temos um método op e um método de complemento. O outro método basicamente tem código e se você apenas lê-lo como um desenvolvedor C-sharp, como um desenvolvedor SQL, você vê o que ele está fazendo. É criar uma tabela com nome, com essas colunas, com todos aqueles corrigir em cada coluna. Tudo bem? E então o “down “significa que se você desfazer essa migração, essas são as coisas que farão. Ele vai cair as mesmas tabelas. Então, para cada um há adulto. Então, agora que temos nosso arquivo de migração existente, podemos ir em frente e atualizar o banco de dados. Então o banco de dados basicamente diz que se ele não existe, são criados. Se existir, aplicarei as alterações. Não existia. Então ele criou apenas neve. E para verificar e verificar se ele foi criado, podemos ir para SQL Server Object Explorer, expandir e expandir a barra de banco de dados local e Mrs Hill banco de dados local faz o servidor que indicamos. E se você estiver usando um servidor diferente, então você pode prosseguir para esse servidor específico. E quando expandirmos, é uma base, veremos nosso dB de gerenciamento de EHR DV. E se expandirmos as tabelas, veremos nossas tabelas que foram definidas de acordo. Não vimos nenhum perigo. Todas as mesas estão vazias. Mais tarde, quando começamos a construir nossa própria aplicação, podemos ir em frente e olhar para como dados ISI. Mas, por enquanto, esta é a missão cumprida. 20. Implementar controladores finos de API: Nesta lição, analisaremos a adição de serviços de mediador à nossa API. Agora, o contexto para isso é que a mídia nos permite especificar comportamentos em nossa aplicação com base em uma resposta no tipo manipulador de relacionamento. Uma das consequências ou benefícios disso é que podemos enviar um monte de operações pesadas antigas do nosso código de chamada, que neste caso vai ser o nosso controlador. E podemos abstrair isso para outro lugar. Então o controlador realmente sabe que eu construo um pedido e eu enviá-lo para ser tratado. Então, para o contexto, eu tenho na tela o controlador do projeto anterior, que é inspiração para nós refazer este sistema de gerenciamento de necessidades. E aqui você veria que não temos controladores finos, temos controladores gordos. Então eles são controladores, na verdade. Aqueles exatamente o que o nome sugere, controla o fluxo e tudo o que o aplicativo faz. Assim, ele responde às solicitações de dados de um usuário, etc. Agora, no projeto antigo, tínhamos o que chamamos de controladores gordos, ou estamos fazendo tudo dentro do controlador. Mais uma vez, isto funciona. Então não é que não funcione. Se for feito, vamos trabalhar. Mas é o melhor praticado Holman Tenable? Porque se eu quisesse verificar que essas operações estão sendo feitas com sucesso, eu teria um monte de unidade dificuldade testá-lo desta forma porque isso não está em uma união, isso é suficiente dentro do nosso controlador. Isso aumenta a minha incapacidade de testar as partes do aplicativo para ter certeza de que eles estão funcionando corretamente. E aumenta o meu tempo gasto na resolução de problemas e testes de regressão e todas essas coisas. Aqui ele está verificando se algo existe e se ele não existe, ele está retornando não telefone. E então ele está fazendo mapeamento e está fazendo um achado, e então ele está retornando a exibição. Leia Andrew, só quero o mínimo de cores possível sem lógica de negócios. Esta é uma forma de lógica de negócios. Nós realmente não queremos isso em nossa aplicação. Muito bem, aqui está outra situação em que estamos a criar nosso recorde e estamos a fazer demasiado nesta opção. Então, essas são as coisas que queremos reduzir quando falamos sobre como ter controladores finos. Então vamos começar instalando mediador em nossos projetos API. Você sabe o que fazer, você pode apenas clicar com o botão direito do mouse em NuGet. Procuramos o mediador e vamos instalá-lo. Depois de concluir essas etapas. Uma vez que você terminar com isso, vamos em frente e adicionar um novo controlador ao nosso projeto. É um controlador MVC e queremos um controlador API com opções de redirecionamento. Vamos começar com o mais fácil, que é deixar tipos e ir em frente e adicionar. Agora vamos explorar como a mídia vai nos ajudar, certo? Portanto, já temos as boas opções básicas que estão sendo geradas para nós, felizmente. Mas então o que precisamos fazer é injetar nosso objeto mediador em nosso controlador. Então você vai trabalhar no AVC. E então vamos fazer referência a I. Mediador exigirá que tenhamos que usar a instrução, bem como para inicializar esse campo. E então podemos começar a usar essa mídia para se opor às ruas Arcbest ou causar neve. Excursão rápida deste controlador. E neste ponto, é claro, eu estou assumindo que você tem alguma familiaridade com controladores. E por extensão, desenvolvimento de API, quando queremos obter a lista de registros são todos os tipos de licença no banco vão acertar este método que é apenas o recebe seus tipos de licença barra API. Isso é o que se espera chegar até nós, mas todos os tipos de folhas. E, em seguida, cada um desses métodos transportaria para as outras operações crud que são puxa o put, o delete. É para atualizações. Ou se você não está tão familiarizado com o que eu estou falando, eu encorajaria você a ir e verificar meus cursos de desenvolvimento de API para que você possa se atualizar em apreciar plenamente quais são os meandros por trás desses métodos e como eles funcionam . Então vamos continuar para o get de que é esperado para retornar todos os tipos de folha no banco de dados. Vamos ter um código que se parece com este. Nós vamos ter tipos de licença var é igual a um aguarde. Então o método enviar encontrado em nossa mídia para se opor e tudo o que exatamente estamos enviando? Se você olhar para a sobrecarga, ele está esperando um objeto do tipo ou um objeto com os apartamentos são chamados de solicitações, então ele não sabe que tipo de solicitação ele vai enviar o pedido. E a expectativa é que ele vai ter algo que pode ser armazenado dentro de tipos de folhas. Sabe quais pedidos estaríamos enviando? Enquanto salta de volta para os nossos recursos de projeto de aplicativo, deixe tipos e consultas. Vamos ver aqui que temos a solicitação de lista de tipo de folha get, que é esperado para retornar a lista de detalhes do tipo de folha. Então, em nosso controlador de tipos de folha, eu diria que estou enviando um novo objeto de solicitação de lista de tipos. E então vá em frente e inclua qualquer perda usando declarações. E então eu vou ir em frente e alterar o cabeçalho do método para resultados de ação de tarefa assíncrona pública, lista de detalhes folheados. Então agora ele sabe que é esperado para retornar um resultado de ação que tem essa lista de tipos de folhas. Então esta declaração retorna não é mais válido desde não, eu vou estar retornando tipos de folha e olhar para que duas linhas. Contextos. Eu só vou compará-lo com o código antigo ou é a nossa antiga opção teria a variedade de tipos. Teria orquestrado a chamada para as unidades de trabalho para obter os registros, trazê-los diretamente, Buck. E então estaremos realizando o mapeamento porque ele estaria retornando os objetos de domínio quando queremos que as VMs sejam contextos para que seja a mesma coisa que um DTO. E então estaríamos fazendo toda essa operação dentro da ação em si antes de retornar a visão. No novo paradigma, o que estamos fazendo é que estamos apenas deixando a mídia saber que estamos solicitando a lista de tipos de folhas ou manipulador vai realizar todas as operações, está colando todo o mapeamento e a consulta e tudo mais, e ele está retornando apenas os objetos que precisamos saber sobre. Assim, a API nunca interage com os objetos de domínio reais provenientes do banco de dados. Fazemos toda essa transformação antes que ela volte. Então vamos avançar um pouco para onde eu já escrevi o código, mas como de costume, vou passar por ele lentamente e explicar cada linha você possa apreciar completamente o que está acontecendo. Você pode pausar conforme necessário e replicar. E vamos passar juntos de qualquer maneira. Tudo bem, então um ajuste rápido para o HTTP GET Eu tenho retorno limitado sobre, ok, com tipos de folhas. Tudo bem? E você percebe mais uma vez, tarefa, ação resultados lista os cinco dB HL. Então isso está sendo muito explícito quanto ao tipo de dados que ele vai retornar null para o HTTP GET com um ID. Uma vez que eu fiz semelhante, tarefa de código muito semelhante, resultados de ação deixar diabetes. Claro que tem que ser assíncrono. E dizemos que tipo de folha var é igual a e, em seguida, aguardamos o mediador Dotson com o novo pedido. Portanto, lembre-se de que o pedido será tratado. mediador está cuidando dessa parte. Temos que ter certeza de que usamos o pedido correto com base no que queremos. Então, nesta situação, o pedido é obter o tipo de folha bt EverQuest, que é onde ele está recebendo o tipo de folha particular com todos os intrusos e quaisquer outros fundos pendentes ou requisitos que possam estar lá. Para os detalhes. Nós também precisamos dar a ele o valor id que você estará recebendo porque em nosso manipulador, ele vai depender fortemente do ID para saber qual registro precisa ser recuperado. E então retornamos, ok, com o tipo de folha. Agora no post, temos mais algumas linhas e é realmente só eu mostrando como você pode quebrá-lo de qualquer maneira, mas não é absolutamente necessário. Porque da mesma forma que tudo poderia ter sido em 19 e nós apenas criamos o novo objeto aqui. Eu poderia ter feito isso dentro deste aqui, mídia para enviar linha. Em vez disso. No entanto, eu disse var comando é igual a um novo criar comandos tipo folha. Assim, o método post é projetado para a criação. Tudo bem, então deixe-me começar a partir Desire2Learn gráfico BAC, mas eu tinha de mim mesmo lá resultados de ação de tarefa assíncrona pública. Na realidade, você não precisa necessariamente ver qual é o tipo de retorno. Ajuda com a documentação do gueto para se gabar. Então eu colocaria de volta. Independentemente desta situação, a resposta seria um int. Então nós poderíamos ver int, mas como eu disse, não é absolutamente necessário. Então eu vou continuar sem que isso seja necessário agora e mais tarde vamos ver por que teria sido uma boa idéia colocá-lo dentro Então tarefa, ação, resultado, postagem, e estamos fazendo a partir do corpo, e então estamos usando o tipo de detalhe específico para a operação. Lembre-se que discutimos sobre você ficar granular. Deixe isso em geral. Bem, esta é uma situação em que evitaríamos o excesso postagem ficando granular porque, em seguida, quando eles giram, quando eles enviam informações sobre o tipo de folha, o que nós aceitamos através desta opção é limitado ao dentro do tipo que especificamos. Então, ao contrário do tipo de folha detalhe ou tipo de folha BTO, que tem mais detalhes são mais campos que eles criam. O tipo de folha é projetado apenas para aceitar os pontos de dados que sabemos que absolutamente precisamos para que nosso tipo de folha seja criado, então qualquer outra coisa será ignorada. Então, quando formulamos este comando, dissemos novo criar folha de comando, D, comando. Precisa deixar esse objeto detalhado. Então, passamos nesse objeto. E então nossa resposta é relativa ao que o mediador retorna. Nesta situação, nossa resposta foi int, porque era isso que tínhamos dito. Quando você cria o tipo de folha, basta retornar seu ID. Então esse foi o manipulador que projetamos para esse tipo de solicitações. Então, quando retornamos todos k com a resposta, que seria ok com a ID folha. Agora, passando para o put, put é usado para a atualização, mais uma vez está em resultados de ação de tarefa. E então é por padrão ter esse parâmetro ID e mudamos do perímetro do corpo para ser o tipo de folha DTO. Então nós fizemos, nós tínhamos discutido desde cedo que o tipo de folha BTO, nós não ficamos muito granulares com isso. Eu tenho uma tag div atualização, div TO diferente de tudo o resto. Isso é bom. Então, nesta situação, estamos aceitando que todos os possíveis medos podem ser atualizados. E nós definitivamente precisamos da identificação dentro deste objeto, é por isso que estamos conseguindo isso. Na verdade, ele atordoa este ID é opcional. Então eu poderia realmente dizer, eu não preciso de um parâmetro ID. Então, quando você liga para o posto, você não tem que chamar uma identificação. E, em seguida, este comentário seria realmente apenas atualizar os comentários estabelecer uniformidade. Então, o resultado da ação da tarefa, colocar uma hora procurando é o corpo contextos com o tipo de folha DTO. Lembre-se, toda a nossa validação está acontecendo dentro de nossos manipuladores. Então, isso é ainda menos. Menos coisas rasgaram balas aqui. Quando falamos sobre a identificação, a identificação existe? Todas essas coisas estão acontecendo dentro do nosso manipulador, entre o manipulador e são validações fluentes na verdade. E se algo parecer desse lado , toda essa operação falhará. De qualquer forma. Vamos ver como lidamos com falhas mais tarde. Mas, por enquanto, nós só queríamos saber como nossos controladores precisam ser vistos. Então, quando enviamos o comando para atualizar, nós não conectamos o sabão para retornar nada, pelo menos nada útil, certo? Dissemos que a unidade de valor do ponto representava um vazio, então tivemos que devolver algo, mas dissemos: “Ok, você só vai devolver algo arbitrário para dizer que foi bem sucedido. E assim a resposta HTTP que corresponde a um put é geralmente sem conteúdo, que é uma ferramenta para, tudo bem, então podemos apenas retornar que não falamos conosco e a resposta a qualquer variável. Excluir parece semelhante. Excluir leva um parâmetro ID, tarefa, resultados de ação, excluir int id. E, em seguida, temos o comando que apenas leva o ID, e então nós enviar sobre o comando e retornar ou todo o conteúdo. Então, se é que você quer que tudo seja apenas duas linhas, então isso é tão fácil quanto pegar o comando, colocá-lo no mesmo parâmetro. E tudo pode ser duas linhas. Tudo bem, então eu estou apenas mostrando a diferença, a grande diferença entre este controlador que está fazendo tudo que este controlador está fazendo com todo o código, tudo bem, com as edições estavam fazendo validações aqui. Para Excluir, estamos fazendo alguma forma de validação. Novamente, todas essas coisas são nulas, obstruídas antigas em outras partes do aplicativo. E nosso controlador pode fazer exatamente o que deve fazer, que é receber uma solicitação, fazer uma chamada para fazer alguma operação e, em seguida, devolver seus dados. Agora, eis o meu desafio para ti. Vá em frente e conecte os outros controladores para os outros tipos, para os recursos. Então temos tipos de folhas são feitos. Vá em frente e tente as solicitações e deixe alocações. Você pode, é claro, criar opções personalizadas em relação ao que é que a operação precisa realizar. Mas, por enquanto, deixarei você fazer isso. Então eu vou voltar no próximo vídeo. Vamos comparar notas. 21. Terminação de controladores finos: Tudo bem, então este é mais um vídeo de revisão do que um vídeo de escuta. Só tenho algumas coisas que eu quero me concentrar nesta lição que você provavelmente tentou e provavelmente teve programas com um se não então parabéns para você. Então vamos começar com o controlador de alocações de licença, realmente e verdadeiramente, este é um controle que vai ser bastante idêntico ao nosso controle de tipos de licença porque realmente e realmente estamos fazendo operações crud aqui. Estamos recebendo a lista de onde obter por ID. E, claro, se você não o completou, você sempre pode fazer uma pausa e seguir em frente e replicar enquanto me vê passando. Fazemos a mesma coisa pelo correio. Então você vai notar que tudo o que praticamente disse pedidos de licença está percebendo alocação de licenças. Você poderia quase dizer que você poderia ter criado um novo controlador, copiado tudo do controlador de tipos de folha, colado no novo controlador e, em seguida, apenas policiado o tipo de folha com alocação de licença ou tipo com a alocação de palavras. Só estou dando dicas para nós. Você poderia ter feito isso muito rápido e bem eficaz, certo? Porque este é bastante idêntico aos tipos de folhas. Pedidos de licença, por outro lado, tem uma pequena surpresa. E isso é na forma da atualização, certo? Então, mais uma vez, passando devagar o suficiente, eu praticamente são replicadas as opções dos tipos de folhas mais em solicitações de licença. Assim, a maior parte do conteúdo deste controlador é idêntico aos outros dois, com exceção da nossa operação PUT. E se você notar e olhar muito de perto, eu diria colocar operações x2. Então todos os outros apenas em uma única operação, atualize endpoints. Mas então, no caso do pedido de licença, tínhamos criado espaço para dois tipos de atualizações. Um em que é uma atualização regular. E observe que desta vez temos o parâmetro ID no put. E isso é porque nosso comando leave requests pede o ID e por um detalhe, tudo bem. Mas, mais uma vez, esses diferentes sabores são relativos ao estilo que você pensa. Cenário muito mais fácil. Então, só estou mostrando opções diferentes. Não estou dizendo que é assim que deve ser. Você tem as diferentes opções. Use o que é melhor para sua situação e seu projeto. Agora, nesta situação, mais uma vez, temos o parâmetro ID possível com o comando e construímos um DTO de solicitação de licença. No entanto, o cenário de outras atualizações teria apenas um status de aprovação de alteração para nossas solicitações de licença. Então, nesse caso, criei uma aprovação de alteração de ponto final personalizada. Então, para chegar a este, você diz api barra Requests Controller aprovação slush. E eu realmente preciso da identificação. Então deixe-me ir em frente e adicioná-lo à raiz para que ele será alterado aprovação do valor Slashdot ID. Como eu também atualizei a documentação em conformidade. E eu preciso colocar esse parâmetro ID, Buck. Então complicado dito anteriormente, colocá-lo de volta e construir meus objetos de solicitação, tudo bem, ou meu objeto de comando em vez disso. Só estou mostrando todas as considerações que precisam ser feitas. O que no final do dia, nossos controladores são magros e os benefícios disso você pode estar vendo, ok, então três linhas, mas tudo isso funciona ou nos vídeos anteriores, só para que eu possa colocar três linhas aqui. Por que Titus não colocou toda a lógica aqui? Quais novamente, eu entendo completamente porque funcionaria. Mas no final do dia, citação, é muito mais testável e eu não tenho que testar o controlador para saber se eu obteria os resultados deste ponto final. Em vez disso, eu posso ir e testar o manipulador que deveria estar retornando esses resultados. E se o manipulador funcionar , o endpoint funcionará. Então, você sabe, é apenas mudar seu foco de ser mais compacto para ser um pouco mais modular e espalhar o código e a responsabilidade entre mais agrada para que você possa ter uma melhor apreciação ou um controle amargo sobre o que cada componente faz unhedged, todos eles amarrados juntos. 22. Dados de semente em tabelas: Certo, então estamos terminando com nossas operações relacionadas à API. E nesta lição, o que queremos fazer é semear alguns dados padrão em nosso banco de dados. O próximo passo, é claro, seria testá-lo, mas então é sempre bom ter alguns dados de amostra para que possamos fazer as operações de leitura com bastante facilidade e eficácia. Então, para ver os dados em nosso banco de dados, vamos olhar para como realizamos isso com Entity Framework. Agora eu já fiz um e eu tenho os outros dois feitos por um, então nós podemos fazê-los juntos. Mas vamos começar indo para o projeto persistência, adicionar uma nova pasta chamada configurações, e lá outra pasta chamada entidades. E então você vai ter um arquivo de configuração por entidade. Então, praticamente este arquivo de configuração permite que você coloque em qualquer Entity Framework relacionado ou qualquer banco de dados relacionado em vez disso, configurações são padrões ou quaisquer regras que você deseja passar na tabela particular no banco de dados será então todo o código é escrito cortesia de EF Core. Então vamos olhar para o que eu já fiz, e isso é para a configuração do tipo de licença. Então você pode pausar, tirar isso, e então podemos passar pelos pedaços juntos. Então nós temos a configuração do tipo folha e, em seguida, ele está herdando da configuração do tipo de entidade I em relação ao tipo de classe que estamos lidando com, que é o tipo de folha. Então, tudo nesta base de código basicamente vai ser relativo ao tipo de folha. Então, uma vez que você faz isso, você vai acabar com, ele vai pedir-lhe para no parlamento a interface e, em seguida, que iria gerar este stub método para você. Então, dentro deste stub método, vamos ter public void configure. E então nós temos que int. É tudo o que realmente é gerado para você. Assim, quanto mais as partes principais dele, que é o que você estará construindo ou escrevendo, estariam nesta seção do Construtor. Então, diríamos que construtor tem dados. E então nós diríamos deixar tipo ou cria um novo objeto. Então este é um método tem morte é um método que tem chaves abertas e fechadas. E aí dentro vemos novo tipo de folha e então preenchemos um objeto. Então este é o objeto de domínio que estamos vendo seus IDs um, seu padrão é ir para bancos de dados 10 e seu nome é férias. E então quantos você precisar, você pode realmente apenas coma separar cada inicialização de um objeto ou instanciação de um objeto dentro de todo esse bloco. Não, eu não fiz os outros dois. Então eu vou fazê-las do zero. Mesmo que por não, você provavelmente já fez isso com o tipo de folha. Bem, isso é bom. Portanto, para configuração de alocação de licença, é herdar, mas não há instruções de uso em tudo. Então é por isso que você está vendo a linha vermelha. Então eu vou usar ponto de controle usando o Microsoft Entity Framework Core, a referência de domínio, e, em seguida, implementar a interface que gera esse stub método para mim. Mas não há nada lá para eu configurar para a alocação. Eu não tenho um requisito para a alocação no momento. Tudo bem. Então eu não estou vendo nenhuma alocação de licença. Eu não estou mudando nada sobre os padrões na estrutura da tabela. Não estou a fazer mais nada. Então, como eu disse, essa configuração pode ser usada para muito mais do que apenas a propagação de dados. E se você quiser uma melhor compreensão do que ele é capaz de fazer, você sempre pode verificar todo o meu curso Entity Framework Core. Tudo bem, então faremos a mesma coisa para o pedido. E vamos deixar que lá mais uma vez, não temos nenhuma solicitação de licença que precisamos como padrão, mas temos alguns tipos de folha padrão, então isso é bom o suficiente por enquanto. Pelo menos podemos executar a API e fazer solicitações GET nesta tabela e verificar se ela está funcionando. Então, o próximo passo depois de escrever este código seria ir para o nosso console do Gerenciador de Pacotes e precisamos adicionar migração para tipos de licença de propagação. Então, uma vez que você faz isso, chegamos a um arquivo de migração que está nos informando que ele estará inserindo esses dados no banco de dados para nós. Próximo passo, como sabemos, seria atualizar o banco de dados. Ok, ótimo. Então, desta vez não vamos para o banco de dados diretamente para verificar se eles foram criados. O que faremos é testar nossa API. Vejo-te na próxima lição. 23. Analisar o suporte da API Swagger: Muito bem, pessoal, bem-vindos de volta. Então, nesta lição vamos estar olhando para um, testando nossa API e documentando-o. Então, o pool de chaves que engloba ambas as tarefas é chamado Swagger. Swagger é uma ferramenta de documentação de API de código aberto baseada nos padrões de API abertos. Agora ele sai da caixa para cinco projetos de API dotnet. Então, se pularmos para iniciar e rolar um pouco cujo ver aqui que estamos adicionando o swagger Ginn Library, que cria esse doc Swagger com uma informação API aberta. Para que possamos mudar todas essas coisas. Eu posso apenas ver a API de gerenciamento de licença de RH. Dê-lhe um título, dar-lhe uma versão. Você pode adicionar outros nós a ele, descrição do contato, et cetera, et cetera. Então é uma ferramenta muito poderosa. E como eu disse, ele sai da caixa e você não colocou isso lá. E outra parte que você veria está aqui no método configure onde ele diz, se estamos em desenvolvimento, então use swagger e API. Então, se você quiser usar swagger, porque eu sei de corporações que foi usado futebol como sua documentação em produção, então você sempre pode usar este sal dessa declaração if e realmente usá-lo independentemente do seu ambiente. Tudo bem, então você pode ir em frente e fazer essa mudança. Não, vamos executar nossos projetos. Então eu só vou acertar F5 com o projeto API como um projeto de inicialização. E isso resulta em obtermos este belo documento que nos mostra todos os nossos potenciais endpoints e como eles podem ser chamados. Repare que ainda temos a previsão do tempo. Podemos apagar isso depois, mas só estou mostrando que não fizemos muito. Tudo o que fizemos foi configurar os controladores, escrever o código que sabemos que precisamos escrever. Mas aqui está este belo documento que nos mostra tudo sobre a nossa API. Então, se eu clicar em um desses, ele se estende e me mostra exatamente o que eu posso esperar. Então esse endpoint, que é R, esse comportamento api barra deixar alocações, que é o get que obtém todos os registros na tabela de alocações de licença. Vai me dar um código de sucesso de 200. E esta é uma prévia do objeto que estaria ficando fanfarrão. Então, mais uma vez, eu vou sempre voltar aos detalhes e quão granular você começa sobre o que você quer exibir. Observe que neste detalhe particular, temos o ID, temos o número de dias, temos o tipo de folha com seu próprio ID, o nome, e o padrão é, então temos o ID do tipo folha. Então você pode estar olhando para isso e dizer, bem, isso é meio redundante. Se eu já tiver o objeto tipo folha, não quero difícil repetir o ID aqui. E isso seria uma declaração de medo, certo? Então, você sabe, nós não fomos muito granulares com a lista de alocação de licenças DTO. Nessa situação, usamos apenas o novo detalhe de alocação. Então nós podemos estar enviando muitos detalhes são muitos campos nessa resposta. Podemos ajustar isso em conformidade. Então, vejamos os pedidos de licença. Solicitações de licença teriam ID, o tipo de folha, a data solicitada e aprovada é verdadeira. Por que ele tem isso em oposição ao que está recebendo os detalhes que tem muito mais. Então swagger está realmente olhando para nossos tipos de retorno sobre o controle particular como nossas opções em vez. E eu vou pular de volta para o controle para que você possa ver o que eu quero dizer. Lembre-se que eu vou dizer em que há um benefício de colocar o tipo de retorno diretamente em que eu realmente resultado porque saga está realmente usando isso para dizer, ok, este é o tipo de dados que será devolvido deste leilão versus este tipo de dados para essa ação. Ou fora disso, só fará uma suposição. E o, o tipo de retorno ou o fema que você pode ver pode não ser representativo do que realmente está sendo devolvido. Então, esse é um dos benefícios que são remotos disse há benefícios para colocar o tipo de retorno aqui. Esse é um deles. Saga irá inferir os objetos que ele precisa para mostrar o esquema para no JSON. E isso é, pelo menos uma documentação melhor e mais clara para aqueles que estarão interagindo com sua API. Certo, então vamos fazer um teste. Vamos saltar para tipos de folha de barra api. Uma vez que esses foram semeados no banco de dados, devemos, eu espero pelo menos dois registros depois que tentamos disse. Então vamos acertar esse ponto final para experimentá-lo e executar em. O que eu vou fazer é definir um ponto de interrupção no controlador e no manipulador que esta operação deve atingir. Então, quando eu executar para 2Ts, o controle ou a opção em vez disso, certo? Lembre-se que é ele vai mediar um Datsun e símbolo com que pedidos não, eu estou pressionando F5 e então ele vai bater o próximo ponto de interrupção, que é o manipulador. Então você vê quando de controlador para manipulador e onde a toda a magia está realmente acontecendo dentro do manipulador e o manipulador, temos o nosso repositório sob mapeador. Ambos inicializados injetados. E, em seguida, no manipulador, realizamos a consulta e, em seguida, retornamos a versão detalhada dos dados. Tudo bem, então eu só vou apertar F5 novamente e permitir que ele complete sua operação. E então swagger, em seguida, nos mostra os dados que vêm de volta do banco de dados. Lá vamos nós, chamado férias padrão é ID1, et cetera, et cetera, et cetera. E da mesma forma, se eu for para o get e eu tentei tote, então ele me permite passar no ID. Então eu vou passar em ID1, executar, e então ele me traz o cartão do Wanderer com o ID um. Agora o futebol nos permite fazer todas as operações crud, pelo menos teste sempre endpoint que temos colocado para fora. Então vamos tentar outro onde vamos criar. Então observe a diferença entre este esquema e o esquema sendo retornado pelo detalhe via gets, direita. Este tem o ID, o nome, o padrão é este só tem nome nos dias padrão. Isso é porque, é claro, estamos usando um detalhe diferente com escopo limitado. Então, pelo nome, eu não vou mudar nada aqui. Na verdade, eu só vou colocar, deixar esses dados padrão. Vamos executar e, em seguida, olhar para o que temos. Recebemos um erro 500. Tudo bem, por que chegamos ao erro 500? Vamos lê-lo atentamente. Então lembre-se do que vamos colocar. Nós não mudamos nada. O nome teria sido string e o padrão, estes teriam sido 0. Se você se lembrar cuidadosamente, tivemos a validação de configuração para ver que o padrão é nunca deve ser menor do que um. Então o que estamos vendo aqui é um erro 500 porque a API, eu não sabia como lidar com o fato de que ele está recebendo uma exceção todo o caminho do manipulador. E essa exceção é de exceção de validação de tipo. Isso parece familiar? Certo? Então, ele está apenas nos deixando saber que houve um erro e essa exceção foi lançada. Não temos nenhum tratamento de exceção integrado. Então tudo o que está sendo jogado, swagger não sabe o que fazer é apenas nos mostrar o que o aplicativo deu a você, o que é bom. É para isso que ele foi projetado para fazer no momento. E vamos refinar isso à medida que avançarmos. Mas a questão é que isso está funcionando. Então, se eu colocar em algo mais significativo e desta vez eu vou colocar em licença de maternidade com dias padrão de 90 executar novamente, então nós obter de volta o nosso código de resposta de 33 seria esse ID. Então eu posso voltar para o get testlet 3 é executar. Lá vamos nós. O padrão da licença de maternidade é de 90, etc. Então eu estou apenas mostrando a vocês o quão útil swagger é para você ver o documento para a API e para testar sem ter que instalar qualquer outro aplicativo. Dito isto, geralmente uso o Postman para fazer meus testes de API. Mas para o propósito deste curso, Swagger é perfeito e serviu o seu propósito. 24. Testes de unidade - visão: Sabemos que terá um grande portal para aplicação construído. Nós desenvolvemos a maior parte do que precisa estar lá para a fundação. Nós configuramos a API e testamos até certo ponto onde vemos que ele está realmente se comunicando com o banco de dados e está trabalhando arte. Mas então, como vimos e discutimos mais de uma vez, teste é uma parte muito importante do desenvolvimento de aplicativos. Então, nós apenas entramos em erupção testando a API Andrea para fazer isso manualmente, onde estamos realmente colocá-lo na ferramenta de teste para a API enviada. E então vemos que ele foi submetido e tudo mais. E estávamos confiantes de que nosso código está funcionando. Mas então imagine uma obrigação muito maior com muitos mais pontos de contato. Nós só testamos um ponto de contato, só sei, mas então imagine testar 50, 60 pontos finais. Você não tem tempo nem capacidade para isso. Seria uma perda de tempo tentar passar por tudo isso. É por isso que vamos estar olhando para testes de unidade e como ele pode nos ajudar a automatizar essas verificações para garantir que nosso código está fazendo o que nós projetamos para fazer. Agora, em poucas palavras, teste de unidade é o código que testa o código. Sim, isso mesmo. Vamos escrever código para testar o nosso código. Esta é uma das razões pelas quais as pessoas se afastam de um próton porque algumas pessoas vêem isso como uma perda de tempo porque então você estaria escrevendo código duas vezes. E que algumas pessoas veem faz completamente essencial porque eles não confiam em código que não foi testado por um teste de unidade. Há pessoas que se inscrevem para ambos os extremos. Não sou necessariamente um deles. Acredito que as ferramentas são usadas dentro do contexto para o qual foram projetadas e no momento em que você está pronto para elas. Então, nesta situação, é definitivamente uma ferramenta que queremos porque queremos ter certeza de que nossos manipuladores estão se comportando de forma consistente com o que nós os projetamos para fazer. Nós também queremos escrever o que vamos chamar de testes de integração, que será apenas a interrupção entre as diferentes camadas de nossa aplicação. Teste de unidade. Mais uma vez, ele funciona muito bem em economizar tempo. A longo prazo. Leva um tempo para escrever os testes. E o nosso teste é tão bom quanto a forma como está escrito. Mas, em seguida, existem estruturas lá fora que podem nos ajudar a garantir que temos testes de qualidade e que estamos tendo cobertura total para a nossa cotação, outra coisa que o teste de unidade nos ajuda com a documentação. Para que ele pudesse deixar documentações e comentários por todo o seu código. Mas testes bem escritos podem realmente mostrar nosso indicar-lhe o que bits de código devem estar fazendo aqui e ali. Então, algumas pessoas realmente usam testes de unidade como uma forma documentar seu código de forma não oficial e não oficial. Agora, em geral, existem três tipos principais de testes que normalmente tratamos. Um é o teste de unidade, o outro é o teste de integração, quais novamente, testa a interação entre as camadas. E, em seguida, testes funcionais que são geralmente como UI enfrentando para testar o que a experiência do usuário deve ser. Então, quando voltarmos, vamos olhar para escrever nosso primeiro teste de unidade e estaremos configurando nosso projeto de teste dentro da pasta de artistas. E estaremos testando nossa lógica de aplicação, também conhecida como os manipuladores, para ter certeza de que eles estão fazendo o que pensamos que estão fazendo. 25. Escreva testes de unidade para o código de aplicativo: Oi caras. Então vamos começar criando um novo projeto de teste para a nossa camada de aplicação. Então, em nossa pasta de teste, em nossa solução, vamos criar um que eu chamei de aplicativo de gerenciamento de RH mina que testes de unidade. Então, desde o início, seria novo projeto e estamos procurando um modelo de projeto x unidade. E então queremos dar-lhe o nome, é claro, e isso precisa ser feito às cinco. Certo, então uma vez que você tenha feito tudo isso, então você pode pular para NuGet e nós queremos instalar MOQ ou simular e astuciosamente. Então Mach vai nos ajudar a criar zombos da nossa persistência. Existem repositórios e outros objetos que são necessários para simular o que nosso aplicativo ou nossos manipuladores estão realmente fazendo. E não deveria estar nos ajudando a afirmar que isso é o que esperamos desse tipo de operação. Agora eu já fui em frente e configurei uma estrutura de pastas para você. E eu acho que eles estão mais interessados em coisas para empilháveis do que para você sentar e me ver digitando. Então eu fui em frente e preparei alguns dos ativos de antemão, mas como de costume, vamos passar por eles lentamente e juntos para que possamos entender completamente o que está acontecendo em cada um, em cada passo. Neste projeto, temos duas pastas pelo menos para não, Então somos 14 tipos de folhas. Um para os cigarros Mach será a mangueira dos repositórios simulados. Agora você tem duas opções. Claro que você pode ter um arquivo por repositório simulado, pode ter um arquivo de repositório simulado e ter várias instâncias lá. Isso é com você agora eu estou usando apenas um arquivo e o que só terá um teste para executar. Então, se você tiver 50 coisas são recursos que você precisa executar. Nossos manipuladores são recursos que você precisa executar testes de unidade contra, então provavelmente seria melhor apenas dividi-los em arquivos específicos por conjuntos de dados que você gostaria de ter uma zombaria antes. Então vamos para as brincadeiras primeiro. Então eu já meio que passou e configurar um método neste, neste arquivo. Então vamos discutir isso juntos. Então eu fiz isso uma aula estática pública e eu estou chamando um repositórios simulados. Mais uma vez, eu poderia facilmente ter sido muito específico e dizer algo como mach deixar tipo repositório. Na verdade, vou pegar minha própria submissão e fazer assim. Então nós temos este arquivo, particularmente para Mach leave type repositório, o Toronto Newcomb buck bem, simulação alavanca repositório de localização, et cetera, et cetera. Então Mach deixar tipo repositório é uma classe estática e tem um método estático nele. Este método é projetado mais uma vez estático público. E reparem que está decorado com esta palavra-chave simulada, que nos vem cortesia da biblioteca simulada, certo? E isso nos permitirá zombar de qualquer tipo de repositório aqui. Então eu quero um repositório de tipo folha simulada zombando do repositório tipo elif. E então eu estou chamando o método obter repositório tipo folha. Agora, este método vai ter uma lista de objetos tipo folha. Você pode ser completamente fictício com isso. Não há nada a dizer que eles devem se parecer com o que estaria no banco de dados. Não há, não há nada em particular sobre isso é apenas uma lista de objetos semelhantes ao que esperaríamos do banco de dados ao lidar com os objetos de tipo de licença de domínio, certo? Então eu só tenho que, você poderia ter dez, você poderia ter 15 ou 20 teria mais baseado em seu cenário e o que você precisa testar. Você pode precisar de mais, você pode precisar de menos do que isso, mas isso é com você. Então, só vou prosseguir com dois. Certo, então inicializamos nosso repo simulado. Então eu vou dizer que o grupo ambiental era igual ao novo Mock. E os tipos novamente é eu vou deixar o repositório de tipos. Então, até que façamos tudo isso, você estará vendo nossa linha vermelha ao lado desse método porque ele está dizendo que nem todos os caminhos retornam um valor porque precisamos retornar a simulação. Então, antes de devolvermos o Mach, precisamos configurá-lo. Portanto, dados de amostra estão presentes. O novo objeto do repositório Mott está presente. Então agora precisamos literalmente chamar a configuração de ponto de repo simulado. Usamos uma expressão lambda onde nos dá acesso aos métodos que teriam sido dentro do repo original. Então, se queremos testar o método get ou pelo menos configurar, eles recebem todos os meios metódicos que quando um teste está chamando este repo simulado e queremos invocar um teste contra o código que está usando isso obtém tudo. Passará no repo simulado. E então estamos sentados, eles têm todo o método. Então este é um bloco ou é uma armadilha. Nossa expressão lambda R-dot guetos L, Isso é tudo em um bloco, e então retorna a lista de tipos de folhas. Então, qualquer código que faça nascer a zombaria vai chamar a saída para este repositório, a simulação. Que será invocado no teste, irá retornar essa lista de tipos de folhas. É com isso que ele vai lidar. Tudo bem, então você pode, você está no controle total de seus dados de amostra. Tendem a T faz para se levantar e começar com este Misha com os dados de amostra, mas é tudo por uma boa causa. Não, o próximo seria configurar o que acontece quando chamamos o método add. Tudo bem, então configuração de pontos azuis zombaria, mais uma vez aquele bloco lambda onde chamamos o método add. Então tudo isso é um bloco. E eu vou apenas explicar o que está acontecendo aqui. Estamos vendo o nosso ponto-ponto normal, mas o método add por padrão precisa um objeto do tipo folha entidade. Tudo bem, então vou deixar ligado. Tudo bem, então nós temos que passar uma entidade tipo folha para o método add. O que estamos fazendo aqui é que estamos fazendo uma afirmação que você só pode chamar este método quando um objeto do tipo, tipo folha está sendo passado dentro. Mais uma vez, este pode ser um objeto fictício. Só precisa ser do tipo, tipo folha. Não precisa ter todos esses dados e nada de especial. Tudo bem, então se estiver fora do tipo de folha, então esse método pode ser chamado. E ele retorna é afundar um objeto. Então, o que vamos fazer é fazer um delegado para dizer depois de obter o objeto do tipo folha, e então temos nossa expressão Lambda ou método bloqueá-los, basta movê-lo para a próxima frase para que você possa vê-lo mais claramente. Então dizemos deixar tipos, que é a nossa lista de pontos adicionar. Então, durante o tempo de vida do teste, sempre que alguém chama o método add e passa em que objetos de tipo folha, vamos apenas adicioná-lo à lista de tipos de folhas e em troca esse tipo de folha particular. Então, isso é apenas manter a configuração funciona e, em seguida, com base no cenário ou teste de configuração Fourier pode diferir. Então você percebe que eles obtêm toda a configuração parece bastante diferente do, o, desculpe, eles adicionarão a configuração. E, em seguida, a excluir um milhão diferente e, em seguida, a atualização um milhão de forma diferente. Então agora estamos apenas sentados ou para adicionar e obter tudo. E depois vamos em frente e devolvemos o repo simulado. Então, depois de devolvê-lo, aquela flecha iria embora, e isso é o que este método é quatro. Então, depois de ter replicado tudo isso, você pode simplesmente, tenho certeza que você está pausando e escrevendo não, mas espero que você tenha uma melhor compreensão de como o MAC nos ajuda a simular dados sem realmente tocar no banco de dados. Agora vamos saltar para o nosso primeiro teste de unidade. Agora este vai ser consultas, pastas. Deixei guias, comandos e consultas. Tudo bem, então os manipuladores que estão fazendo consultas serão testados dentro de consultas vai olhar e comandos nos comandos. Então, o primeiro que temos é o teste do manipulador de solicitação de lista de tipo de folha get. Está quase cheio, mas pelo menos ninguém pode cometer um erro quanto ao que está sendo testado. Em vez deste arquivo, você pode ter vários testes, é claro, mas, em seguida, neste cenário que nós só queremos ter, nós só precisamos de um teste realmente para o manipulador lista de convidados ou não, deixe-me apenas orientá-lo através do que é acontecendo dentro destas primeiras 10 linhas. Bem, precisamos saber que precisamos de mapeador automático e sabemos que precisamos de um repositório para interagir com o manipulador, certo? E eu vou pular, não terminei escrever os testes que vamos fazer isso juntos, mas eu queria apenas demonstrar o que acontece quando tentamos instanciar nosso manipulador, estamos recebendo um erro. Por quê? Porque um 100 está esperando um parâmetro do tipo I elif type repositório e outro parâmetro do tipo high mapper. Agora este é um teste unitário que não pode simplesmente injetá-los. Isso é 12. Não queremos injetar nele. Quero dizer, provavelmente poderíamos, mas não gostaríamos porque estamos lidando com zombarias, certo? Não quero injetar no repositório de tipo elif real porque isso vai falar com o banco de dados. Não queremos que nosso teste de unidade fale com o banco de dados. Só queríamos simulá-lo. Então o que eu fiz foi inicializar ou declarar ou outros dois campos privados, um para o mapeador e outro para o nosso representante simulado, certo? Então, mach privado somente leitura de tipo elif pessoas de repositório tipo tipo II. Então temos o nosso construtor. Então, no construtor, uma vez que este teste é invocado para sobre para inicializar nosso barco zombaria local para ser igual a chamar a classe de repositório tipo folha simulada ponto obter método de repositório tipo folha. Tudo bem, para que não, vamos fazer tudo isso e devolver as pessoas zombarias para usar neste teste. Agora, para o mapeador, nós mais uma vez, não estamos injetando nada. Portanto, precisamos deste mapeador para saber de todas as configurações de mapeamento reais que existem em nossa aplicação. Então, o que vamos fazer é inicializar objeto de configuração do mapeador. Seja uma nova configuração de mapeador de mercado. E então temos uma expressão lambda aqui com nosso bloco de objeto dentro do qual vemos lambda Tolkien ponto adicionar perfil para o perfil de mapeamento. Depois de configurar o perfil de mapeamento e a configuração, então podemos saber apenas passar que não fez. Então dizemos mapeador é igual a mapeador. O ponto de configuração cria um novo mapeador usando essa configuração. Então, ao todo, nosso mapeador aqui no artista realmente é representativo do mapeador real no aplicativo. Então, todo o método abaixo sabe tem tarefa assíncrona pública obter lista de tipo de licença. Então somos específicos, sabe o que exatamente estamos testando? Onde testar para o método que obtém a lista de tipos de folha. Ele é decorado com este atributo fato porque isso é o que está dizendo a obrigação de que este é um teste unitário. Então este é um ditado: “Ei, o que quer que aconteça aqui precisa ser um combate. Quaisquer afirmações aqui precisam ser passadas. Se eles não passarem, então este teste falhou. Agora vamos realmente interagir nas centenas, assim são os testes em vez. Então dizemos manipulador var é igual a novo. E então eu estou instanciando os 100 que eu desejei o teste neste método. Observe as linhas vermelhas porque requer nossa ondulação simulada ou alguma instância de um repositório tipo elif. Então, Bull zombaria nos dá um objeto simulado, mas então eu posso obter a citação real unaspas objeto real através MLK repo dot objeto. Próxima parada, precisamos do nosso mapeador. Tudo bem, isso parece bom. Em seguida, queremos realmente testar a chamada de método. Então eu vou dizer var resultado é igual ao manipulador ponto punho. Tudo bem, porque havia manipulador tem esse método chamado identificador e requer um novo objeto ou requer os objetos de solicitação. Então precisamos passar em um novo objeto do objetivo. E eu só vou tirar tudo isso fora e usa a inserção, a instrução usando. Lá vamos nós. Para que não tenhamos um todo desse texto. E depois disso, ele também precisa de cancelamento. Tolkien, tudo bem, então contra coleira em lata ou eu posso simplesmente passar em cancelamento Tolkien linha pontilhada. Tudo bem, então este ônibus que entrou, ainda assim este derramamento vermelho e inclui quaisquer referências faltantes. Lá vamos nós. Então, estamos apenas vendo chamar isso. Não estamos passando nenhum token de cancelamento. Somos mandões e esse novo objeto, então não precisamos necessariamente ser. Então Mach é realmente só para isso, o topo. Tudo bem? Não, podemos ver um resultado. E se você olhar para o tipo de dados para resultados, oh, bem, precisamos esperar por isso. Desculpas. Se você olhar para o tipo de dados para o resultado, ele é realmente lista. Sim, lá vamos nós. Portanto, o tipo de dados para o resultado é uma lista de tipo folha DTO. Então é fácil o suficiente para portas declarações e dizer, Ok, bem, se os cones são maiores que um, então isso ou algo assim, apenas para ter certeza de que nós temos de volta mais de um porque a lista, então nós devemos voltar um ou mais. Mas então, no final do dia, podemos sentar e pensar em todos os tipos de cenários e assim por diante que podemos ficar sobrecarregados. Então é por isso que temos o quadro deve nos ajudar. Então eu posso dizer resultado dotplot. Lembre-se que isso é realmente apenas coisas listadas. É só uma lista. Mas fui para o tipo deve estar fora do tipo porque eu quero ter certeza de que estou recebendo o tipo de dados correto. O tipo de dados que esperamos do nosso manipulador para esta chamada específica seria a lista. O tipo de dados seria lista de detalhes do tipo de folha. Então eu vou ver e conhecer linhas de mandarim por enquanto. Vamos trabalhar nesta parte. Deixe o tipo DTO. Tudo bem? Não, quando eu faço isso, há pura linha Larry porque deveria ser do tipo, você provavelmente nunca viu isso antes. Então, se eu controlar WC usando em breve, modo que é onde ele não deve ser entra em jogo. Isso nos ajuda com nossas afirmações, com nossas suposições sobre o que deve acontecer. Vou em frente e colocar a declaração de uso para o DTU também. Mas esse é o ponto que eu certamente vou. Então eu invoquei o manipulador, eu executar um comando ou executar uma operação, obtive um resultado. E então eu estou vendo que os resultados devem ser do tipo, tipo folha DTO. Então essa é uma afirmação. E vamos ver o que temos Kinsey resultado ponto e o início, começar a digitar Se eu vou ver todos os possíveis, certo, todos estes. Nossas possíveis coisas que podemos afirmar ou não deve ser, devem estar ao alcance, devem estar em ordem. Todas essas coisas são coisas que você pode verificar. Então eu posso ver deve ser e dizer T2 porque eu sei para os meus dados de teste que o tiro, oh desculpe. Mais contagem de pontos C deve ser. Lá vamos nós. Tudo bem. Então isso deve ser é apenas dobrado em qualquer outra propriedade ou o próprio objeto. E ele permite que ele obtenha a afirmação para qualquer cenário que espera. Então saiba que já dissemos isso. Deixe-me escrever para o projeto e dizer executar testes. E isso nos dará esporo autista, que então fará o teste e nos mostrará o passado. Tudo bem. De modo que um e quatro, se deve ser dois. Não, eu sei que coloquei dois, mas digamos que eu disse cinco e refaça o teste. Em nenhum lugar obtendo falhas. E se eu expandir isso um pouco, quem vê deve deixar afirmação deve ser cinco, barco era dois. Então isso significa que se algo mudou no meu código e ele busca em massa em, eu sei que meu código deve retornar em todos os momentos, mas então algo genes. Digamos que não mudei o teste. Eu sei que é também. Certo. Mas então se eu colocar em um item mãe. Tudo bem, então é aqui que a modificação do código entra em ação. E sim, isso é tudo estatístico, mas mais uma vez, estamos falando de sonares. Então maternidade ou se eu mudar o código que deveria ter retornado para um, deve sempre voltar para 18, introduzir algo. Não, está voltando três. Meus testes de unidade apenas executando ele vai saber me dizer quando algo mudar. Então deixe-me apenas reexecutar o teste de unidade. E a minha afirmação ainda são dois, mas depois três dólares de jogo. Então, de repente, eu sei que há algum inseto no manipulador com quem estou lidando ou porque algo deu errado. Então isso é o que o teste de unidade traz para a mesa. Agora vamos criar o nosso teste manipulador de comando tipo de licença são. E assim, em vez da pasta de comandos, você pode ir em frente e configurar esse arquivo. E ele vai parecer bastante semelhante ao tipo de folha get. Temos o mesmo repositório Mach sendo usado. Temos o mesmo procedimento de inicialização sendo usado. E então temos teste, que é a corrente que, claro, com o fato e a tarefa onde vemos criar tipo de folha. Então nós invocamos o manipulador, que é o manipulador de comando do tipo de folha, cantando É os objetos conforme necessário, e então nós temos os resultados. Então, o nosso resultado vai vir do nosso manipulador alimentar ponto manipulador criar comando tipo folha. E lembre-se de que nosso comando de tipo folha para criar requer um BTO vitalício. Então isso significa que precisamos de algum objeto aqui para passar nulo, você tem duas opções. Você pode criar os novos critérios de objeto neste manipulador e usá-lo. Mas, em seguida, se você tiver vários testes, você pode apenas criar um objeto de folha tipo D2 e usá-lo para vários testes. Então eu vou usar a segunda abordagem onde eu vou ter meu privado somente leitura deixar que DTO e então eu vou inicializá-lo no construtor. Algumas pessoas depois de um tempo, eles têm tantos ativos sendo inicializados que este construtor cresce muito grande. O que eles fariam é talvez farm ETL para outro método que eles chamam como inicial, configuração inicial ou inicializar. E então eles fazem todas essas inicializações lá. E, às vezes, os ativos são realmente compartilhados entre testes. Então, o que eles fariam é colocar tudo em um arquivo totalmente diferente, como uma configuração de ponto crass, direita Deixar configuração de teste tipo. Isso só irá em frente e retornar todos os objetos necessários. Portanto, não há ambas as maneiras, mas estes não são grandes testes. Só queremos entender o conceito antes de pensarmos em obstruí-lo demais, certo? Então nós temos toda essa configuração e nós temos nosso detalhe tipo folha que precisa ser passado dentro Então oh desculpe, eu estou recebendo esta área porque é o tipo de folha criar BTO, desculpas. Então deixe-me consertar esse tipo de dados e então estaremos prontos para ir. E lá vamos nós. Tudo bem, e claro que não há identificação nessa. Certo, então vamos ver o que precisamos afirmar neste caso. Primeiro, quando adicionamos uma nova ferramenta de tipo folha, nosso repo simulado, então o cone deve aumentar, certo? Da mesma forma quando adicionamos ao nosso banco de dados, se houvesse dez, sei que há 11. Então lembre-se em nosso repo simulado, nós tínhamos configurado o método add que deve tomar qualquer tipo de licença e deve adicioná-lo à lista. O que significa que se eu fosse ligar para a lista ou para pegar tudo. O repositório logo após uma operação de adição, então deve haver mais um arquivo, então há nulo, mais um registro e há no momento, certo? Então, há três nulos. Deixe-me primeiro a atualização esta afirmação para dizer três. E então eu vou chamar o repo simulado. Então eu vou dizer tipos de licença var. Fui consultar o repo para Khomeini. Então, é claro que estamos fazendo o simulado repo dot objetos pensamento, e então nós podemos apenas obter o fica tudo. Então, quando invocamos ainda, tudo o que sabemos exatamente o que estamos recebendo. Vamos pegar essa lista. Então eu posso fazer meus resultados pensei que deveria ser. E sabemos que estamos retornando os valores de ID. Então, depois de chamar o create Tumblr para o tipo de folha, ele deve ser do tipo int, right, então essa é a nossa primeira afirmação. E então eu vou dizer também que tipos de folhas ponto, ponto deve ser. E eu vou me certificar que diz quatro porque sabemos que estamos começando com três nulos após a chamada, deve ser para. Agora, antes de fazer o teste, vou renomeá-lo para parecer um pouco mais útil, certo? Então crie, crie testes de tipo folha. Mas o que então você pode ter vários testes são humanos criar tipos de folha de teste para o que acontece quando é teste inválido para o que acontece quando é teste válido para o que acontece quando os valores são valor particular e você tem um regra de negócios em seu trabalho deve se comportar desta forma ou daquela maneira com base na natureza do que está sendo passado lá. Tantos cenários, não consigo me sentar e pensar em todos os cenários, mas estou apenas dando a você o quadro sobre o qual você pode formular seus testes. Então este teste é, é uma afirmação de que sempre que um tipo de folha válido é adicionado, Este é o comportamento esperado. Então eu vou saltar de volta para o nosso manipulador faz para que possamos entender, novamente, o propósito de testes de unidade. Então testar que precisamos Buck, isso é fácil. Ok, sim, nós temos o repositório MLK onde apenas consulta no repo simulado, o manipulador deve fazer uma coisa qualquer maneira que é devolvido o que está no repo, tudo bem. Mas, em uma situação em que temos vários resultados em nosso manipulador, queremos testar para cada resultado. E então você provavelmente pode dividi-lo no bom teste e no exame de sangue. Isso fica a seu critério sobre o que você deseja garantir que você tenha cobertura para os possíveis resultados. Porque se as regras de negócios mudam, se um desenvolvedor entra, altera a declaração if, mesmo que acidentalmente, então um dos resultados mudará e você quer pegar isso o mais cedo possível. Então, em nosso comando create leaf type, e lembre-se que estamos fazendo alguma validação aqui, certo? Então nós validamos o tipo de folha e, em seguida, lançamos uma exceção. Quando não é válido. Então, se for válido, passamos e devolvemos o ID. Então nós testamos isso já é. E vemos onde adicionar a coisa realmente traz de volta mais registros. Se fôssemos ao Git Repo. E isso é bom, mas precisamos testar o que acontece quando dados ruins entram em certificar-se de que eles são tratados corretamente de acordo com nossas regras de negócios. Certo, então foi aí que fizemos as afirmações. Nós afirmamos que se eu receber um objeto de solicitação inválido com um tipo de folha inválido D deixar tipo solicitação DTO folha ab initio, desculpe, que devemos obter uma exceção ou devemos obter certas coisas em sua resposta com base em como você escreveu seu código. Isto é o que deve acontecer. Este cenário é o MIT. Observe também que porque estamos na unidade dois, CO começar a ver quantas referências sobre quantos testes estão passando para o seu código. Então você sempre pode saber que você está no verde ou você está no âmbar ou verde ou você não está no verde quando se trata de passar os testes. Então eu vou saltar de volta para o nosso teste e eu adicionei outro teste para o tipo de folha inválida adicionado. Certo, então temos o mesmo código onde montamos nosso manipulador, certo? E então, mais uma vez, isso está repetindo. Então o que algumas pessoas fazem e o que eu costumo fazer às vezes é mover esse código repetido para ser um campo privado e inicializado no construtor. medida que o arquivo de carvão de teste cresce, você pode querer cultivar algumas partes dele porque não queremos ter que fazer isso toda vez que você tem um teste, você tem que inicializar. Então é o mesmo manipulador de comando que vamos usar com um repo simulado C e o mesmo mapeador. Então, depois de sentar no repo simulado, eu sou o mapeador. Podemos inicializar nosso manipulador para pegar esses objetos. Então o artista parece, bem, temos uma linha a menos com que nos preocupar, certo? Então dizemos manipulador de sublinhado, conta de data e hora, e seguimos em frente. Então, neste novo teste, eu vou pegar meu tipo de folha DTO e eu vou torná-lo inválido. Então lembre-se que inicializamos para ter 15 dias e esse nome. Mas então nós sabemos que enquanto estamos testando para ele, se eu deixar tipo alguma vez veio com isso, então ele deve ser inválido, certo? Então, vamos apenas torná-lo inválido. E então eu vou fazer algo um pouco diferente. Não, então estamos testando uma exceção. Tudo bem, então eu vou dizer exceção de validação e x é igual a 0, deve. Então, obtemos uma classe estática chamadas não deve lançar uma exceção de validação do coletor. E então abrimos parênteses e você pode abrir e fechar. E, em seguida, em vez de que você diz assíncronos delegados seta Lambda. Agora vamos para os nossos pesos, a chamada do manipulador passando os detalhes. Então é literalmente apenas este nove que estamos colocando dentro de que deve lançar método assíncrono. Então, no final, podemos testar para obter todos os tipos de folhas. Então nós vamos para as folhas nós, lembre-se que fizemos isso aqui em cima e dissemos que ele deveria saber antes. Então, depois de uma operação inválida, ainda deve ser três, certo? Então é isso que somos área distinta. Estamos nos certificando de que isso não entrou em nosso conjunto de dados de repo simulado. E então eu também posso ter certeza de que a exceção não deve ser nula. Então esta é a minha maneira de garantir que uma exceção fosse realmente trono. Então agora que eu fiz tudo isso, e quando você está testando alguns dias você vai ter o feto. Então, quando você é preenchido como é ou porque você precisa refinar o teste para ter certeza de que você está testando a coisa certa ou você está, você leu o teste e você está apenas interagindo e ele está falhando porque seu código não está passando o teste. Tudo bem, então duas partes olham para fora. Então, agora que eu fiz tudo isso, vamos em frente e fazer um novo conjunto de testes. E eu tenho recebido todas as luzes verdes em todos os lugares. Assim, o tipo de folha inválida adicionou todas as asserções passadas, que significa que ele corretamente não adicionou ao repositório e lançou a exceção porque a exceção não era nula e a válida foi adicionada com sucesso. E então, é claro, recuperamos as coisas na ondulação corretamente. Certo, então podemos fechar o Explorador de Testes, e foram os carrapatos verdes aqui. E então, se olharmos para trás em nosso código, o que estava vendo campo é não ver passagem. Tudo bem, então você pode ver quantos testes estão fazendo referência a este método manipulador particular neste comando. Então essa é uma visão geral rápida e suja dos testes de unidade e como isso pode nos ajudar com nossa cobertura de código. E cordial, é claro, o vermelho embora testes para seus outros manipuladores e explorar como os diferentes cenários podem ser testados para. 26. Configurar o ASP.NET MVC: Certo, então estamos configurando nosso projeto neste novo módulo. E o que vamos usar para o nosso projeto de interface do usuário é o ASP.net Core Web App, MVC. Assim, nosso aplicativo cliente ou UI poderia facilmente ter sido construído com qualquer tecnologia capaz de consumir uma API RESTful. Então, temos nossa API que já configuramos. Mas quando vamos criar este cliente, poderíamos ter usado vista angular, reagir ou larva ou blazer, qualquer um destes. Mas eu realmente vou ficar com o MVC porque é raro que você realmente vê um MVC até ser o consumidor de uma API. É geralmente o tudo em um de qualquer maneira, que, eo projeto original já foi built-in MVC. Então nós vamos tipo de manter essa sensação MVC para ele. Sem problema. Mas, em seguida, a arquitetura subjacente já foi eviscerada e configurada. Então vamos em frente e você pode apenas procurar MVC. E lembre-se que é um ASP.NET Core Web up, não o aplicativo Web ASP.NET. Certo, então você aperta o próximo, você dá o nome, que, nesse caso, estamos chamando de h i dot leave management dot MVC, e estamos usando um projeto dotnet 5. Você também pode habilitar a navalha no tempo de conclusão enquanto estiver aqui. E então você pode apenas clicar em criar. Agora, uma vez que isso é feito, você vai acabar com este projeto, que é o modelo padrão MVC caldeirão padrão para um aplicativo MVC padrão para dotnet Core. Você verá que ele se parece muito com nosso projeto de API, exceto que ele tem mais algumas pastas como views e modelos. Will MVC Model-View-Controller. E então temos o mesmo arquivo de inicialização, o mesmo arquivo program.cs, as configurações do aplicativo. Todas essas coisas são um tipo de apelos comuns. E temos a pasta raiz ww www, que tem todos os quatro estáticos. Então, se você já está familiarizado com MVC onde você não tem nenhum problema, mas eu vou tentar o meu melhor para ser o melhor para ser o mais detalhado possível com todas as mudanças e o código que precisa ser escrito e como tudo se une. Então, quando voltarmos, veremos como podemos começar a integrar nossa API em nossos clientes. 27. Use o NSwag para código cliente API: Tudo bem, então nós somos fanfarrão e artista para ser é configurar nosso aplicativo cliente para consumir nossa API. Então, já criamos a nossa aplicação MVC e temos a nossa documentação API na forma do noch sogar. Então vamos usar n swapped para nos ajudar a gerar, é literalmente gera o código que, que nos ajudaria a consumir esta API. E entre swagger e em swag, você verá que em poucos cliques, em poucos minutos, teremos todo o código, ou pelo menos a maior parte do código necessário para estabelecer comunicação entre o cliente e a API. Então, passo 1, traga sua documentação do Swagger e então você pode ir para o arquivo JSON que ele gera clicando neste link, que irá trazer este arquivo JSON, que está basicamente alimentando esta tela que estamos vendo aqui. Então a próxima coisa que eu quero que você faça é ir ao Google ou Bing e encontrar a página do GitHub para n swag studio. Então você pode baixar e instalar isso e está bem documentado, mas vamos passar exatamente o que você precisa fazer para colocá-lo em funcionamento. Então você pode baixar e instalá-lo. E uma vez que você tenha feito isso, você será recebido com esta bela interface. Então, há poucas coisas que você quer fazer também. Comece com este procedimento. Número um, você quer se certificar de que o tempo de execução está correto. Então, por padrão, eu acho que ele pode ir para net Core 21. Estamos usando a rede cinco, então você pode ir em frente e mudar isso. E, em seguida, a URL de especificação precisa ser a URL para o arquivo JSON proveniente do swagger. Então você pode simplesmente copiar isso do navegador e colá-lo lá. Clique em Criar cópia local. E então você vê essa documentação aqui em cima. Agora com tudo isso feito e apenas as notas que em swg aqueles suporta outros tipos de aplicações cliente, o que significa TypeScript. Se, se você estivesse usando view ou reator, um desses frameworks JavaScript, então você poderia facilmente gerar código usando e swg para esses tipos de frameworks. No entanto, nós estamos nos mantendo com os clientes C Sharp, então você só pega isso e você recebe a nova conta. E, em seguida, há algumas configurações aqui. Deixe-me rolar até o topo. Há algumas configurações aqui que queremos ter certeza que estão na polícia. Número um, configure o namespace. Então, para namespace eu tenho HR ponto deixar gerenciamento ponto MVC pontos serviços. Esse é o namespace em que pretendo ter todo o código gerado. Há outras coisas que já podem estar marcadas, mas vou passar e ter certeza de que configuramos o cartão F1. Portanto, use o URL base para a solicitação. Você deseja certificar-se de que está marcado, bem como gera a propriedade URL base deve ser definida na classe base. Tudo bem? Você deseja certificar-se de que você tem o cliente HTTP injetar por um construtor marcado e gerar interfaces para classes de cliente. Rolando, eu acho que a maioria deles já estão lá por padrão. Pretende certificar-se de que tem os tipos de detalhes genéricos assinalados. E perto do fim. Queremos também garantir que, na verdade, cheguemos ao fim, porque penso que tudo o resto aqui já será preenchido por defeito. Então eu não vou gastar muito tempo em coisas que já estão lá e não eu não estou cansado, não absolutamente necessário. Então, qualquer coisa que esteja fora do ponto, só vai garantir que eles estejam no lugar. Você pode deixar tudo o resto. E, em seguida, no final, você deseja colocar no caminho do arquivo de saída para que você possa simplesmente ir para o seu projeto corretamente chamado de projeto. Lotes de Visual Studio, desculpe, grep, clique em um projeto e vá para Abrir no Explorer, pegue esse URL ou esse caminho e colá-lo aqui, o que estamos colocando serviços barra, barra de serviço cliente ponto CSS. Então, depois de ter feito tudo isso, você pode ir em frente e pressionar Gerar arquivos e não deve demorar muito para gerar esses arquivos. E, em seguida, quando isso for feito, você pode saltar para o Visual Studio e ir para a sua base de serviços e classe de cliente de serviço. Eu tenho um pouco mais rápido que nós vamos discutir mais tarde, mas é apenas foco no servidor e arquivo de concessão de serviço. Então nós temos este arquivo cliente que é gerado e nos dá uma interface e a implementação da interface fora da caixa, certo? Muita documentação sobre anotações realmente não precisa se preocupar com muitas dessas coisas. Mas no final do dia, gerou um barco 1700 linhas de código, pelo menos no meu livro. Assim, com base no tamanho da sua API, você pode obter mais, você pode obter menos. Mas a questão é que tudo isso foi feito por nós para que possamos nos concentrar em coisas mais importantes, certo? Então, queremos trabalhar de forma mais inteligente, não mais difícil. E outra coisa importante a notar é que, dentro de swagg, sempre que essa documentação mudar, ou seja, sempre que essa documentação mudar, ou seja,alguém fez uma alteração na API, arrogância. Como resultado, tem, embora nos endpoints requisitos mudou, o que isso muda? Você sempre pode simplesmente excluir que você está colocando em. E, novamente, crie novamente esse arquivo para que você não precise obter que reduza a frente e a frente, especialmente em um ambiente ágil onde as mudanças são inevitáveis e rápidas. Então você sempre pode apenas manter o ritmo com regenerar neste cliente e alterar o código em torno dele conforme necessário? Não, eu não mencionei que eu tenho alguns outros arquivos e enquanto vamos entrar nos detalhes deles, eu só vou te mostrar. Então eu tenho contratos e os contratos que eu tenho um arquivo de contrato ou uma interface por tipo de ponto final que eu conheço de interagir com e também um arquivo de implementação de serviço para cada avons de contrato iniciado para Windows em, mas eu estou apenas dando a vocês uma idéia do que esses arquivos adicionais estão no arquivo base, pasta base. Eu também tenho uma resposta API e eles são mais PFAS que vão para a base apenas para que possamos ter essa extensibilidade. Mas para não, você não precisa se preocupar com isso. A próxima coisa que você pode querer fazer no entanto, é configurar o soft de Newton. Então você provavelmente está recebendo um erro em qualquer lugar que a palavra Newtons destes sendo referenciado neste arquivo. Então você sempre pode ir para New gets. E então você gostaria de olhar para o soft, desculpe, Microsoft dot ASP, NET Core, VC dot Newton soft JSON de Newton. Então você pode ir em frente e instalar isso, fazer uma nova construção, e essas áreas devem desaparecer. Em seguida, em nossa classe de inicialização, queremos registrar nosso cliente HTTP. Então você diz, nos serviços de configuração diria serviços que adicionam cliente. Eu lidero PaaS no cliente IE e cliente. Esses dois estão procurando por mais arquivos gerados. E depois queremos passar o endereço básico. Então é apenas um CEO ou cliente de uso igual, você sabe, isso é uma expressão lambda. endereço base dos pontos é igual ao novo URI. E, em seguida, queremos a URL para a API real. Então, para encontrar essa API de URL, o que você pode fazer é ir para o projeto de API, expandir propriedades e iniciar configurações. E então você veria essa porta SSL. Então é basicamente http localhost dois-pontos para o total, no meu caso, 44, 3, 27. No seu caso, pode ser diferente, certo? Então HTTPS localhost e essa porta SSL como você vê-lo em suas sessões de gramado. Então, com isso feito, nós realmente configuramos o cliente ou pelo menos a base para o cliente. Assim, os contratos e as definições de serviços que temos aqui e que iremos pescar acabam por voltar, são relativos às operações específicas necessárias por chamada. Porque quando chamamos C recebe todos os tipos de folhas. Como vamos exibir os tipos de folhas em nossa aplicação? Ainda precisamos de modelos. Ainda precisamos desserializá-lo do JSON porque, você sabe, APIs de descanso que eles estão enviando e recebendo JSON. Então vamos precisar converter de JSON em algum tipo que nosso aplicativo cliente possa apreciar. E então podemos permitir que o usuário interaja com ele de acordo. Então, quando voltarmos, vamos olhar para todos eles. Embora codificar atividades que precisamos colocar em nosso próprio, nosso cliente. 28. Configurar clientes de API personalizados e código base: Então agora vamos criar ou passar por alguns dos arquivos de suporte e funções que vamos colocar no lugar antes de continuar com a construção de nosso aplicativo cliente. Então, essas são realmente operações únicas que vamos passar e eu vou explicar por que elas são úteis. Não necessariamente necessário, mas pelo menos útil. Então vamos começar com nossas bibliotecas de terceiros em novos gets. Nós vamos para ir e obter o Outono superior e nós vamos para armazém local no Julian Hansen. Tudo bem, então isso vai nos ajudar mais tarde. Nós não vamos necessariamente usá-lo agora, mas você pode simplesmente ir em frente e obtê-lo do Não, que possamos apenas configurar tudo de uma vez por todas. Nós estamos recebendo tanto outono superior e finalmente extensões. E já temos o Newton mole. Então, com tudo isso instalado na inicialização, vamos nos certificar de que adicionamos o mapeador automático. Agora você provavelmente está se perguntando, ok, por que eu estou adicionando papel final? Novamente depois que provavelmente fizemos isso já no aplicativo. Então nós tínhamos configurado esses serviços para distribuição em nossa camada de aplicação e nós tínhamos adicionado oper outono. Então você provavelmente está se perguntando, ok, assim como com a API quando nós apenas chamamos configurar aplicativo e serviços. Por que você não configura aplicativos e serviços que são Clint? Bem, a realidade é que o cliente realmente não sabe nada sobre mais nada neste projeto, certo? Então é o seu próprio projeto. Imagine se estivéssemos usando digamos, uma vista ou uma aplicação Angular, será a mesma coisa. Não haverá, sim, além do fato de que não haveria de baixo para cima, mas o fato é que não haveria referências de núcleo ou infra-estrutura. Ele mal faz referência à API, só sabe que uma API deve ser encontrada em um endereço, e essa é a suposição que ela faz. Então, com isso dito, é por isso que não estamos referenciando qualquer uma das outras bibliotecas dentro deste aplicativo cliente MVC. Ele é autônomo e tudo o que ele faz é acessível a um endpoint e esperar um certo resultado depois, que seria a chamada de API que configuramos aqui. Então nós estamos adicionando outono superior individualmente a este projeto. E, mais uma vez, isso é porque quando estamos recebendo o DTO com, talvez tenhamos que massagear bits de dados antes que exibamos para o usuário esteja interagindo com ele de qualquer forma, forma ou forma. Então nós adicionamos o mapeador automático, e eu já fui em frente e adicionei isso. Bem, você não tem que se preocupar com essa linha vai passar por essas três linhas em detalhes em algumas. Então vá em frente, adicione a parte superior do outono. E então as próximas coisas que temos que colocar no lugar seria criar um tipo de resposta personalizado. Então nosso tipo de resposta aqui seria usado quando falamos com a API e a resposta API, poderia ser com a resposta de comando. Pode ser com a resposta do comando RBS, em vez disso poderia ser com os erros de validação, seja lá o que for. Nós não sabemos. Lembre-se, estamos apenas interagindo com uma API, então estamos esperando que coisas boas voltem ou alguma forma de exceção são algumas criações de manteiga. Nós não sabemos. Então estamos criando nosso próprio tipo de resposta genérica no cliente, que será capaz de receber uma mensagem. Vai ser bom. Adoro obter erros de validação na forma de uma string. Ele vai saber se foi bem sucedido e ele iria recuperar alguns objetos, objetos. Então eu estou chamando de “t go “, nós não sabemos o que poderia ser. Pode ser um objeto com o que você sabe, fomos retornados o objeto em alguns dos criar, poderia ser um inteiro, seria apenas o ID, nós não sabemos. Claro que seria prudente da nossa parte fazer retroceder e padronizar todas essas coisas. Para fins educacionais, teríamos passado por diferentes cenários. Mas pelo menos indo para o ambiente mais empresarial, gostaríamos de padronizar isso para que possamos definitivamente saber o que esperar para cada cenário. Então essa é a nossa resposta do cliente. Tudo bem, então seguir em frente no próximo arquivo que temos que quer ver é que eu afirmo. Então, na pasta base, temos um cliente e você tem clientes que você provavelmente está vendo. Está bem. Mas não vimos o cliente da AAE e o cliente antes? E se você está vendo isso, então você está correto. Em nossos clientes de serviço que foi gerado, temos ironclad e temos cliente. Mas então nós só queremos criar uma pequena extensão disso para que não tenhamos que cavar muito fundo para chegar a certas coisas. Então, primeiro, você notaria que isso é parcial. Tudo bem? Então a coisa legal sobre uma parcial é que isso significa que você pode ter várias versões da mesma classe. Claro que vão trabalhar juntos. Mas qualquer Kevin tem vários arquivos com o mesmo nome, o mesmo nome de classe ou nome de interface. E é como se todos se fundissem no tempo de execução. Então, é muito legal se você nunca interagiu com parciais. Mas já temos a parcial sendo gerada para nós. Então, vamos apenas criar nossa própria implementação parcial ou nossa própria interface parcial do cliente AAE, que só tem acesso ao cliente HTTP. Tudo bem, então em serviço, então temos esse cliente HTTP. É muito profundo. Em tempos provavelmente não é muito acessível, então estamos apenas criando uma versão pública disso. E, em seguida, na implementação que é público de crédito de classe parcial no, em corte de cabelo, desculpe, da Islândia. Nós só temos essa propriedade pública que está recebendo nosso retorno aquela propriedade privada dos tipos de serviço. Então, há o nosso cliente HTTP privado. Então isso significa que isso nos permite realmente não interagir com o cliente HTTP no caso de você querer fazer alguma coisa com ele. Como mais tarde, quando estivermos fazendo a segurança, vamos querer interromper com ele para colocar os cabeçalhos antes que ele envie inflamação. Então, você verá que em alguns No 1 para observar com o cliente e o cliente, você deseja certificar-se de que eles estão no mesmo namespace que um serviço, gradiente de serviço. Tudo bem, então, na verdade, quando eu estava fazendo isso, eu não tinha o ponto porque eu dei serviços NBC Dot. Esse é o namespace que eu dou em swag para gerar este arquivo mesmo que ele esteja indo para a pasta base. E então eu cliente foi criado automaticamente com o namespace dot ds. Então você tem duas opções. Você poderia tanto neste para este, e, em seguida, certifique-se de que no swag sabe que namespace deve adotar estes. Ou você pode apenas ter certeza de que isso é serviços porque se eles não estão no mesmo namespace e eles não vão se ver como parciais. Então você pode apenas tomar nota disso quando você está fazendo isso. Se você está recebendo algum erro que você não consegue descobrir por que você está obtendo eles. Agora vamos voltar para a pasta Contratos. E lá você veria que eu tenho um arquivo chamado i serviço de armazenamento local. - Não. Vou falar sobre seguir em frente. Os serviços de armazenamento local para nós estaremos implementando autenticação usando JSON Web Tokens ou JWT para breve saber, depois que um Tolkien tem sido fácil de aplicar, aplicação aqui sendo um aplicativo cliente, precisamos uma maneira de armazená-lo entre as operações, então você faz login e, em seguida, enquanto você está logado, você provavelmente está olhando para a sua licença, você provavelmente está fazendo uma série de coisas. Qualquer um pode estar fazendo qualquer coisa em qualquer ponto do sistema. Mas vamos exigir autenticação para que você possa concluir certas coisas. Então, um token definitivamente precisa estar presente. Como eu disse, vamos acrescentar isso mais tarde. Mas eu quero configurar isso pelo menos o serviço local olho, serviço armazenamento local de null porque ele será necessário para alguma outra configuração de fera que queremos fazer. - Não. Então, depois de obter essa biblioteca de armazenamento local do NuGet, vamos apenas criar uma interface onde podemos abstrair algumas das operações em nossos próprios métodos. Portanto, queremos que exista armazenamento claro, obter valor de armazenamento e um valor de armazenamento definido. E é realmente apenas um par de chaves de valor. Então vamos dar a ele uma chave e um valor. Então você pode usar isso para armazenar pequenos pedaços de informação. Claro, você não deseja armazenar nada muito sensível dentro do armazenamento local, pois ele pode abrir seu aplicativo para vulnerabilidades. Mas esse é o seu propósito. Então, depois de configurar essa interface, você pode ir em frente e configurar a implementação na pasta de serviços. Então, temos o serviço de armazenamento local herdando do meu armazenamento local. E temos um campo de tipo de armazenamento local que vem até nós da biblioteca que nos foi dada pela rede de pontos de Hansen. E aqui no construtor estamos apenas sentados como uma pequena configuração e, em seguida, inicializando o armazenamento. Portanto, nossa configuração diz nova configuração de armazenamento de baixo custo. Carregamento automático e salvamento automático são verdadeiros. E então o nome do arquivo que eu dei a ele esse nome que é indicativo do aplicativo ao qual ele pertence. Então você pode ir em frente e fazer isso. E, em seguida, o armazenamento é igual ao novo armazenamento local. E todos os métodos são bastante simples. No armazenamento mais claro, temos apenas a lista de chaves que queremos limpar do armazenamento. Então esta coordenada útil quando alguém provavelmente está logout e você deseja remover as referências aos tokens e qualquer outra coisa que você teria armazenado. Você pode simplesmente ir em frente e passar em todas as chaves e ele iria apenas removê-los para você. Você tem o valor de armazenamento definido onde passamos na chave e qualquer valor e, em seguida, ele irá armazená-lo. Não, Isso é t. Sim, ele pode tomar como um objeto ou uma string, qualquer tipo de dados, mas ele irá analisá-lo para baixo em alguma forma de valor armazenado e, em seguida, armazenamento que persistem análise básica, apenas mantê-lo e certifique-se de estão prestando atenção a isso. Obtém o valor de armazenamento basicamente apenas retorna o que é baseado na chave que é solicitada. E então podemos sempre verificar se existe, certo? Então passe a chave e ele vai retornar armazenamento Xist, que é apenas um booleano. Sim, existe ou não, não existe. Ninguém passo que eu teria esquecido passeios para adicionar isso aos arquivos de inicialização. Portanto, temos que dizer que os serviços não adicionam singleton desta vez porque não precisamos de várias instâncias do nosso armazenamento local. Isso seria mesmo. Péssima ideia, certo? Portanto, queremos apenas que uma instância do armazenamento local persista para todo o usuário, o tempo de execução do usuário ou o uso desse aplicativo cliente. E estamos apenas passando no serviço de armazenamento de baixo custo, bem como o serviço de armazenamento local? Não, em nosso serviço HTTP base, que está vivendo na pasta base em nossos serviços. Nós só vamos estar sentando algumas operações base que queremos que todos os serviços sejam capazes de fazer. Então, um em que temos os campos para eu, armazenamento de baixo custo, serviço de armazenamento e um cliente que inicializamos usando nosso construtor, estamos familiarizados com isso ou apenas injetando-os. E depois, não temos dois métodos. Temos um em que convertemos exceções de API são é assim que a exceção de API está realmente vindo de nossa cogeração de plantas de serviço. Porque ao olhar para o ponto final, olhando para o que esperar, percebeu que poderíamos obter exceções de fantasia com código de status e resposta e outras coisas, certo? Então temos acesso a esse tipo de base, mas então provavelmente queremos convertê-lo na resposta se ele chegar. Então, podemos ver se o código de status da exceção da API é 400, então vemos erros de validação ocorreram porque essa foi a solicitação incorreta, certo? Se for 404, então vemos a mensagem, o item não pôde ser encontrado. E então, caso contrário, se é 500 e você vê que algo deu errado, e tantos códigos de erro como teríamos b, sabemos que seríamos capazes de voltar da API. Podemos sempre configurá-los aqui e ter personalizado, pelo menos até certo ponto, mensagens personalizadas por tipo de era. Certo, o próximo método seria adicionar a cerveja Tolkien. Assim, vazio protegido no token portador nos permite ver se o armazenamento de baixo custo tem algum valor com a palavra Tolkien. Alguns só mais uma vez, Linda, Linda, a Linda cresceu aqui, bem onde não estamos prontos para esta. Só estou colocando lá e discutiremos isso em detalhes mais tarde. Mas este método permite que você adicione o token portador para o cliente ponto HTTP, cliente padrão ou solicita autorização, certo? Então, todo esse código é basicamente como você obtém acesso aos cabeçalhos de autorização em qualquer comunicação de cliente HTTP com nossa API RESTful. E o que vamos fazer é adicionar um novo valor de cabeçalho de autenticação. Deixe-me apenas quebrar a linha aqui senta ou limpa. Então, estamos adicionando um novo valor de cabeçalho de autenticação com o portador do nome. E estamos colocando-o do armazenamento local, obter o valor de armazenamento do tipo string com essa chave. Tudo bem, então essa é a sua alma estará recebendo os tokens para enviar com nossos pedidos HTTP. Mas não estamos prontos para discutir isso em detalhes, mas você pode escrever no código de null. Mais uma vez, tudo isso é trabalho crescido. Ninguém que vamos olhar para a nossa fantasia. Eu não gosto de chamá-los de traje, mas nossas extensões dos diferentes recursos são os diferentes tipos de interações que vamos ter com a API da mesma forma, todas as interações tipo folha, todos os as solicitações e as interações de alocação. Nós os obstruímos em seus próprios contratos. E então todos eles estarão interagindo com o serviço HTTP base de qualquer maneira, porque quando nos protegermos, eles precisarão de certa funcionalidade BC e para interrupção geral. Certo, então quando voltarmos e começarmos a olhar para o tipo de folha, porque essa é sempre a mais fácil, certo? O único é bastante simples. Então começa com aquele. E eu vou ver como nós amarramos tudo juntos. 29. Serviço de gerenciamento de letar: Olá, bem-vindo de volta. Vamos começar a olhar para os requisitos de serviço tipo folha. Mas antes de entrarmos no contrato e na implementação do serviço no projeto da interface do usuário, quero que façamos algumas coisas de limpeza com os manipuladores e a API. E vou explicar, é claro que à medida que avançamos, por que estas são benéficas antes de avançarmos. Então, para começar, vamos apenas saltar para o manipulador de comando create leaf type. E se você precisar de nossa primeira audição que está no projeto do aplicativo para a pasta principal. Tudo bem, então o que eu encorajaria você a fazer uma é padronizar o que está sendo devolvido. Então, em todos os pontos, nós queremos provavelmente ter a resposta do comando bs. Lembre-se que uma resposta de comando bs nos permite passar de volta a bandeira de sucesso, o ID do novo registro, bem como uma mensagem, certo? Então você vai querer refatorar seu código manipulador. Vou deixar isso na tela o tempo suficiente para que você possa pausar e refatorar de acordo, onde se a validação falhar, então os sucessos de resposta cairão. Eles terão uma mensagem e colocaremos todos os erros de validação. E depois temos mais. Se estiver tudo bem, então temos o verdadeiro, a mensagem e retornamos o ID com o objeto de resposta. Claro, se estamos atualizando isso para retornar a resposta do comando bs, isso significa que nossa solicitação também precisa retornar isso. Então você pode apenas ir em frente e atualizar o comando de tipo de folha para que eu solicito retornando resposta de comando bs. Então isso são somas das alterações que precisamos no manipulador, bem como na classe de comando. Embora. Passando por isso, vamos pular para a API. Agora, quando estávamos discutindo a API, também mencionamos por que é uma boa idéia nos resultados da ação da tarefa também incluir o tipo de dados que está sendo retornado. E nós vimos na documentação arrogante que, você sabe, para aqueles que tinham o nosso tipo de retorno, a documentação realmente indicava claramente o que seria devolvido. Agora que ajustamos o tipo de retorno para o nosso manipulador de comando criar, vamos também ajustar o tipo de retorno de resultados de ação para a batida com a resposta de comando bs. Difícil porque quando fazemos isso, obtemos a resposta, voltamos bem. Com essa resposta. Tudo bem. Para que saibamos, melhoremos a nossa documentação e depois vou mostrar-vos outra coisa que a torna ainda melhor em termos do que a documentação estar atualizada e ser que explícita nos ajuda a fazer. Agora, mais uma coisa antes de avançarmos, quero que você clique com o botão direito do mouse em seu projeto de teste e execute testes. Então, só para o caso de você não estar convencido sobre por que testes de unidade são importantes. Se você executar os testes, você provavelmente obterá todas as falhas para os testes que foram para verificar se o, se a validação ou o tipo de folha válido ou tipo de folha inválido foram adicionados com sucesso, Por que eles estão falhando? Bem, acabamos de fazer nosso refator, então mudamos algo em nosso código, nosso frango Teslas para uma coisa. E obviamente o que mudamos quebraria esse teste. Agora, se você voltar para o seu teste, lembre-se que dissemos que o resultado da operação ADD deve ser do tipo int. Então, mais uma vez, esta é uma ótima maneira de ver onde refatorar seu código realmente modificaria as coisas, certo? Então não, o teste válido teria dito deve ser tipo folha int. Vamos mudar isso para deve ser baseado em resposta de comando. Agora o inválido estava contando com uma exceção de validação sendo lançada, que era o caso anterior ou fatorado ou neve. Então nós realmente precisamos ajustar este teste para saber refletir que não há nenhuma exceção. E que estamos apenas fazendo o mesmo tipo de operação em que estamos apenas ligando esperando por 0 porque é isso que nosso novo código está fazendo, certo? Estamos a ligar à espera dos resultados. E os resultados devem estar fora da resposta de comando baseada em tipo e o código deve ser três. Então, se reexecutarmos esses testes, então veremos que temos testes bem-sucedidos todos os nossos próprios. Então, mais uma vez, a própria unidade era para nos manter, ajuda a manter-nos sob controle com nossos fatores e nossas mudanças centrais em um projeto tão grande. Agora que modificamos ou API, precisamos regenerar a Guerra Fria, o cliente de serviço. Além de apenas regenerar, há algumas mudanças que eu quero apontar com as configurações como você faz isso. Então, mais uma vez, vá em frente e pegue o link JSON se você ainda não o tiver ligado. E, em seguida, na interface final do swag, vamos colá-lo e vamos recriar a cópia local. Então nós temos que fazer esse passo toda vez, se você tinha, não há porque o que ele vê no JSON é o que ele vai usar quando ele está gerando o código. Então eu estou apontando esse dedo porque antes do método post que acabamos de modificar só tinha um tipo de retorno de 200, 100 com talvez um int. Não, você verá que ele tem outros tipos de devolução. Tudo bem. Então, a inferência de que para o final SWACH Studio é que ele precisa compensar o fato de que ele deve esperar nosso tipo de retorno de resposta de comando bs. Então vamos ser a mesma coisa. Então, se você já está aberto, tudo bem. Mas se não, podemos passar por isso de novo. É gerenciamento de licença R-dot, mas MVC dot services.js, Estou colocando na base desta vez Mr. -lo fora da primeira vez, quero garantir que estamos gerando as classes de exceção. Injete o cliente HTTP via instrutor e gere interfaces para Acesso para Cliente. E queremos embrulhar as exceções de detalhes no futebol. Instância de exceção. Queremos gerar os detalhes. Mas uma coisa que se você tivesse antes, eu adoraria que você desmarcasse É isso em um barco, a URL base dos EUA para o pedido. Então, inicialmente, tínhamos marcado. Você pode desmarcá-lo. Razão sendo no código de concessão de serviço que você abriu todos, você veria que há um campo BaseURL lá e ele está esperando por uma string. Então nós estamos realmente tipo de ignorar a necessidade de colocar a string nesse código porque nós tínhamos registrado ou cliente HTTP com seu endereço base. Então não precisamos disso. Use BaseURL para solicitação mais. Tudo bem, então você pode desmarcar o ponto um e ir em frente e certificar-se de que tudo o resto está marcado de acordo. E uma vez que você fez isso, é claro, você apontou para o caminho de saída e então você gera arquivos. Então, uma vez que você que o arquivo CS tendências de serviço será regenerado e atualizado para saber esperar que o novo tipo de retorno ou tipos se você refatorar mais de uma coisa, o que quer que seja que é novo em sua API será refletido no e, como resultado, refletida em sua nova classe de marca de serviço. Então, agora que concluímos a base com nossos manipuladores e nossa API. Vamos voltar para a nossa interface do usuário. Então, eu estou na classe de inicialização e Lee pode ver que eu descomentei a linha de serviço tipo folha de serviço tipo de folha de serviço. Vamos descomentar os outros no devido tempo, mas você pode apenas começar com aquele em comentou. E vamos olhar para as implementações. Antes disso, porém, quero salientar que temos o perfil de mapeamento. Então eu criei o perfil de mapeamento que segue os mesmos procedimentos foram usados para de nossa camada de aplicação onde herdamos de perfil cortesia de outono superior e, em seguida, começamos a colocar essas configurações de mapa de perfil. Eu também criei alguns modelos de visão. Eu vou realmente começar com o ViewModel antes de olhar para implementação do serviço de folhas e interface. Então, se nós apenas não sabemos onde para isso, eu criei em nossa pasta de modelos, deixe o tipo VM. Eu só coloquei tudo em um arquivo desta vez. Então, no tipo de folha VM, você verá que eu tenho isso, que representa a VM que tem todos os campos, mas ela só tem o ID. E então eu criei deixar que VM onde temos o nome eo padrão é, então deixe que VM herda de criar folha que VM. Portanto, sempre analisamos como podemos reduzir a repetição entre as VMs. E, mais uma vez, depende de quão granular você deseja obter em termos de dados ou pontos de dados, em vez de colocar em seus modelos de visualização. Então, aqui, deixe que VM tem ID e herda todos os outros campos de Criar e cria aqueles que não têm esse ID. E já discutimos isso é do nível de detalhe, por que isso é feito dessa maneira. Então, mais uma vez, a partir do perfil de mapeamento, eu posso mapear como gostar entre o ViewModel nativo para o, para o aplicativo de interface do usuário ou o caminho e a cortesia de nosso arquivo de cliente de serviço AI ou arquivo de concessão de serviço, desculpe, onde temos todos os detalhes tipo de ser feita referência nesse arquivo. Então você pode ir em frente e replicar esse tipo de mapeamento e esses modelos. Agora vamos pular para, eu acredito, tipo de serviço. Então esta interface, está em contratos e basicamente implementa todas as funções de multidão que sabemos que são nativas. Você precisa deixar as operações tipo são acreditadas operações tipo. Então nós temos os tipos de folha get que está retornando uma lista de lift, IBM, aquele que recebe o detalhe retornando a mesma VM. Temos resposta à tarefa insular. Eles olharam para a classe de resposta. Então aqui nós realmente esperamos essa resposta relativa ao Pai. Estamos recebendo essa resposta base do comando que está criando nosso tipo de folha. Então nossa tarefa vai retornar uma resposta, mas, em seguida, interior, isso representa o valor id que está voltando porque é isso que nós realmente queremos, certo? Então, uma resposta relativa ao tipo de int criar tipo folha e estamos passando nessa folha que VM. Nós também temos a tarefa de atualizar e uma tarefa para excluir. Então, depois de configurarmos tudo isso na interface como vimos antes, uma vez que você tem um contrato, você tem que ter a implementação. Então, sobre a implementação que eu acabei de colocar na pasta de serviços, nós temos o serviço tipo folha. Então vamos passar por isso juntos. Então isso é herdar do serviço HTTP base que você passou juntos. E então eu deixar o tipo de serviço nesse ponto vai dizer tudo que você precisa para fazer a implementação. Não há problema, você vai em frente e deixá-lo implementar todos os métodos necessários. Então, dentro deste serviço tipo folha, temos o pico local, o cliente IM superior e AAE sendo injetado. Então, todos eles são injetados e inicializados de acordo. Também temos de passar para a nossa base. E base aqui sendo o serviço HTTP base, o cliente HTTP, bem como o serviço de armazenamento local. Você já viu isso. Então você tem que definir todas essas coisas. Por favor, aponte para parar lá realmente para este segmento, quando voltarmos, vamos olhar para os diferentes métodos que foram implementados. Já tenho um código lá, mas tudo bem. Vamos passar por isso em detalhes no retorno. Mas esses são seus métodos sendo herdados do serviço de tipo elif e eles são todos colocados lá esperando para serem implementados. Então, vamos passar por isso, bem como nossos controladores e nossas opiniões na próxima lição. 30. Interface de geração: Nesta lição, vamos percorrer nossos controladores e pontos de vista e a interface geral do usuário sobre como lideramos nossa aplicação interage com a API para todas as operações crud. Mas antes de chegarmos lá, tenho algumas correções que precisamos fazer nossa interface e na implementação do nosso serviço tipo folha. Portanto, as correções incluiriam a atualização dos tipos de retorno para a atualização e exclusão. Eu meio que tenho copiando e colando. E na lição anterior, você provavelmente teria copiado sobre as implementações incorretas são protótipos incorretos para esses métodos. Então você pode ir em frente e atualizá-los de acordo, onde todos eles devem estar retornando a mesma resposta de tarefa em relação ao tipo int. E para a atualização e exclusão atualização é bom tomar um parâmetro int id e o tipo de folha VM. E o delete vai tomar esse parâmetro int id. Então você pode ir em frente e fazer essas alterações e, claro, atualizar as implementações dentro do arquivo de serviço de tipo folha. Agora, a fim de começar a fazer a interface do usuário, é claro, temos que colocar a implementação subjacente e, em seguida, conectar o código e tudo mais. Então vamos começar com os muito simples, que seria o tipo de folha R para obter tipos de folhas, que será a lista. E eles obtêm detalhes do tipo folha, que seria o único. Tudo bem, então vamos olhar para as implementações para essas ferramentas. Eles são bem simples. Tudo o que estamos fazendo é inicializar uma variável que estou chamando nos tipos de folha ou Napoleão via tipos de folha igual a esperar cliente. Então este cliente não é a concessão HTTP que está sendo injetado no que o cliente vem do serviço HTTP obeso, certo? Certamente, seria quase a mesma coisa, porque a única razão pela qual temos este é para que possamos passá-lo para a base. Tudo bem, mas vamos nos ater a isso. Portanto, o cliente sublinhado representa a glândula de serviço HTTP problema base. E é isso que estamos usando. Então eu vou esperar aqueles Work Trend, tipos de folhas de ponto, tudo uma pia. Tudo bem, então isso está nos dando acesso a todos os métodos que foram gerados para nós no cliente de serviço thunks a troca final. Então você verá tipos de folha de tipos de folha, leads obter mais completo é visto por alguém chamado ele métodos em seu controlador de API, você pode ver nomes ligeiramente diferentes, mas eu apenas olhei em convenção de nomenclatura particularmente para API padrão desenvolvimento. E eu só estou pegando esses. Então eu acho que é claro o suficiente que este está recebendo todo o outro está recebendo, só quero obter, etc. De qualquer forma, os parâmetros sempre podem ser o seu guia. Então tipos Vardy é igual a esperar todos os tipos de folhas. E então retornamos esfregão, lista de esfregões, tipo de folha, VM, os tipos de folhas. Tudo bem, então é por isso que isso está retornando essa lista de folha tipo VM, porque isso retornaria na lista são zona pública do tipo folha DTLs hora apenas mapeando-os para a nossa VM tipo folha local. Então nós já olhamos para o mapeador e a configuração para isso. Não fora disso, para os detalhes, o que estamos fazendo aqui é pegar apenas um. Então estamos vendo var folha para ser z igual a 08. Cliente. Tipos de folha obter uma pia e os gets ocupa o nosso mentor fora int id. E, em seguida, da mesma forma, estamos retornando uma versão simulada para deixar tipo VM desta folha. Agora vamos para um dos mais complicados. Vamos começar com o tipo de folha de exclusão, e eu vou excluir tipo de folha só precisa do ID. Ele só precisa do ID porque o parâmetro API quando ele precisa do ID. Então, estamos fazendo uma captura de tendência nesta situação em que vamos ver um tipo de folha de cliente.read peso, excluir assíncrono passando nesse ID. E então vamos retornar uma nova resposta do tipo int onde o sucesso é verdadeiro. Tudo bem, Então, se isso não foi bem sucedido, então é por isso que pegamos e então nós convertemos ou API que teria a nossa exceção API vez que teria sido voltar para a resposta com as informações apropriadas. Tudo bem, então isso é praticamente tudo para a exclusão. E depois a atualização. Na verdade, parece muito semelhante a isso, exceto para tomar ID e o tipo de folha em como folha de tipo que VM. Então eu vou fazer um mapeamento para converter que de folha para uma VM no tipo de folha DTO antes de, em seguida, enviá-lo para cima. E toda a coisa sobre esses tipos de folhas colocam assíncrono. Se você passar o mouse sobre ele, você verá que ele leva um ID do tipo string, minha cadeia gerada final. Eu achei surpreendente o que eu disse, deixe-me trabalhar com ele em vez de tentar contorná-lo. O seu toma int, então tudo bem. Você não tem que fazer este ponto id para string, mas no meu caso é preciso string, então não há problema, eu estou pegando o int id, eu estou apenas convertendo para string. E eu também estou passando por cima da diabetes folha. Bem, isso é que eu acabei de me converter. Então, se tudo foi bem sucedido, nós apenas retornamos uma resposta com sucesso sendo igual a verdadeiro. Mais uma vez, está em uma captura de tentativa. Então qualquer exceção seria capturada. Saiba com a criação coloca você em um pouco mais. Então eu comecei ou você teria visto uma prévia disso. Bem, deixe-me explicar o que este código está fazendo desta vez. Então, mais uma vez, ele está retornando uma resposta com mergulho em staking, criar folha VM como seu parâmetro. E são realmente os mesmos pedaços de código, mas apenas com mais alguns gráficos e reviravoltas para ele. Então aqui eu estou vendo criar detalhes do tipo de folha e eu estou fazendo o mapeamento. E então eu estou vendo Obter a resposta do correio. Então a razão pela qual eu tenho que fazer isso é lembrar que nós atualizamos nossa chamada API para retornar essa resposta de comando. Os outros eu devolvo conteúdo nulo, certo? Então é por isso que só há tarefas. Mas no caso da criação, estamos recebendo feedback após a chamada. Então estamos recebendo uma resposta melhor, que é resposta de comando bs. Então o cliente de serviço realmente gerou este vidro para nós para imitar a resposta do comando base vindo da API. Então lembre-se, neste momento, ainda não sabemos nada sobre AICPA não foram interagidos com a implementação de resposta base real que fizemos todo o caminho até em nossa camada de aplicação. Tudo isso está sendo feito aqui mesmo no cliente. Então, basicamente, a não-resposta ajuda a fanfarrão depois de fazermos uma tentativa post. E lembre-se que isso é contra a tentativa, mesmo que sinta que não é necessariamente uma falha porque ele poderia ter falhado por razões de validação, mas ainda estaria recebendo cerca de 200 respostas, certo? Então o try catch, e apenas para retroceder um pouco, o try-catch aqui é realmente que se o cliente de serviço é configurado de uma forma que, se a resposta não é um 200, então ele vê isso como uma exceção, e é por isso que fazemos essa conversão. Saiba que no caso do, o Criar, poderíamos ter obtido uma resposta de 200 com esta resposta de comando base, mas então não é bem sucedido. Então estamos voltando, ok, http sábio. Mas a operação em si não foi bem sucedida, então o motor está nos dizendo que não foi bem sucedido. Nós escrevemos aquele motor para sabermos esse direito. Mas no caso de você estar consumindo uma API de terceiros em nós, neste momento, eles teriam que deixar claro para você que você poderia obter um 200, mas você sempre tem que verificar esta bandeira se ela é verdadeira ou falsa. Então, neste caso, se for bem sucedido, então nós equipamos nossa resposta, essa é a nossa resposta local do tipo int. Nós equipamos os dados com o ID. Lembre-se que falamos sobre isso, retornando o id do registro recém-criado, e então o sucesso é verdadeiro. Então, localmente, sabemos que nossa tentativa de criar foi realmente bem sucedida. Caso contrário, não vamos obter todas as setas que teriam sido empacotadas na resposta do comando base com esses, com os erros de validação. E então vamos colocá-los em nossa resposta local e empilhá-los. E então estamos retornando essa resposta para que fosse verdadeira ou falsa ou retornando essa resposta. E mais uma vez, pegamos quaisquer exceções que teriam sido lançadas. Então, agora que temos um passo a passo todo combatido, nosso código de implementação de serviço parece. E, claro, isso ainda está permeado a mudanças em um ambiente ágil. Você pode fazer isso de uma maneira e em gengibre no final da estrada porque há outra coisa que está bem. Mas, por enquanto, é o que temos. Então, o próximo passo seria começar a criar nossos controladores. E o controlador com o qual estamos começando seria, naturalmente, para tipos de folhas. Então você pode ir em frente e clicar com o botão direito em controladores, clique em Adicionar controlador. E eu vou apenas fazer um controlador MVC com opções de redirecionamento. Vá em frente e adicioná-lo, e nós vamos chamá-lo de controlador de tipos de folha. Então saiba que o controlador foi criado. A primeira ordem do dia seria preparar a injeção. Então nós queremos injetar o nosso Eu vou deixar o tipo de serviço e nós podemos, é claro, ir em frente e adicionar quaisquer referências faltantes. Então eu deixar o tipo de serviço é nulo em nosso controlador. Vamos começar com o fácil, eu vou dizer as páginas mais fáceis para começar e correr. Como podemos começar com a página de índice. Tão fácil maneira de criar a página de índice. Você pode clicar com o botão direito do mouse e clicar em Adicionar exibição E queremos aumentar o índice de visão deles. Queremos o modelo da lista. E, em seguida, deve ser uma lista relativa ao tipo, tipo folha de VM. Então você pode ir em frente e adicionar isso. Uma vez que você tenha feito isso, você terá aquela vista. Tudo bem, então é agradável e simples. E se você está acostumado com MVC, então esta não é uma tarefa real para você. Então você sabe o que é isso. E porque não estamos usando um EOF, nosso objeto de domínio, certas coisas que adoramos transferir dinheiro, seja essa seção onde ele está pedindo a chave primária, então diga ID do ponto do item. Então é por isso que usamos o tipo de folha VM, que tem todos os campos em oposição ao criador, os outros, porque nós definitivamente precisamos do ID para este bem e ir em frente e atualizar esses links para que edite os detalhes e a exclusão. Saiba onde obter o ID de quando precisamos navegar. Se você quiser enfeitar a interface do usuário de Não, Você também pode remover os campos de id porque você e eu sabemos que não precisamos necessariamente daqueles nas operações diárias de exibição de dados. Saiba que a interface foi criada. Claro, precisamos deixar a interface N4 de onde ela está recebendo seus dados. Então esta chamada vai ser bem simples, onde tudo o que vamos ver é o modelo VAR é igual ao peso. Os tipos de folha de repositório git tipos de folha, que é o que acabamos de olhar para a implementação. Então ele é chamá-lo de tipos de licença, que, em seguida, faz com que API e retorna a versão esfregada. Então, mais uma vez, estamos promovendo controladores finos aqui porque ele queria estar fazendo toda a lógica aqui, você sabe, fazendo a chamada de API, fazendo o mapeamento e, em seguida, retornar na exibição. Queremos cultivar tudo isso para outro lugar. Então o controlador só sabe, chamar este método, obter os dados, e depois continuar com a vida. Esta linha vermelha é porque precisamos fazer este método uma opção resulta. Isso é uma tarefa e uma pia, certo? Então, se você queria realmente ir através e fazer tudo isso porque todos eles vão estar fazendo chamadas assíncronas. Então, apenas para reduzir a probabilidade de obter essas setas, basta ir em frente e mudar tudo para um resultado AsyncTask de ação. E então é isso para o índice. Então vamos tomar este pior sido antes de eu fazer, deixe-me ir para o layout e adicionar um URL para ele. Então eu estou apenas adicionando um novo item de menu que diz é B tipos de folha de controlador traço é a ação é índice e é tipos de def. Então vamos correr e ver. Sinto muito, antes de executar, antes de executar, eu não mencionei que precisamos deixar o cliente e a API seta e simultaneamente. Então, o que você precisa fazer é clicar com o botão direito nessa solução e ir para Propriedades. E então você iria para o projeto de inicialização e alterá-lo para vários projetos de inicialização. Então precisamos da APA para começar. Precisamos que o MVC também tenha início. Se quiser que eu comece com a depuração. Então leva, você precisa de um tempo mais curto para começar. Secant é ir em frente e clique em Iniciar. Então agora nosso aplicativo está funcionando, ele está funcionando e tudo o que precisamos fazer agora é pular para deixar tipos. E há nossos dados que estão vindo diretamente do nosso banco de dados. Bem, nós não sabemos. Não nos importamos neste ponto de onde vem. Nós só sabemos onde chamar uma API, pedindo os dados e ele, nós estamos exibindo isso aqui. Então tudo está acontecendo fora da caixa, certo? Claro que, em segundo plano, como desenvolvedores de API, sabemos todas as palavras que colocamos em um manipulador e tudo para que saibamos de onde os dados estão vindo. Ambos o nosso cliente não sabe. Certo, então a seguir queremos ser capazes de criar. Então precisamos criar o nosso scuffled que cria visão. Para fazer isso, mais uma vez, tudo o que temos a fazer é ir para Ver, clicar com o botão direito do mouse em Adicionar vista, vista navalha. E então queremos criar modelos. E o modelo aqui seria o Create leave type VM, e então você vá em frente e adicione isso. Assim que você tiver adicionado a vista e você obter o arquivo físico, o código que precisamos escrever aqui é duplo. Então, um para obter, não precisamos de nenhum código porque só estamos carregando o formulário, certo? Então já é, ele já criou esse formulário sabendo que ele deve ser relativo aos campos que estão aqui. Então temos o campo para o nome do feto para os dias padrão. Não precisamos fazer mais nada. Então, a menos que tenha algo especial, tudo bem. Mas no nível básico, nada mais é necessário. No entanto, no post, é aí que a magia precisa acontecer. Então o que precisamos fazer agora é para o nosso peso, nossa chamada para a operação do tipo folha. E bem, antes mesmo de chegarmos lá, precisamos ter certeza de que estamos olhando para o tipo de dados correto, certo? Então eu vou chamar isso criar folha para VM e deixar tipo. Vá em frente e inclua todas as referências que faltam. Então crie folha para o tipo de folha VM. Nós vamos tentar obter uma resposta da folha que ponto repositório criar tipo folha. E então, se nossa operação for bem sucedida, então podemos redirecionar para o índice. Tudo bem, então olhe para este nulo. Se fizermos esta chamada, se foi um sucesso, então podemos operar como se fosse um sucesso. O que acontece quando ele falhou? Então, quando ele falhar, gostaríamos, é claro, de adicionar nossos erros de validação à interface do usuário. Então as flechas teriam voltado com a resposta. Então você pode dizer estados de modelo, erro de modelo, erros de validação de resposta. E no final de tudo isso, nós apenas devolvemos a vista. Então nós vamos modificá-lo um catch para não retornar a vista tem um fato de confusão Eu vou modificar o catch, o catch uma exceção real, e então nós podemos adicionar essa exceção. Então isso fica a seu critério. Claro, isso depende da experiência que você deseja que seu usuário tenha, porque você pode não querer necessariamente que eles vejam os detalhes dessa exceção. Você provavelmente poderia colocar algo que diz que algo deu errado, entre em contato com seu administrador. Mas no final desta operação, você deseja retornar a exibição. E você pode até colocar de volta os dados do tipo de folha que acabaram de ser enviados. Para a exibição para que ele tenha o que exibir para o usuário. Então vamos levar esse para uma spin art para que possamos executar o aplicativo, saltar para o nosso Create. E eu vou criar compassivamente com o número padrão destes Sten. Digamos que cometi um erro e coloquei muitos zeros. E, em seguida, clique em Criar. Você verá aqui que estamos recebendo de volta nossa mensagem de validação. E tenho certeza que esta mensagem parece muito familiar. Eu não tenho digitado esta mensagem desde que eu tenho vindo a construir esta interface de usuário. Isso vem diretamente da API. Então, isso é apenas para mostrar como as informações viajaram a partir da API e como poderíamos ser divididos para o usuário que o APIC, Isso é ilegal. Agora você tem duas opções quando se trata de validação. Você pode querer confiar na API para toda a sua validação e suas mensagens e assim por diante. Mas, em seguida, a coisa é que você em alguma API é cobrado por chamada. Tudo bem, então nesta situação em que você provavelmente está construindo em cima de uma API que você não quer muito tráfego ou os usuários da API dizem que você fez em muito tráfego ou seu limitado ou algo assim. Bem, você pode fazer é usar a documentação da API e impor a validação do lado do cliente. Então esta mensagem está vindo diretamente da API. Claro. O que então isso significa que uma chamada API foi feita, algum processo foi feito, e atirou Buck com essa mensagem. Tudo isso poderia ter sido evitado se eu ler a documentação como o desenvolvedor do aplicativo cliente e configurar minhas próprias regras de validação do lado do cliente. Então, isso nunca chegaria à chamada de API até que isso seja válido pelos padrões do cliente. Agora, há microfones. Com base na sua intuição, você terá que fazê-lo de uma forma ou de outra. Mas, por enquanto, deixamos a API fazer a validação. E então eu acho que é sempre bom construir a validação na API porque essa é a última linha de defesa antes, ou pelo menos nas centenas, essa é a última linha de defesa antes de obter o banco de dados. Então aqui você quer ter certeza que apenas coisas válidas recebe o banco de dados. No entanto, você pode incentivar seus consumidores de API a seguir as regras de validação. Então combustão no número padrão destes 10 con, continuar com a criação e olhar para isso. Nós temos um novo tipo de folha, então a criação funcionou e, em seguida, uma página de índice carregada e recarregada e estamos de volta aqui. Não se importe com a identificação. Aconteceu alguma experimentação. Buck em ambos, pelo menos, estamos confiantes de que isso está funcionando. Agora, alguém voltou e disse que compassivamente deveria ser 15 dias. E tudo o que precisamos para ir em frente e editar. E todo o primeiro passo é realmente criar a exibição. Portanto, visualize diretamente na edição de exibição. E sabemos que estamos usando a VM de edição e o tipo de folha. E então uma vez que você tem tudo isso no lugar, você pode ir em frente e adicionar. E, em seguida, na edição que você percebe, assim como com create, temos dois métodos. Nós temos o post e nós temos os gets, conhecendo o Get. Isso significa que ele tem que obter o necessário para ser editado. Bem, como conseguiremos esse disco? Já sabemos como conseguir uma lista de registros. Nós olhamos para obter um registro ainda, mas qualquer coisa legal que temos o direito de obter o único registro aqui é praticamente o mesmo legal ter que escrever para obter o único registro aqui. Então o que vamos fazer é dizer que o modelo var é igual a 08 tipo de folha de repositório ponto obter detalhes do tipo de folha. Assim, os detalhes trariam todos os campos que são necessários para uma operação de edição. O ID, o, você sabe, os campos, todos os campos, o nome dos nomes dos campos estão iludindo Marino, mas estamos recebendo de volta todos os detalhes para o tipo de folha que ele está prestes a ser editado, então nós estamos retornando a exibição com esses dados. Então, enquanto eu fiz este ano para as edições, eu realmente vou fazer de novo para os detalhes porque é a mesma coisa. Detalhes. Conseguimos os detalhes. Chegamos ao ID, passá-lo junto, e então retornamos a visualização com esses dados. Tudo bem, então vamos em frente e fazer isso, editar para obter. E, em seguida, para o post vai olhar um pouco semelhante ao nosso Criar, exceto que nossos parâmetros devem ter o int id e deixar tipo VM. Tudo bem, então ID folha tipo VM e eles estavam tentando obter uma resposta do nosso tipo de folha de atualização. E então passamos o ID e o objeto a ser editado. E se foi bem sucedido, então retornamos ao índice. Caso contrário, nós basicamente apenas cadeia de margarida e todos os erros de validação, assim como fizemos com a criação. E então retornamos a exibição com os dados que foram enviados. Então vamos começar a operação de edição e fora do ônibus você pode ver que há algumas taxas que não precisamos. Por exemplo, nós definitivamente não precisamos exibir o ID desta forma, de uma forma aditiva para o usuário Isso nem vai funcionar. Ou API rejeitaria isso completamente. O banco de dados rejeitaria para espalhar o nome. Número padrão de dias. Foi tudo o que dissemos. Precisávamos mudar os 15 e eu só estou curioso para ver o que exatamente vai acontecer se eu tentar isso, se eu clicar em Salvar, Tudo bem, então eu estou recebendo essa Sra. de valor não pode ser nula. O valor não pode ser nulo. Ok? Deixe-me alterar isso de volta para 10 e deixe-me clicar em Salvar. Tudo bem, então funcionou. Deixe-me rever o que essa mensagem significava. Se os dados forem inválidos. Lembre-se que nosso manipulador que está lidando com a atualização, certo? Não, foi, ou pelo menos originalmente foi projetado para lançar a exceção de validação quando os dados eram inválidos. Então voltar para aquele manipulador faz QI e ver o que eu quis dizer. Não devolvemos nada. Era apenas a unidade ou em que explicamos era apenas algo a dizer. Está tudo bem. Mas quando o resultado da validação era inválido, lançamos uma nova exceção de validação. Agora essa exceção de validação não foi tratada. Nós não escrevemos qualquer cotação real para lidar com o que acontece quando nosso manipulador lança uma exceção segurar a API lida com ele e como tudo o resto vem para baixo. Então, entre o manipulador lançando a exceção, o AICPA e auto sendo manipulação de erro global para saber que tipo de respostas em dólar. E então a concessão de serviço não ser capaz de entender que tipo de resposta é essa, então nós estamos recebendo esse tipo de erro. Então, tecnicamente, você não necessariamente tudo o que você não gostaria de usá-lo para ver um erro como este. Este é, na verdade, o erro que volta de todo o try catch e a mensagem de exceção que está sendo lançada de volta para a validação do estado do modelo. Você não iria querer usá-lo para ver isso. Mas mais tarde, quando olharmos para a manipulação de exceção global vai ver como podemos melhor ou fornecer melhor feedback quando exceções são lançados através do manipulador ou através da API todo o caminho de volta para a interface do usuário sem que tenhamos para compensar muitos cenários. Tudo bem, mas para todos nós realmente vemos que a validação está funcionando até certo ponto ele está falhando porque se eu colocar um ponto de interrupção aqui neste manipulador, e então eu clique em Salvar novamente, Oh, nozes no modo de depuração. Ou podemos fazer isso mais tarde, mas você pode tentar que coloque um ponto de interrupção dentro do manipulador. Tente isso, veja se você veria que ele atinge a validação não está lá. Desculpe, a validação é falsa. E então ele vai jogar o dólar exceção. E se você passar e segui-lo até o fim da linha, você verá por que tudo isso equivale a esta mensagem muito vaga. No entanto, vemos que a edição está funcionando corretamente. E na próxima parada. Nós já analisamos os detalhes para que você possa avançar e gerar a exibição de detalhes. Eu já tenho o meu, e você verá que entre o código que acabamos de colocar no controlador e você está gerando a visão, você pode ver os detalhes. Então o próximo seria deletar. Saber para a exclusão geralmente armazenado em um passo de duas vezes em aplicações MVC, certo? Então, geralmente você obtém o registro e mostra ao usuário como em uma exibição de detalhes e diz, você tem certeza de que deseja remover esse registro? E então eles diriam sim, e então ele basicamente submete um formulário. Então esta é uma maneira muito segura ou a melhor maneira de fazê-lo. Deixe-o enviar o formulário. Então, um porto que pelo Tolkien anti falsificação e que iria levar adiante essa operação de exclusão. Não, o que eu faria, ou há várias maneiras de abordar isso. Mas o que eu fiz várias vezes é em vez de usar tanto o bom eo post, Eu só tenho o post, certo? Então é assim que o meu método de exclusão se parece. E se você olhar para ele, você vê que ele se parece muito com o, tudo o resto que o editor eo criador outro. Então tentamos, obtemos a resposta. Se for bem sucedido, então redirecionamos para a página de índice e, em seguida, eu estou apenas retornando pedidos de bytes. Então a praia, o aplicativo seria apenas sentir, mas vamos olhar para como lidar com isso mais tarde quando olharmos nossas modificações para nulo, no entanto, na página de índice, o que eu faria é em vez de ter este link axônio, Eu realmente embrulharia isso em uma fazenda. Mais uma vez, há muitas maneiras de fazer isso porque algumas pessoas têm a forma passando e passando. Algumas pessoas têm um formulário e usam JavaScript para vê-lo quando você clica no botão Excluir e, em seguida, exclui o farm. Mas agora, vou manter as coisas simples o suficiente para passar por isto. Então este é um botão de exclusão. Tudo bem, então eu não queria aborrecê-lo com a minha digitação, então eu fui em frente e terminei o topo. Então, nosso formulário se parece com isso, onde formulário é Opção, Excluir é B traço, ID de rota é item.name. Usando isso no sinal para facilidade de uso. E método é igual a postar. Então, entre estes três vai saber que ele deve ter como alvo o método post do nome axônio e passar nesse ID. Então, ele sabe postar e excluir com esse ID. E então o que precisamos fazer é colocar o botão para cima. Então tipo de botão enviar e eu dei-lhe a classe btn, btn linha tracejada. Então parece que os outros dois links, então parece uniforme. Ninguém jamais saberia que é abortar e a menos que eles realmente vão para o código para ver. E, em seguida, ao clicar, estamos retornando em uma janela firme. Tem certeza de que deseja excluir? E então passamos a palavra excluir. Então vamos dar uma olhada no que isso torna. Tudo bem, então isso é o que nós não temos completamente alinhados. Podemos consertar isso mais tarde, mas a questão é que estamos recebendo o botão de apagar. Então eu tenho um muito aleatório aqui. Acho que alguém estava tentando falsificar o sistema e eles entraram nisso, então tudo bem. Vamos apagá-lo. Tem certeza de que deseja excluir esse registro? Ok. E então você vê que tudo aconteceu. Esse recorde não está mais lá. Isso significa que nossa operação de exclusão funcionou com sucesso. E com isso feito, acabamos de completar a multidão para nossos tipos de folhas através da nossa interface de usuário. Tudo bem, então quando voltarmos, vamos ver como podemos completar outras operações específicas com as solicitações de licença e as alocações de licença. 31. Adicione código web do Json (JWT) à API: Ei pessoal, bem-vindos de volta. Nesta lição vamos falar sobre autenticação. Agora, a próxima etapa lógica a seguir ou a configuração da interface do usuário do tipo de folha teria sido resolver a alocação de folhas e deixar as UIs de solicitação. Mas, em seguida, o plano falado é que, a fim alocar licença ou solicitações de licença precisamos de usuários ou funcionários. Então, a única maneira de conseguirmos que o empregado veja o sistema é se eles tiverem logado e soubermos quem são, essa é a esposa dele. A autenticação precisa vir antes desses dois outros recursos. Então eu meio que fui em frente e implementá-lo porque há um pouco de código para escrever e eu não quero aborrecê-lo com me ver digitar. Então, é claro que eu vou passar por isso muito lentamente para que você possa pausar, replicar e explicar tudo o que está lá que precisa ser entendido. - Não. Fora disso, eu tenho swagger onde eu implementei a autenticação JWT, então eu apenas tê-lo para que você possa obter uma visualização do que autenticação JWT realmente é no caso de você não estar muito familiarizado com ela. Então vamos J, W e T são abreviação de JSON Web Tokens. E o que eles são é como um pacote, apenas uma string plana que está codificada. Mas dentro desta string codificada estão o que você chama de bits de informação são reivindicações que permitem o acorde D e saber quem é o usuário. Nenhum JWT é amplamente utilizado na fraternidade API como o padrão de segurança porque permite autenticação sem estado. Ou seja, quando você faz login, você não está realmente fazendo login em uma camada de API acessando a API. Mas se é osso lote ou protegido e você autenticar na API e eles basicamente identificam quem você é e, em seguida, enviar este token com todas as informações sobre quem você é. Então o aplicativo cliente agora precisa ver a qualquer momento que eu estou usando o aplicativo cliente e eu solicitar dados da API, ele precisa incluir este token com minhas informações para que cada vez que a API é chamada, quando vê este token, ele irá decodificar, verificar se esta pessoa é válida e, em seguida, ser capaz de executar na solicitação. Então, apenas uma demonstração rápida aqui, eu vou tentar fazer login. Então eu já modifiquei o swagger, eu já modifiquei a API com os pontos finais de login e registro e nós vamos passar por isso. Mas eu também coloquei em alguns usuários de amostra. E eu vou apenas ir em frente e mostrar como é o símbolo. Então, estou executando uma solicitação de login com um de meus usuários. E você vê aqui que está devolvendo 200 com essa resposta simbólica, certo? Então eu recebo o ID do usuário, o nome de usuário, o e-mail. E este é aquele JWT ou token, certo? Então este é basicamente um veículo com todas as informações necessárias para me identificar. Então, apenas para mostrar o que surge neste token, eu vou saltar para JWT dot IO, que é uma ferramenta livre legal que você pode usar para apenas colar seu Tolkien aqui. É forma codificada e, em seguida, para a direita ele vai essencialmente tudo o que está neste token. Então sujeito, esse é o endereço de e-mail, GTI, que é o identificador JWT. Sim, o e-mail, você tem, o ID do usuário, as funções que exploram timestamp, o emissor e o público. Então você pode colocar mais coisas. Estas são apenas coisas básicas que este token que estamos gerando vai ter. Mas daqui para frente, você pode colocar em mais coisas e colocar todas as informações que você julgar necessárias para o seu aplicativo ou sua API para funcionar. Agora vamos começar com a nossa arte de código. Então, em primeiro lugar, eu vou chamar a sua atenção para, e eu vou apenas derrubar tudo o que não é absolutamente necessário para o, para a conversa em mãos para que seja menos confuso. Então, em nosso projeto de aplicação, você deseja adicionar uma nova pasta na pasta modelos chamada identidade. Saiba quando adicionar esta pasta que diz que eu deveria ter colocado as configurações de e-mail e e-mail em uma pasta para si, mas podemos fazer isso mais tarde. Coloque-os em uma pasta chamada e-mail ou e-mail, algo assim. Mas para uma identidade de todos os modelos e, em seguida, temos esses novos arquivos. Então temos solicitação de autenticação, que é basicamente apenas e-mail e senha. Acabamos de ver que quando estávamos fazendo login através do swagger, colocamos o e-mail, colocamos a senha, e então a enviamos. Então é para isso que serve a solicitação de autenticação. Auth resposta é o que temos buck através swagger, o ID, nome de usuário, o e-mail, e a string token. Tudo bem, as configurações do JWT, isso tem que fazer é semelhante às configurações de e-mail. Lembre-se que queremos as configurações de e-mail da parte do arquivo Up settings.js ON que nos deu todas as configurações necessárias para o e-mail. Bem, isso é o que vai acontecer com as configurações do JWT. Então vamos ter um problema importante ou um público e uma duração em minutos, todos sendo referenciados no arquivo de configurações UP em nossa API. Agora, assim como tudo o que temos a solicitação de autenticação, vamos ter a solicitação de registro. Muitas vezes é abreviação para autenticação, eu apenas encurtei, mas você pode ser explícito e dizer autenticação. Mas a solicitação de registro vai exigir o FirstName, o LastName, o endereço de e-mail, o nome de usuário, bem como a senha. Então, qualquer um que está se registrando no up e o novo funcionário que está entrando na empresa vai dizer a eles, você ainda pode agitar ainda mais. Você precisa fornecer essas informações. E, em seguida, a resposta de redistribuição é realmente apenas ir para trás com o ID de usuário. Então, depois que essa pessoa se registrou lá no sistema, nós apenas enviamos o ID do usuário. Isso é tudo o que é necessário. Não, fora disso, também queremos uma nova pasta na pasta Contratos, e estou chamando de identidade. E queremos que eu auth serviço. Então, vamos ter um novo serviço onde temos login de resposta do autor da tarefa. E leva esse objeto de solicitação de solicitação de autenticação. E então temos um para distribuição que está nos dando a resposta de registro. E tem uma busca de redistribuição. E isso é realmente tudo o que é necessário para o aplicativo. Então você pode ir em frente e rever se você precisar. Claro, pausar enquanto você está indo junto para certificar-se de que você está recebendo todos esses arquivos e os campos necessários. E observe os atributos de validação que estão na solicitação de registro porque queremos ter certeza de que estamos atendendo aos padrões mínimos. Nem nossa próxima tarefa nos fará adicionar um novo projeto à pasta de infraestrutura de TIC chamada Identity Art. Então, o ponto de gestão de RH identifica o nome, e gostaríamos que este fosse um ponto nele, cinco. Então eu vou explicar isso. Sim, estamos usando o padrão dotnet para a maioria das bibliotecas de classe. Mas neste caso vamos precisar de certas bibliotecas que simplesmente não podem trabalhar com uma biblioteca padrão dominante. Então queremos dotnet fire para que tenhamos 0 problemas de compatibilidade. E, claro, isso continuaria em versões futuras do mesmo. Então você pode ir em frente e adicionar esse novo projeto. Já o tenho aqui. E neste novo projeto, vamos ter algumas pastas novas. Teremos configurações, migrações, modelos e serviços. Temos novos arquivos onde temos a redistribuição dos Serviços de Identidade. Estamos familiarizados com isso onde estamos sentados desse arquivo de registro para ser chamado a partir da API. E também temos nosso próprio contexto de banco de dados. Então eu vou começar com um contexto de banco de dados porque este é provavelmente o mais fácil. Então, no contexto de banco de dados, temos id de gerenciamento de licença de classe pública, identidade, contextos DVI herdando do contexto de banco de dados de identidade. Observe aqui que estamos digitando o contexto do banco de dados de identidade. Então eu poderia ter feito isso, mas eu tenho uma classe especial de substituição para meus usuários. De modo geral, o usuário de identidade não tem taxas extras como FirstName e LastName. Então eu tenho essa classe de usuário aplicativo que eu criei na pasta modelos. E herda do usuário de identidade. Então tem dois campos. Nome, Apelido. Em sua situação, talvez seja necessário que seus usuários tenham mais informações sobre o nome, sobrenome e e-mail. E então talvez você queira a data de nascimento, você quer outros campos. Você pode adicionar todos esses aqui. Mas, enquanto você está herdando da identidade usuário aplicativo usuário pode ser usado para substituir usuário identidade e operação relacionada ao usuário. Estes dão acesso a todos os campos necessários. Então, voltando para o contexto do banco de dados, temos o mesmo tipo de construtor que você teria visto do nosso contexto de banco de dados anterior, onde estamos tomando as opções de contexto do banco de dados e que será Páscoa através da API projeto no perturbador mais uma vez. E então temos o modelo em criação. Então, desta vez eu não vou fazer isso, começa a reunião. Estou chamando as abelhas na criação de modelos. E depois vou chamá-los um por um. Na prática, realmente não importa. Então vamos continuar. Então, temos a configuração da regra, a configuração do usuário e a configuração da função do usuário. Então é aqui que eu estou semeando esses bits de dados ao gerar este banco de dados. Então lembre-se que eu disse que gerou usuários antes. Então, se passarmos para a pasta de configurações, você verá configuração de função onde eu tenho configuração regra herdando de I função de identidade de configuração tipo de entidade. Agora este está configurado para configurar novas regras. Temos o ID, o nome da regra e o ID do nome normalizado. Isso só precisa ser bom para que você possa ir e obter o nosso bom Dino aleatório, gerar um online, tudo bem. Você pode usá-lo lá. Você não tem que usar o mesmo. Eu comprei. Estes precisam ser bons. Portanto, nossas tabelas de identidade não usam inteiros como seus IDs. Depois de terminar com as funções, você gostaria de cuidar dos usuários. Então, os usuários, há um pouco mais para ele, mas é realmente apenas um pouco mais porque há mais para preencher, mas é praticamente o mesmo conceito, a configuração do usuário herdando de uma configuração de tipo de entidade relativa para o usuário do aplicativo. E, em seguida, em nosso método de configuração, temos var Hampshire é igual a nova senha Hampshire, relativo relevante, desculpe ao usuário do aplicativo. Então isso vai ser usado para hash a senha. Então, estamos preenchendo para usuários de aplicativos mais uma vez recebe um bom, estamos dando a este o e-mail e e-mail e e-mail normalizado e nome de usuário, nome usuário não normalizado, eles são todos iguais. A única diferença é que as versões normalizadas têm todas as maiúsculas. Se você está familiarizado com o usuário de identidade, então eu não vou, eu não quero aborrecê-lo, mas você meio que vê que estou preenchendo todos os campos de acordo. E, em seguida, para o hash de senha, estou usando o HobShare para hash da senha null para o primeiro parâmetro. Não precisamos passar no usuário do aplicativo. Obviamente não podemos porque estamos apenas criando um. Mas vamos trocar a senha, certo? Então, estou usando minha senha padrão especial que geralmente atende aos requisitos mínimos para criar nosso usuário na identidade. Então temos esse para o administrador e, em seguida, temos outro para um usuário regular. Então, depois de termos nossos dois usuários sob duas regras, eu tenho usuário ou configuração, que é praticamente I tipo de entidade configuração na função de usuário entidade. E então você passa essa digitação por uma string. Muito importante. E então temos duas novas funções de usuário de identidade. Temos o ID da função para o ID do usuário, ID regra para o ID do usuário. Então isso é ver a função, eu acho que esta é a função do funcionário para o usuário que supostamente era o funcionário e, em seguida, o ID da função para o ID do usuário. Então, porque este tipo de tem que acontecer em ordem que precisamos que a regra que precisamos usar são todos antes do usuário ou é gerado. Então eu acho que é por isso que eu apenas explicitamente afirmei as configurações como esta. Então ele não iria executar esta corrida que, em seguida, executar aquilo. Agora, antes de ir mais longe, só queria 0 músicas as bibliotecas que você vai precisar neste projetos apenas para que você tenha no topo tantas linhas vermelhas. Então, queremos ter certeza de que temos uma velocidade dotnet Core Authentication, portador JWT, queremos uma identidade central, identidade Entity Framework, Core Entity Framework, Core dot SQL, as ferramentas, as extensões para as configurações Newton ponto JSON e system.out.print modelo da cidade, JWT de Tolkien. Então você provavelmente já incluiu alguns deles porque ao configurar o contexto do banco de dados e alguns dos outros arquivos, você teria sido solicitado que você precisa de certas bibliotecas. Então, se você já tem isso, tudo bem, mas essas são as bibliotecas que você precisará no geral. À medida que você avança, você pode simplesmente incluir o ausente usando instruções e referências em conformidade. Então, vamos passar para a implementação do nosso serviço de Auth. Então temos o serviço de autenticação na pasta Contratos. Agora temos a implementação. Estamos acostumados com a coluna vertebral. Tudo bem, então temos três campos são, bem, vamos começar com o construtor e como estamos injetando o gerenciador de usuários. Estamos injetando o gerenciador de login e estamos procurando opções para a seção chamada configurações JWTs. Então você pode simplesmente ir em frente e criar esses três campos. E então em nossas implementações temos login e registro, e temos alguns métodos privados, mas vamos passar por eles um por um. Então, em nosso login onde tomar a solicitação de autenticação, então eles são memoráveis que isso vai ser chamado a partir da API, na verdade. Então, quando alguém atinge o ponto final de login ou quando eu acertei o ponto final de login, basta saber que a API realmente apenas chamar esse método que em seguida, fez as verificações e retornou a arte de resposta. Então, tentamos obter o usuário, se o usuário não tem que existir, lançamos uma nova exceção, Então estamos usando exceções aqui mais tarde vamos olhar para o tratamento de exceção adequado, Global Exception Handling para a API. Mas, por enquanto, usaremos as exceções e refinaremos à medida que avançarmos. Então, se o usuário não for encontrado, lançamos uma exceção, não foi possível encontrar esse usuário. Se o usuário for o telefone, tudo bem. Mas depois tentamos inscrevê-los. Se eles não puderam ser salvos, isso é apenas mais uma exceção. Agora, se passarem todos os cheques, a próxima coisa seria gerarmos o Tolkien deles. E é aí que entra este método privado, Generate token. Então eu vou pular para baixo para esse método para que você possa ver exatamente o que toda essa coisa de geração Tolkien é tudo sobre. Então vamos devolver o kit de ferramentas de segurança JWT que vem na biblioteca para o modelo de identidade JWT de Tolkien, certo? Então você pode, como eu disse, incluir todas as declarações usando uma vez que você tem o seu spinning dificilmente. Prompt do Visual Studio. Hoje você precisa consultar a biblioteca de efeitos. Então estamos gerando o Tolkien ou estamos analisando no usuário do aplicativo que foi telefonado. Certo, então o usuário caiu aqui e conseguiu entrar. Então estamos passando por cima desse usuário. Sabe, nós recebemos as reivindicações. Portanto, as reivindicações podem ser armazenadas no banco de dados. Jogos, mais uma vez, são bits de informação sobre o usuário. Você pode basicamente armazenar qualquer coisa como eu limpo o usuário em um pouco de informação que você precisa para o seu aplicativo para executar, você pode adicioná-los aos gritos do usuário. Isso está fora do escopo deste curso, mas eu estou apenas dando a vocês uma idéia do que uma reivindicação realmente é. Então está fora de informações sobre o usuário no banco de dados. Vamos pegá-lo rolos. Queremos todas as regras porque um usuário pode ter vários usuários Rosa pode ser um funcionário e um administrador. Como se eu fosse um supervisor do que eu poderia ter que ser um supervisor inferior também um funcionário para que eu possa aprovar pedidos de licença. Talvez o que eu também pode fazer pedidos de licença porque eu estou ambos certo, Então funções podem ter várias funções para o nosso usuário recebe todas as regras. Então, vamos agora apenas criar uma nova lista de reivindicações. E então vamos adicionar à lista de reivindicações todas as regras. Então você vê, nós estamos apenas adicionando novas reivindicações chamadas regras para papéis são, na verdade, há, deixe-me me livrar dessa string mágica porque há realmente uma constante que podemos usar para ter certeza de que estamos recebendo o tipo de regra de carrinho Nino Evite erros de digitação que já discutimos por que não queremos nenhuma, nenhuma corda mágica, certo? Então eu posso adicionar os tipos de afirmação rolo ponto e tipos reivindicados é apenas uma constante que tem diferentes tipos de reivindicações que são usados principalmente em toda parte. Tudo bem, então você sempre pode dar seu próprio nome para limpar, mas então há certos padrões que você sempre pode procurar e você pode apenas olhar através e ver qual deles é relevante. Mas neste caso, estamos adicionando papéis. Então eu vou usar o tipo de reivindicação para rolar. Tudo bem, então eu vou construir outro IRI de reivindicações onde eu estou vendo nucleon é igual a nossa nova reivindicação, é JWT registrado nomes reivindicados. Então você reivindicou tipos versus JWT registrados reivindicações. Então JWT registrou basicamente reivindicações. Estas são afirmações específicas do JWT que geralmente são usadas para aplicações em geral. Tudo bem. Então, esses são padrões diretos de DWT versus tipos de creme, que não é necessariamente relacionado com JWT, o que aqueles usuários relacionados. Então você pode combiná-los porque todos eles se resumem ao mesmo tipo de reivindicação. Então nós temos as funções e estamos adicionando nomes limpos registrados DWT. Sabonete. Sabonete é abreviação de assunto. Tudo bem? E isso é geralmente falando, os usuários, os usuários nome de usuário ou seu e-mail, o que é único. Você vê GTA, que geralmente é apenas essa boa string, e depois o e-mail, que é auto-explicativo. Então eu estou adicionando minha própria reivindicação aqui onde eu chamo o UID ou ID de usuário, que é o valor de ID real do banco de dados. Então você vê que você pode construir suas reivindicações. Você pode colocar em como muitas reivindicações, você pode colocar em seus nomes personalizados, se você quiser. Mas mesmo que eu tenha uma corda mágica aqui, eu sugiro que se você tiver várias reivindicações personalizadas que você precisa adicionar, não adicione as cordas mágicas, coloque-as em outra constante. Colegas de classe é como você vê as constantes aqui e, em seguida, referi-los em conformidade. Então você teria sua constante como tipos de limpeza personalizados, ID de usuário de ponto, algo assim. E ele OMS depois de construirmos essa área, nós vamos apenas ponto união as reivindicações do usuário do banco de dados e as reivindicações de função, e então tudo está agora neste IRI. Então, descendo um pouco mais, o que precisamos fazer é codificar nossa chave de assinatura. Então, quando chegarmos às configurações do JWT, você verá que há uma chave que seria exclusiva para o seu aplicativo. E há muitas maneiras que as pessoas usam para armazenar a chave nessa configuração. Nós vamos apenas usar settings.js, sun, algumas pessoas armazená-lo como uma variável de ambiente. Fiz isso no meu curso definitivo de desenvolvimento de API. Então você verá várias maneiras de fazê-lo. Então, tudo o que realmente estamos fazendo aqui é assiná-lo. E o que queremos fazer também é usá-lo para determinar as credenciais de login. Certo, entre essas duas linhas, temos as credenciais de entrada. Então este pouco de ruído de código onde nós realmente geramos nosso token de segurança. Então, o token de segurança JWT é igual ao novo emissor de token de segurança. E isso vem da nossa audiência de configurações JWT. Isso também vem de nossas configurações e afirma que acabamos de construir em nós mesmos, expira. Estamos convertendo de data-hora saber onde adicionar os minutos provenientes das configurações JWT. Mais uma vez. E então estamos adicionando as credenciais de login, que acabamos de determinar aqui usando essa chave de assinatura. E depois devolvemos aquele Tolkien. Então, uma vez que devolvemos esse Tolkien, ver muito quando feito nesse método. Depois que transformamos esse Tolkien, então construímos nossa resposta do autor, que tem o ID do usuário, o token que acabamos de construir. E tome nota do acorde aqui, novo manipulador de token de segurança JWT ponto direito Tolkien e segurança JWT Tolkien e o e-mail e o nome de usuário, e então retornamos essa resposta. Então essa foi a resposta que recebemos do Swagger com o ID, o Tolkien, o e-mail e o nome de usuário. Então, agora que fizemos todo aquele trabalho pesado entre os serviços e, você sabe, todo esse código que pula para os Serviços de Identidade ou um arquivo de distribuição onde configuramos os Serviços de Identidade. Então, como fizemos em tempos anteriores, vamos precisar da coleção de serviços de IA e da configuração I. E movendo-se para baixo, veremos as diferentes seções. Assim, os serviços ponto configurar em relação às configurações JWT. Estamos procurando na configuração para obter a seção chamada configurações JWT. Estamos adicionando contextos RDB que estamos familiarizados com isso. Então você pode simplesmente copiar, colar esse código, apenas certificar-se de que você está fazendo referência ao arquivo de contexto do banco de dados correto. Portanto, é deixar os contextos do banco de dados de identidade de gerenciamento, que é o que acabamos de criar para esse projeto específico. E estamos adicionando o SQL Server. Deixe-me baixar a cota. Você pode ver que é um pouco mais fácil. Portanto, as opções que usa SQL Server obter seqüência de conexão, e isso é o que eu estou chamando a seqüência de conexão deixar a seqüência conexão Identidade de Gerenciamento. Agora, a coisa legal sobre isso é que você pode realmente ter dois armazenamentos de dados completamente diferentes. Se você precisar ter um armazenamento de dados para seus aplicativos separado de um armazenamento de dados para seus usuários. Então este é, É assim fácil separá-los porque tudo que você precisa é uma cadeia de conexão para um banco de dados e outro para outro. Estamos referenciando a outra cadeia de conexão. Então eu realmente vou estar separando esses armazenamentos de dados e você verá isso em alguns minutos nas configurações do aplicativo. Então, se você deseja usar o mesmo banco de dados para ambos, então você só precisa da mesma string de conexão. Sem pressa. Também estamos especificando que o assembly de migrações está no mesmo assembly que o contexto de banco de dados, é por isso que temos essa pasta Migrações. Também temos serviços que adicionam identidade, onde estamos vendo que a identidade que estamos adicionando é usuário do aplicativo para a classe de usuário de identidade e função de identidade. Estamos adicionando a estrutura, o armazenamento Entity Framework para ser o nosso contexto de banco de dados que foi inicializado no topo. E estamos adicionando provedores de token padrão. Então, isso adiciona provedores de token usam para gerar para redefinir senhas G e Gmail, todas essas coisas. Tudo bem, então qualquer se você tiver que fazer essa ferramenta, confirmar, enviar e-mail ou redefinir senha, esse tipo de coisa. Esta biblioteca, vamos facilitar os provedores de Tolkien para você. Estamos nos serviços e eu estou adicionando este como transitório porque queremos um novo serviço de autenticação cada vez que uma solicitação entra. Então, não tem escopo desta vez. Ele me deu um novo a cada vez. E nós somos apenas vinculativos ou abstração ou implementação. E então chegamos aos serviços que adicionam autenticação. Então, aqui nós especificamos opções onde temos opções não esquema de autenticação padrão é JWT cerveja padrão esquema de autenticação e esquema Desafio padrão é a mesma coisa. Certo, então é assim que dizemos ao esquema de autenticação para usar o JWT. Depois disso, nós estamos adicionando as opções de cerveja JWT onde eu estou vendo os parâmetros de validação Tolkien são como tal. Em cursos anteriores onde eu passei por WTI era distrito mais estreito, mas mais uma vez, contexto determina a sua implementação. Então, para nossos parâmetros de validação Tolkien, eu vou precisar validar nossa chave de assinatura, o emissor, o público, a vida útil, a inclinação do relógio, que faz com que nossos sets o relógio ao aplicar um tempo de validação. Então, em relação a onde você está, como aplicamos isso? Tempo de validação, validar a CE desculpe, emissor dividido é encontrado na configuração para o emissor de dois pontos configurações JWT. Portanto, esta é uma boa maneira rápida de obter um valor específico da nossa seção de configurações em um arquivo de configurações de aplicativo. Tudo bem, então nós estamos recebendo o emissor e o público tanto da seção de configuração JWT e, em seguida, nossa chave de assinatura do emissor. E vimos algo assim antes, onde fazemos a assinatura de chaves de segurança simétricas para essa chave que também é encontrada nas configurações JWT sob a chave de nome, então retornamos os serviços. Tudo bem, não isso, mas agora que fizemos tudo isso em nossa identidade, podemos saber, conectá-lo com a API. Então, na API, vou começar com nosso arquivo de configurações do aplicativo. Então, mais uma vez, temos duas cadeias de conexão. Tenho duas cordas de conexão. Você poderia ter um, se quisesse. Sem problema. Mas eu tenho um chamado banco de dados de gerenciamento de licença de RH, que estavam acostumados. Eu então adiciono 14, a identidade que eu acabei de acrescentar na identidade quadrada a ele, certo? Portanto, não é realmente grande coisa, dependendo das necessidades do seu negócio, você pode precisar separá-las. Um caso para quando você gostaria de separá-los seria se temos vários aplicativos usando a mesma loja de usuários. Então, nessa situação, então você pode querer um banco de dados autônomo estritamente para informações do usuário. E, em seguida, os diferentes bancos de dados são relativos aos diferentes aplicativos. Mas todas as operações poderiam se inscrever no armazenamento de um usuário e usando a mesma biblioteca de identidades que eu acabei de configurar e as mesmas cadeias de conexão foram resolvidas. Cada aplicativo poderia tirar proveito dele com bastante facilidade. Seria agnóstico para quem realmente está interagindo com ele. Então nós temos nossa cadeia de conexão e mais tarde não no arquivo, eu tenho a seção de configurações JWT. Então aqui eu só tenho uma chave. Mais uma vez, esta chave pode ser qualquer coisa, pode ser uma palavra, pode ser algo como uma senha, mas não é algo que você queira que alguém adivinhe facilmente porque então as pessoas poderiam falsificar seu Tolkien se souberem sua chave. Então é por isso que eu disse que às vezes as pessoas não armazenam em coisas opostas. Eles armazenam como uma variável de ambiente ou como um Application Secret, outra coisa. Mas, por enquanto, eu só estou colocando aqui porque é nosso aplicativo, mas você sabe como armazená-lo. Mais segurança precisa ser o nosso emissor. Eu só estou vendo cada um dos nossos líderes de gestão e o público seria usuário de gerenciamento de licença de RH. E a duração é de 60 minutos, que significa que este token é válido por exatamente uma hora. Depois de uma hora, você precisará de um novo token, você precisará fazer login novamente. Então é sua discrição que você se sente desta vez. Algumas pessoas o definiriam por dias, depende de você e de sua política de segurança. Agora vamos saltar para os controladores de cones no controlador de cólon Estou injetando o serviço de autenticação ocular. E você pode ver que é um controlador muito simples. Lembre-se, magro Gonzalez, esse é o nosso objetivo, certo? Então não há nada, nenhuma lógica, nenhuma operação séria acontecendo aqui. Estamos apenas implementando resultados de ação. Um que retorna resposta do autor em embora um que retorna ou uma distribuição na resposta. E então, basicamente, estamos apenas voltando. Ok, eu vou 18 o resultado do pedido de login. Mais uma vez, em nosso serviço de OSS educado, estamos lançando exceções. Então, mais tarde, veremos como avaliamos essas exceções e temos mensagens de retorno apropriadas quando nosso aplicativo cliente está chamando. Mas, por enquanto, isso é tudo o que precisamos para fazer login e registrar. E, em seguida, em nosso arquivo de inicialização, que é o segundo a último bit que realmente precisamos prestar atenção. Temos algumas mudanças em conformidade. Portanto, queremos que você configure nossos serviços de identidade. E para fazer isso, precisamos fazer referência aos projetos de identidade, certo? Então você será solicitado, ou se, se você não for solicitado, então, pelo menos, adicioná-lo como uma dependência do projeto quando você tiver a chance, e então isso estará disponível para você. Então, depois de termos configurado nossos serviços de identidade e outras mudanças que eu quero apontar é muito arrogante. Então eu mudei isso para um método que vai configurar o swagger porque há poucas coisas que vão ser diferentes. Como você percebe, meu médico de futebol era um pouco diferente das primeiras vezes que o usamos. E é por isso. Então, antes de chegarmos a este método, no configure para os middlewares, você deseja adicionar a autenticação de tecidos e você deseja verificar novamente se você usou autorizações. Então você vai querer ter certeza que você tem esses dois. Se nada mais. Dentro desta configuração, qualquer coisa é que você tem que permanecer inalterado. Conheça as mudanças no documento Swagger, e este é apenas o método privado implementado abaixo. Então, se eu derrubar esses dois, você vê a doca de futebol da Liga Árabe. É preciso que sirva de coleção. Então, na chamada do método estamos passando nos serviços e neste, não, estamos expandindo o que eram apenas os serviços que tinham futebol, Jen. Então não, estamos criando uma configuração no sangue onde estamos vendo definição de segurança AD para portador. Então isso significa que estamos dizendo swagger que sempre que algo é autorizado e nós vamos chegar à autorização citação unquote parte da API. O que, quando um endpoint é autorizado, então exija um token de portador. Esse é o nosso esquema de segurança para testes que autorizam o endpoint necessário. Nós apenas damos a ela aquela pequena descrição sobre um vaivém de verbiage, o usuário, isso é o que você precisa fazer. Autorização de nome. No local do perímetro é o cabeçalho. Então, o que quer que coloquemos, que é uma cerveja, vai no cabeçalho do pedido. E o tipo é uma chave de API, e o esquema é um espelho. Tudo bem, então isso é tão cortante Swagger. Saiba que se um endpoint é autorizado, mais uma vez, exigem uma cerveja Tolkien, e é assim que ele deve ser tratado. Em seguida, adicionamos os requisitos de segurança onde vemos novas aberturas. Uma API de referência Open API Security Scheme, Open API reference type é um esquema de segurança de tipo de referência chamado esquema portador off to name bear. Então você verá muitas das coisas que estão se repetindo. Então vá em frente e adicione essa seção. E então temos a mesma seção de Doc Swagger onde dizemos versão um. E o tipo é RH, gerenciamento de licença, EPA e colocar um pouco de espaço lá. Tudo bem. Então é basicamente isso. Então, se eu fosse autorizar e flutuar, então você me viu usar a API. Você me viu autenticar, mas não me viu autorizar e testar. Então isso é tudo que você realmente precisa para informar a API que ela deve bloquear tudo neste controlador. Se você não quiser que ele esteja em todo o controle, você pode colocá-lo sobre as ações específicas. Então, se obter os tipos de folhas não exigia que alguém se conectasse, então tudo bem. No entanto, se criar os tipos de folha exigia que alguém fizesse login e então você poderia colocá-lo diretamente sobre aquele post ou o PUT, etc. Não, estamos quase terminando com a configuração de nossos serviços de identidade. E neste ponto nós só precisamos deixar o banco de dados realmente existir e atualizá-lo com os dados relevantes, certo? Então eu vou no console do Gerenciador de Pacotes e certifique-se de que seu projeto de inicialização é a API e que o projeto padrão que está sendo referenciado aqui é o projeto de identidade. Certo, então o primeiro comando que você precisa executar é a migração de anúncios para os novos contextos BB de identidade. Então vamos dizer adicionar migração traço. O que temos nome de migração é, mas então eu estou especificando quais contextos essa especificação você pode obter um erro visto que existem vários contextos e ele não sabe qual deles usar. Então, para ter o nosso próprio que você acabou de dizer contexto holandês e o nome real do contexto. Depois de fazer isso, você obterá esse arquivo de migração gerado. E você terá as tabelas que estão sendo criadas, bem como os novos dados que estão sendo pré-implantados para as funções, os usuários e as atribuições de função de usuário. Tudo bem? Agora, depois de ter feito isso, você deseja fazer um banco de dados de atualização. Então o banco de dados vai parecer semelhante no sentido de que temos que especificar quais contextos estamos atualizando. Então você só diz atualizar banco de dados traço, contexto holandês e colocar em que contextos DVI identidade. E com tudo isso você não teria criado o banco de dados. Posso pular e mostrar-lhe o banco de dados de identidade de gerenciamento de licença de RH, com todas as tabelas que teriam sido criadas. Mais uma vez, separei o banco de dados do aplicativo do repositório do usuário. Tudo bem, então vamos testar esta autorização e então podemos terminar esta atividade de uma vez por todas. Então, vamos dizer autorizado sobre a lista get ou obter lista de tipos de folhas e ponto. E então vamos saltar para arrogância e login algum login como um do mar que os usuários têm o Tolkien. E então quando eu percorrer todo o caminho para baixo alguém para testar um que não está autorizado apenas acerta. Então vamos olhar para o get by IDs para que eu possa dividi-lo em id1 e executar. E você vê que estou recebendo minha resposta, não é necessária autenticação. Agora, se eu quisesse testar os tipos de folhas, posso clicar no cadeado. Então deixe-me começar de novo. Quando o cadeado me dará as instruções que dissemos. Assim diz, certifique-se de que você entrar portador, em seguida, espaço do que o seu Tolkien. Então isso é o que realmente parece passar por cima do fio, escrever a palavra espelho. E aquele Tolkien que acabei de copiar da resposta do login. E quando eu clicar em Autorizar, eu posso anotar as roupas. Então, no que diz respeito ao futebol, quaisquer solicitações que ele vai estar enviando, quando clicarmos em executar, ele vai incluir esse token portador no cabeçalho. Então, quando eu clicar em Executar neste ponto, então vemos nossa resposta. Então deixe-me tentar de novo com o barista. Se eu clicar em logout, ele limpa o cabeçalho do portador e eu clique em Executar. E eu estou recebendo isso por um, eu não estou autorizado, eu não estou autenticado. Certo? Então deixe-me tentar de novo. O valor do potluck é a palavra portador. Os Tolkien autorizam, fecham, executam, e lá vamos nós. Então, nós protegemos toda a nossa API, ou pelo menos estamos colocando a capacidade de ter o EPI protegido e avançando, é claro que agora podemos replicar esse tipo de política de segurança para nosso aplicativo cliente. 32. Adicionar autenticação ao projeto web: Muito bem, então estamos a começar a fazer alguma API de loja de modificações pesadas, a fim de facilitar a autenticação e autorização até certo ponto. Agora tudo o que precisamos para replicar esses esforços em nossa interface do usuário, onde precisamos ser capazes de permitir que o usuário faça login. E com base em seu papel, eles devem ser capazes de ver certas coisas não são. Então aqui eu estou fazendo login como o usuário administrador e você pode ver que eu fiz algumas modificações no menu onde eu posso ver certos itens que eu não poderia antes. Então vamos ver o que foi feito. Mais uma vez, eu não posso fazer o trabalho já e eu vou te guiar por isso porque eu não quero te aborrecer ao me ver digitar. Então, passo número um, vamos atualizar nosso código gerado swg final porque nós modificá-lo ou API. Como resultado, nossa documentação foi modificada. Então precisamos de um novo conjunto de código para representar o estado atual da API. Então, mais uma vez, vamos entrar em wag ou tempo de execução é feito às cinco. Colocamos nosso URL à frente e criamos uma cópia local. E praticamente replicamos todas as configurações no mesmo namespace. Nós nos certificamos de que todas as opções são marcadas, injetar, gerar a interface e garantir que você está acima dos detalhes e gerar os detalhes e os tipos de classe. E quando tudo isso for feito, certifique-se de que o caminho do arquivo está correto e, em seguida, regenera. Sabe, isso é algo que podemos fazer várias vezes em um provavelmente deveria ter mostrado isso antes, mas você pode realmente ir para o arquivo e apenas salvar este espaço de trabalho para que você não é difícil começar do zero cada vez. Tudo bem, então vou guardar isso. E quando voltarmos, podemos sempre reabri-la e salvá-la dentro do projeto. Você pode salvá-lo em qualquer lugar. Isso é bom. No entanto, vamos em frente e continuar com o nosso código recém-gerado, que deve saber ter as tarefas ou, ou os objetos de solicitação e resposta para nossas operações de login e registro. Tudo bem, agora que temos tudo isso, vamos configurar nossos serviços de autenticação local. Em nossos contratos, vamos ter uma nova interface, eu serviço de autenticação. E vamos ter três métodos. Um para autenticar, outro para registrar 12 logotipos. Isso poderia facilmente ter sido chamado de login, realmente não importa, mas isso é para login, isso é para distribuição, e isso seria forçado a sair. E, claro, para sempre contratos, há uma implementação. Então, nos serviços, eu tenho essa implementação na forma de serviço de autenticação, que vai herdar do serviço HTTP base, bem como do contrato. Agora há um pouco acontecendo neste método e eu vou orientá-lo passo a passo como de costume. Então, primeiro, eu preciso injetar meu acessador de contextos HTTP. E eu vou ter um campo privado para manipulador de token de segurança JWT conhecer algumas dessas classes e você carregar. Eu realmente vi esta classe de nem lidar com a API, você vai precisar de bibliotecas adicionais. Então, à medida que você for solicitado a instalar as bibliotecas, vá em frente e faça isso, bem como colocar as instruções de uso. Então, em nosso construtor, como vimos antes, estou injetando os ícones, armazenamento local, e eu contextos HTTP acessor, que está sendo inicializado aqui. Também estamos passando isso para o BCE ou o cliente e o armazenamento para o VCE. Estamos inicializando manuais, para que esses manipuladores de token não sejam injetados, mas estamos inicializando-o para ser uma nova instância do manipulador de token de segurança JWT. Saber para as implementações porque, claro, após essa herança, realmente precisaria da implementação. Então você pode ir em frente e gerar esses stubs métodos e deixar-nos saber, olhar através juntos o que precisa ir em cada um. Então, para a autenticação, tomando senha de e-mail e eu tenho tudo embrulhado em uma captura tentativa. O que estamos tentando fazer é gerar uma solicitação de autenticação. Então vamos obter o e-mail e o analisador a partir dos parâmetros. E eu não sei se eu já mostrei isso antes, mas nesta carreira, nesta última versão de C sharp, você pode realmente inicializar um novo objeto apenas vendo o nome do objeto do tipo de dados é igual a novo, e então você apenas tem os seus valores, certo? Então é só isso que estou fazendo lá. Em seguida, estou vendo resposta de autenticação var é igual a aguardar a chamada de clientes para login assíncrono passando nessa solicitação de autenticação. Agora, se o ponto de solicitação Tolkien não é igual a string dot servidor vazio sem o objeto de solicitação compreende algumas coisas. Ele tem o ID do usuário, o, eu acho que o endereço de e-mail em outras coisas, algumas coisas vieram sobre o que a única coisa que realmente estamos interessados em manter é um token porque isso é tudo que o aplicativo terá que usar para ver este é quem o usuário é. Então, se o token não está vazio, então o que queremos fazer é obter o conteúdo de Tolkien. Estou vendo var Tolkien conteúdo é igual ao manipulador de token que foi inicializado aqui. Leia JWT, token. E então estamos passando a corda. Então este é realmente um tipo forte chamado token de segurança JWT. Certo, então queremos as reivindicações do Tolkien. Lembre-se das informações, o e-mail, o ID, tudo o que foi enviado, Bucky, e o token que nos diz quem é esse usuário, precisamos de tudo isso. Então eu vou apenas analisar as reivindicações do token. Agora este é um método que eu tenho Putin e é aqui em baixo onde ele apenas retorna a lista de reivindicações. Então lembre-se quando estamos configurando a ferramenta pode lembrar que compilamos a lista de membros e compostamos e colocamos, codificamos e colocamos em Tolkien em nenhum lugar descodificando para que saibamos a lista de reivindicações. Então, neste método, estamos basicamente dizendo var reivindicações é igual a token conteúdo dot reivindicações ponto duas listas. Então, todo esse objeto de conteúdo token nos permite apenas obter as reivindicações de volta como uma lista de string ou lista de reivindicações em vez disso. E então vamos adicionar explícito. O nome dos tipos de reivindicação é assunto de ponto Tolkien. Então talvez houvesse algum, talvez não houvesse. Estou fazendo isso explicitamente. Só estou te mostrando porque talvez você não saiba o que você está recebendo de volta para Tolkien às vezes. Então você, se você quiser ser explícito, você sempre pode adicionar seu próprio limpo com seu próprio nome, como vimos antes. E você coloca em qualquer valor que deveria ter. Depois de fazer tudo isso, devolvemos a lista de reivindicações. Tudo bem, agora temos as limpas. Preciso criar um usuário para o meu up atual. Então eu estou vendo usuários var igual ao princípio reivindicações e princípios sonhos terá uma nova entidade reivindicações Ed com as reivindicações que foram apenas tomadas a partir do Tolkien. E estamos usando a autenticação de cookies. Então, uma vez que essa pessoa é criada, estamos armazenando esse registro de usuário ou a sessão do usuário, a fonte que não há um usuário atualmente no sistema como um cookie. Então vamos ver como isso é configurado mais tarde na inicialização. Mas é isso que estamos fazendo. E então vamos fazer um login vendo HDTP contextos acessadores. Então esta é a nossa biblioteca muito legal no caso de você não estar muito familiarizado com ela, que permite que você realmente acesse o contexto das solicitações HTTP. Então tudo está acontecendo quando um usuário está solicitando dados ou enviando dados, o que quer que seja que eles estão fazendo, tudo está acontecendo dentro do contexto de uma solicitação HTTP. Então, esta biblioteca realmente usa acesso direto a esse pipeline de solicitação atual e nos permite manipular contextos HTTP e é injetável para que não tenhamos que fazê-lo a partir dos controles, pode ser de qualquer outro lugar. Então eu posso dizer me dê o contexto HTTP em que estamos e vá em frente e assine este usuário usando o esquema de autenticação de cookie. E vamos guardar o Tolkien no depósito local para segurança. Então lembre-se que temos o armazenamento de baixo custo sendo chamado pelo nosso método token portador sempre que vamos fazer uma chamada. Então é por isso que temos que armazená-lo assim que você obtê-lo, e então nós vamos apenas voltar verdadeiro. Então, se a pessoa é autenticada, nós fazemos tudo isso. Eu retornarei verdadeiro. Se retornarmos falso , podemos fazer outra coisa. E você verá isso em alguns minutos. Então é isso que autenticar está fazendo. E se houve um erro neste try-catch, então ele apenas retorna false. Houve um erro, certo? Então isso é autenticar. E vamos olhar para o registro, o que é muito mais simples na verdade. Vamos apenas formular essas solicitações de registro com base em todos os parâmetros que teriam sido passados. E isso poderia facilmente ter sido um objeto, mas tudo bem. Você pode se referir a isso mais tarde quando criarmos a solicitação de registro em conformidade. E, em seguida, passamos sobre esse registro chamada HTTP assíncrono com essa solicitação. E, em seguida, se obtivermos ID de usuário MCI ou emitir sucesso superficial, caso contrário, não foi. Saiba em nosso logotipo, estamos fazendo duas coisas realmente estavam apenas limpando o armazenamento de quaisquer valores Tolkien que estavam lá. E também estamos assinando e destruindo implicitamente qualquer usuário. B são cookies que foram criados durante a assinatura CE. Isso é praticamente tudo o que o cinto de troncos está fazendo. Tudo bem, então é isso para o nosso serviço de autenticação. Não é muito complicado, certo? Em seguida, precisamos da interface de usuário ou interfaces que vamos chamar essa alma. Eu criei para um controlador chamado users Controller. E aqui nós injetamos serviço de autenticação I e temos duas opções, uma para login e 14 login com a nossa arte post. Então, faça login, ele só vai retornar uma vista e podemos gerar uma visão com bastante facilidade com isso. Então, bem, deixe-me voltar atrás. Na verdade, estou usando o site da VM de login, criei uma VM de login. Lá vamos nós, o que obriga algumas validações são mais, mas eu vou dizer, você sabe, nós sempre podemos impor a validação de um cliente disse que eu não tenho necessariamente que confiar na API. Então, algo como fazer login. Você não deve ser capaz de tentar fazer login sem o e-mail que estou analisando sendo preenchido. Eu também tenho um campo chamado URL de retorno. Tudo bem, então sempre que você tentar entrar, nós vamos exigir que você tenha senha de e-mail e onde também validar os tipos de dados com eles? E, em seguida, na opção, vamos gerar uma visão. E eu só disse para aumentar o seu login. Eu uso os modelos de criação porque nós vamos ser, precisamos de uma fazenda. E então estamos usando a VM de login para essa geração ou assim depois de fazer tudo isso, clicamos em adicioná-los, obtemos nossa visão simplesmente não que estamos acostumados a ver em nossa pasta de usuários. E é só o formulário de login, certo? Eu coloquei o URL de retorno como um oculto. E nós temos uma caixa de texto para nossa senha de e-mail 14, que eu especifiquei que o tipo é senha, então são os laços de caracteres, é claro. E, em seguida, o botão diz login, saber quando esse formulário é enviado, estamos pegando a VM de login e URL de retorno. Portanto, o URL de retorno está indo para o conteúdo de saúde ou raiz de conteúdo de URL padrão. E nós vamos ter um sinalizador que diz que está logado, que vai ser definido após a nossa ponderação de uma chamada para o ponto de serviço de autenticação autenticar onde política no e-mail de ponto de login e senha de login. E se obtivermos um booleano, então podemos retornar um redirecionamento para o URL de retorno. Tudo bem? Caso contrário, vamos adicionar um erro de estado modelo para dizer tentativa de login falhou estes dragão e nós apenas retornar a vista com o login. Então lembre-se que uma vez que causou isso e isso pode bloquear que volta como verdade. Isso significa que você já teria criado um cookie, já criado esse registro de usuário ou essa sessão de usuário. E então, quando estamos redirecionando, o usuário já estaria logado. Agora vamos pular para o nosso layout e ver algumas das mudanças que fizemos. Então, em nosso layout, tínhamos nossos tipos de folha, link ou URL aqui nesta seção de menu. Então eu removi isso e substituí por este bom, é um bloco de código. E eu também coloquei nesta parcial chamada login parcial. Mas vamos ver um pouco de código que eu coloquei. Então, nesta lista UL ou não ordenada onde temos todos os nossos itens de navegação colocaram em uma declaração if que diz se usuário, então usuário com um U maiúsculo usa para olhar para os princípios reivindicações, lembre-se que é o que acabamos de criar em que serviço de autenticação, certo? Então, se este usuário ponto adicionar entidade é autenticado, então queremos fazer isso. Alguns frangos user.name está se cadastrando. Lembre-se que mandamos a regra limpa, certo? Assim, podemos ver user.email mineral, procurar o administrador de função. E se o usuário estiver nessa regra, então exibimos esses muitos itens. Então eu só tenho outro item de navegação com uma classe chamada drop-down e uma tag âncora que diz Gerenciar. E eu não vou passar por cada personagem. Eu só vou rolar lentamente o suficiente para que você possa ver tudo o que vai para a etiqueta âncora. Tudo bem. E, em seguida, abaixo disso, temos uma div que tem os itens de menu drop-down. Então você pode apenas pressionar Pausar e replicar isso, se necessário. Certo, então foi assim que conseguimos o item da lista suspensa no menu. Pelo menos se você estiver usando o Bootstrap 4, que vem por padrão quando você scuffled ou.net predicação do arquivo.net sabe no login parcial, tudo o que eles fizeram foi criar uma nova visão navalha, não usou nenhum modular e dedos e vazios de você deu algum nome sublinhar baixa parcial onde geralmente indica que é uma parcial de qualquer maneira. E então temos esse pedaço de código onde eu tenho outro URL com barra de navegação classe. E dentro dessa declaração da avenida, o usuário é autenticado. Em seguida, queremos um item de lista que mostra o nome do ponto de identidade do usuário ponto. Então lembre-se que afirmação de nome que dissemos explicitamente. Era isso que era arte. Então isso é um bom, eu uso uma velocidade intermediária na barra de navegação. Então, naquela exibição bem ali, e então temos um botão de logotipo. Então, o botão Carregar é na verdade um formulário que vai chamar a ação Logos no controlador do usuário. E eu acabei de incluir aquele URL de retorno bem ali. E então aquele botão que diz logotipos. Então, se o usuário é autenticado, ele mostra que mais. Queremos mostrar link para uma irmã e um link para um login. Machucou o suficiente. Então, se eles não estiverem conectados, queremos que eles sejam capazes de fazer login ou se registrar, caso contrário, mostrar-lhes seu nome. Então você pode ir em frente e replicar essas linhas. Embora a grande modificação que precisava ser feita fosse para a nossa inicialização. Então você pode ver aqui que algumas coisas aconteceram. A última vez que estivemos aqui. Creio que teríamos chegado a este ponto. Agora temos todo esse processo. É certo. Então, em primeiro lugar, temos que deixá-lo saber que queremos adicionar o acessor de contextos HTTP, significa que queremos permitir que ele seja injetável em qualquer outra classe, então nós usá-lo no serviço de autenticação ocular. Permite-nos ir àquela instalação. Tudo bem, então eu quero definir as opções da política de cookies, certo? Assim, os serviços são configurados opções de política de cookies não estão em nenhum lugar no lado mínimo responsável. Desculpe, a visão mínima parece definida. Parece que mais de um. Tudo bem. Então, mais uma vez, este é um aplicativo muito simples. Eu não estou disposto a todos com a segurança, você pode ter diferentes necessidades de segurança, nosso próprio seus cookies e suas políticas. Mas em um nível básico, é nisso que estamos sentados. E então eu vou dizer serviços ponto adicionar autenticação. E estamos adicionando o esquema de autenticação padrão de autenticação de cookies. E nós só adicionamos biscoito. Então eu estou adicionando transiente ou adicionando um transiente ou distribuição para o nosso serviço de autenticação com a sua implementação, tudo é, permanece praticamente o mesmo em que serviços configurar o método de serviços. Mas, em nosso Configure, também queremos ter certeza de que adicionamos autenticação e que temos ADD ou usar autorização lá também. Então você vai querer ter certeza de que essas duas linhas são prisões. E antes de eu seguir em frente, também queremos ter certeza de que as políticas de cookies lá. Então, as três coisas na verdade, política de cookies, usar autenticação e usar autorização. Agora, outra coisa que você deseja fazer é modificar seus serviços. Portanto, saiba que sabemos que temos que ter o token do portador anexado a determinadas chamadas de serviço. Agora podemos ir a uma missa. Então você tem o serviço de tipo folha já instalado e funcionando. E então podemos chamar o método de token add bearer dentro de cada um desses métodos. Então, logo antes de realmente atender a chamada de cliente, queremos adicionar token portador. E assim como uma atualização no token portador basicamente diz, se o token existe, então vá em frente e adicione-o à autorização. Tudo bem, obtê-lo como uma cerveja. Então lembre-se, quando estamos testando, ele iria se gabar. Quando tivemos que testar o endpoint seguro onde ir e ver o espaço do portador, o token Isso é tudo o que isso está fazendo é apenas ver os valores de cabeçalho de autenticação cerveja. E nós estamos adicionando esse token. E a autorização é o cabeçalho padrão, certo? Então esse é o cabeçalho e ele está adicionando portador. Isso é errado. Colocar uma barreira acelera Tolkien para nós. Quando fazemos isso, vamos adicioná-lo a esse cliente. Então, no momento em que o cliente faz a chamada, o token do portador está presente, e então tudo o resto pode fluir. Então você pode simplesmente ir em frente e adicionar esse token de portador porque nós não sabemos quando algo será seguro não é ela. Não sabemos qual endpoint será protegido na API. Bem, isso realmente não importa. O fato é que sabemos que precisamos de segurança espelhada. E mais do que provável, você teria sua API ou uma API seria bloqueios não completamente para qualquer pessoa que não está fazendo login está tentando se registrar. Uma vez que você está logado, você deve ter seu Tolkien para dizer, aqui estou eu estes para a informação. Agora, como um teste, o que vamos fazer é saltar de volta para o nosso controlador de tipos de folha na API e colocar e autorizar sobre todo o controlador, que significa que você não deve ser capaz de chegar a qualquer um desses endpoints com todo o seu token de portador, você deve obter um 40 1, o que significa em autorizado ou não autorizado, em autenticado. Em vez disso, se você tentar ir para qualquer um desses endpoints a partir da API. Tudo bem? Portanto, lembre-se de testar, você quer se certificar de que você tem em vários projetos, vários projetos de inicialização, vá para as propriedades da solução e deixe a API começar. Estou começando com o depuração, digamos que vem mais rápido e MVC, você também pode começar sem depuração se você não precisa ir linha por linha. Então vamos em frente e testar isso. Então temos o nosso aplicativo MVC, vamos tentar fazer login. Então deixe-me colocar, mas tentativas. Eu sei que o usuário não acha que este login e dar-lhe alguns, e, em seguida, ele está saltando acima vendo tentativa de login falhou. Por favor, tente novamente. Tudo bem. Devidamente anotado. Vamos tentar um que conhecemos e depois experimentá-lo novamente. E, em seguida, desta vez estamos agora registrados sido tão redirecionados para a nossa página inicial e nenhum ISI que Gerenciar item de menu, que nos dá essas opções porque estamos em como o administrador. E se eu for deixar tipos, tudo carrega. Por quê? Porque o meu símbolo está presente. Ele sabe que tenho acesso a informações que estão sendo solicitadas. Oh, se eu amo muito. E deixe-me tentar fazer login novamente como o usuário regular, em seguida, login vai ficar bem, mas não há gerenciamento agora. E se esse usuário estivesse de pé sobre o ombro do administrador e visse que, a fim de chegar aos tipos de folhas e criar meu próprio tipo de folha, eu posso fazer isso. Vou tentar chegar lá. Vai para lá, certo? Então altere isso. Temos alguns pontos de ataque e, mais uma vez, somos opções. Implemente o que é melhor para a sua situação. Mas a partir do aplicativo do lado do cliente, devemos saber que certas coisas são reservadas para administradores, coisas incertas são reservadas para usuários ou talvez não livros reservados. Os usuários não devem conseguir acessar certas coisas que os administradores podem. Então, em nosso controlador de tipos de folha, provavelmente não é suficiente apenas dizer autorizar porque isso significa que você tem que estar logado. Também pude ver autorizar com o administrador de funções. Então isso significa que apenas os administradores devem ser capazes entrar nesta parte real do aplicativo. Tudo bem, então isso realmente me economizaria muito tempo do lado do cliente tentando descobrir, ok, qual é a vocação? Guerra eles o que quer, porque este Autorize realmente vai cuidar de toda a situação para mim. Tudo bem. Então, agora que eu autorizei apenas os administradores para ser capaz de acessar o controlador de tipos de folha. Se eu estiver conectado como um usuário e eu tentar ir para deixar tipos manualmente. Então, mais uma vez, não basta esconder o link porque se eu memorizá-lo, eu posso triangular. Bem, você está vendo que ele está vendo acesso negado e está apontando para um endereço que não existe. Bem, isso é bom. O que está nos dizendo acesso negado , ou, você sabe, está relatando que não podemos chegar lá. No entanto, se eu estava logado como administrador, eu poderia facilmente navegar lá porque eu atender aos requisitos. Então essa é uma boa maneira de proteger seu aplicativo do cliente. Disse agora que sendo dito, você também pode protegê-lo a partir da API disse porque da mesma forma que você pode definir que autorizar inundação sobre o controlador tipos de folha no cliente para cima ou qualquer tipo de aplicativo que você está usando, se é um blazer MVC ou angular, onde quer que você se sente, a autenticação naqueles que você poderia nossa autorização em vez, você também pode definir essa autorização na API. Então, o desenvolvedor da API também pode ter estipulações rigorosas sobre quem deve ser capaz de acessar meu controlador porque se ele não for aplicado do lado de cima, e então nós ainda poderíamos passar para a API. Então, como desenvolvedor de API, você também pode ser muito rigoroso e ver que apenas os administradores estão autorizados a aquecer todo esse endpoint, todo esse comportamento, certo? Ou um conjunto de comportamentos. Então, como eu disse, há poucas opções e você sempre pode atacá-lo de diferentes ângulos. Certo, então vamos encerrar toda essa atividade com mais algumas modificações e então estaremos livres pelo menos por enquanto. Tudo bem, então em nosso controlador de usuários, em nosso aplicativo, eu quero fazer uma modificação aqui onde eu verificar se o modelo Steve é válido. Então, se você é usado MVC e todos esses, você não pode prosseguir enquanto eles são erros de validação e não em Logan VM, nós temos algumas validações. Queremos ter certeza de que eles estão em cheque e não agradaram, isso é tudo que nós impomos essa validação antes mesmo de tentar essa chamada de API. Tudo bem, caso contrário, ele só irá adicionar esse novo, aquele erro estático e retornar a exibição com os dados e os erros. Sem problema, não para registro. Vamos em frente e brigar com este. Então vamos para View, New View, Navalha View. Queremos registrar-se com o nosso modelo de criação e nossa classe seria registrar v0 m. Tudo bem, então eu não tenho certeza se eu mostrei a você o registro, registrar VM, mas ele praticamente se parece exatamente com o pedido de registro. Registro, solicitações, FirstName, Sobrenome, e-mail, nome de usuário e senha. Certo, e se quiser colocar Putin confirme a senha, mas por agora é tudo o que temos. E nós também temos esses atributos para garantir que eles são necessários. Então você vai usar isso para gerar a exibição. E então, no, no post, o que vamos ter é aceitar esse registro ou há VM? Saiba, eu fiz uma modificação para o método de registro e isso tem alguns passos através dele. Um no perfil de mapeamento de perfil adicionado para o raio da VM e solicitações de registro para lembrar ou distribuição a pedido é um desses modelos gerados cortesia de n swag, certo? Então eu estou limpando isso porque eu escrevi, mas eu realmente não gostei. Então, mais uma vez, quando você está desenvolvendo, às vezes você faz algo de uma maneira e depois faz enfermagem. Eu poderia ter sido o centro da parte melhor e isso vai ter problemas com a refatoração, certo? Então, no método register, eu estou tomando nota do nosso parâmetro de registro VM e eu também atualizei ou eu serviço de autenticação para refletir isso. Tudo bem, então nulo, ele pega todo o objeto em vez de seis parâmetros. Então isso é outra coisa com princípios sólidos. Você não quer passar para muitos parâmetros em um método. Então, quando você perceber que você provavelmente excede três ou quatro, crie um objeto. Então, neste caso, só tínhamos dois. Não queria que refatorizasse aquele, mas este tinha cerca de cinco ou seis. Então eu refatorei para passar o objeto de registro. E então nossa solicitação de registro é não, apenas um mapeamento entre a solicitação de registro e nossa VM de registro ou registro. Certo. Então, é claro que eu tive que injetar outono em cima disso para colocar isso em funcionamento. E então tudo o resto permanece o mesmo praticamente. Então, de volta ao controle. Eu sei POS nessa chamada de registro, eu verifico se ele foi criado? E então, se for criado, então redirecionamos. Então aqui eu estou apenas sentado o URL para ser o seu conteúdo. Eu não estou sentado é especificamente e nós redirecionamos. Caso contrário, temos uma mensagem e retornar a vista com os dados. E mostraria todos os erros de validação em conformidade. Então, vamos também modificar nosso serviço de Auth no nível da API porque queremos os funcionários se registrem, então precisamos saber que seus funcionários, então nesse ponto eles estão se registrando com base em nossa cotação é configuração não, que seriam apenas usuários. Não haverá nenhuma atribuição de função. Portanto, precisamos garantir que quando eles se registram, conheçamos seus funcionários. Então, em nosso serviço de Auth, mais uma vez, em nosso projeto de identidade na infraestrutura, certo, serviço de OT, precisamos ver se o resultado foi bem sucedido para o usuário de criação. Então precisamos atribuí-los à regra. Então, vamos apenas adicionar esta linha depois que um ponto resultado foi bem sucedido. Nós apenas dizemos, Eu vou esperar para usar um gerente adicionar à regra usuário assíncrono, funcionário. Então vamos ficar com esse registro para dar uma volta. Então eu vou bater no registro e preencher isso. Agora uma coisa que eu queria apontar O, nós fazemos para o e-mail e o nome de usuário. Mais uma vez, contextos são diferentes em nosso contexto, estou usando o mesmo valor para e-mail e nome de usuário. E então seria dito que ele poderia ser dito de viável. Eles são convidados por ambos. Por que não pediu apenas um e atribuí-lo no bucket, que é argumentos verificáveis, certo? Então, em sua situação, você pode precisar deles separados, e eles podem precisar ser duas coisas diferentes. Assim, nenhum problema apenas dando-lhe o quadro. Então, antes mesmo de eu fazer uma distribuição adequada e você pode ver que a validação está realmente funcionando ativamente. Não posso avançar para tudo o que está no lugar, certo? Então deixe-me colocar os valores e, em seguida, ir em frente e bater registre. E eu fui redirecionado para cá. Então você tem outro, você sabe, eu estou sempre falando sobre as opções porque neste momento eu estou registrado, mas eu não sei. Não há indicação de que tenha sido bem sucedido. Acabei de voltar para a página inicial. Claro, se eu tentar fazer login, posso fazer login, mas o usuário não sabe. Então, de modo geral, ou às vezes o que você veria é que eles realmente se conectariam depois de uma distribuição bem-sucedida ou. Então podemos fazer uma simples modificação para que isso aconteça. Isso é simples modificação é chamar ou autenticar arte. Então nós passamos por sua distribuição, nós obtivemos uma resposta se ele não está vazio e nós retornaríamos verdadeiro. Antes de retornarmos verdadeiro, só queremos chamar autenticar, que sabemos o que ele faz. Ele realmente aciona todo o procedimento de login, e então nós retornamos true. Então, em nosso controlador, poderíamos facilmente ter algum redirecionamento para ver, em vez de voltar para a página inicial, poderíamos ler nossos dois endereços IP. Você terá sucesso amor banner, alguma mensagem amigável para o usuário para que eles saibam exatamente o que aconteceu. Tudo bem, então é realmente isso para nulo, pelo menos mais tarde nós temos a embelezamento terá algumas modificações porque mesmo acima do nulo, nós não estamos focando ou compensando certas setas que estar voltando da API. Assim por diante. Nós dissemos que lidar com erros globais para cuidar, mas mais tarde vamos lidar com isso, certo? Não, estamos apenas nos concentrando na implementação desses recursos e fazendo com que tudo funcione bem juntos. 33. Gestão de Leave: Certo pessoal, então agora que temos ou configuração de autenticação, temos nossos usuários, ou pelo menos nossos usuários têm a capacidade de se registrar e ser configurados como funcionários. E tudo o que precisamos para colocar no recurso que permite que os administradores alocem os Ds para sentar funcionários. Então isso começa com aqueles que modificam nossos objetos de domínio para alocação de licenças onde vamos adicionar o ID de funcionário porque precisamos saber a quem o número de dias para esse tipo de folha para esse período foi atribuído. Então precisamos acrescentar isso. E depois disso, fazemos uma migração. Lembrando que precisamos definir nosso projeto de inicialização para a API e o projeto padrão para o projeto de persistência. E ou adicionar declaração de migração traço ficará assim. Nomeei meu ID de funcionário adicionado para deixar a alocação e os contextos seriam contexto de banco de dados de gerenciamento de licença. E depois disso, executamos essa atualização para o mesmo contexto. Então este é o nosso arquivo de migração. Basta fazer o banco de dados de atualização e um solo que ele tenha completado e podemos seguir em frente. A próxima coisa que queremos fazer é criar um arquivo de contrato ou uma interface em nossa camada de aplicativo sob a pasta de identidade, eu estou chamando, eu uso um serviço. Então nós vamos ter qualquer operação de usuário especializado neste, eu uso um serviço que pode ser usado por nossos manipuladores. Então eu vou ter este retornando uma lista do tipo empregado e é chamado de empregados get porque nós só queremos alocar. Estes são os funcionários sabem que o departamento de RH disse que tudo o que eles realmente precisam para este recurso é a capacidade de ir para a página e clicar alocar, e então nós obter todos os funcionários e alocar. O padrão é para o período, período sendo este ano. Claro, não queremos alocar nada para qualquer corpo que não esteja na função de funcionário. Então precisamos ter certeza de que estamos recebendo funcionários. Funcionário é um modelo que foi criado dentro da pasta de identidade. E tudo o que realmente tem é o ID, o e-mail, o FirstName, Sobrenome, e nada demais, não muito vindo do banco de dados apenas em uma floresta e todos os que esse funcionário pode ser. Obrigado, temos a nossa implementação que vive no projeto de identidade, e é apenas usa o serviço sob a pasta de serviços. E está herdando do contrato. E ele está injetando o gerenciador de usuários em relação ao usuário do aplicativo. E então nosso método para obter a lista de funcionários estava apenas olhando no gerenciador de usuários, obter usuários inscritos assíncronos e passamos nessa função. Então isso está nos garantindo que estamos recebendo qualquer um no banco de dados foi um usuário que tem função de funcionário. E então estamos devolvendo a lista do tipo empregado. Então, onde é que esta é uma lista de usuários do aplicativo? Então, estamos dizendo selecionar a partir desta lista em novos objetos do tipo empregado. E eles estavam apenas reatribuindo os valores de acordo. E então terminamos com uma lista de afazeres tudo nesse retorno. Então, uma vez que este serviço é chamado, vamos estar usando esse método para obter todos os funcionários. Em seguida, em nosso método de registro de serviços de identidade, é claro que temos que adicioná-lo I User Service. Então vamos em frente e registrá-lo de acordo. Agora isso vai ser seguido por algumas mudanças no nosso repositório de alocação I leave. Então salte de volta para os contratos e encontre o nosso original. Vou deixar o repositório de alocação. Originalmente, teríamos escrito a implementação para os recursos atuais completos de alocação de licenças juntamente com esses dois métodos personalizados. Mas então HR, mais uma vez, tipo de mudança de regras tornou mais simples para nós, problema do sono, mas precisamos de alguns métodos mais personalizados, a fim de realizar o que HR tinha em mente. Então, certo, não, eu tenho uma tarefa, estamos devolvendo um booleano que verifica se a alocação existe. Então, obtemos o ID do usuário, ID do tipo de folha e o período. E então nós temos outra tarefa onde eu estou vendo em alocações. Então você vai ver por que eu tenho em alocações, mesmo que nós já temos o método de adição genérico, o estado sabe que este toma uma lista de alocação de licença como parâmetro, sabendo a implementação. Que você vai ver o que está acontecendo aqui. Então vamos começar com o aplicativo existe. Mais uma vez tarefa retornando um booleano, verificando se ele existe, obtemos esses três parâmetros, então estamos apenas retornando alocações de ponto de contexto do banco de dados que qualquer assíncrono onde verificamos se o ID do funcionário corresponde ao ID do usuário sendo magro. Se o ID do tipo de folha muito é um sendo passado dentro e o período tanto quanto o período. Então nós estamos apenas retornando, sim, essa alocação existe, são conhecidos por nossas alocações estavam fazendo algo um pouco diferente aqui então com o anúncio regular. Porque o que acontece é que se estamos permitindo que ela vá e clique em Adicionar alocações e há 100 pessoas lá. O que não queremos fazer é chamar a função add 100 vezes. Então EF Core realmente nos deu um método de intervalo de anúncios que nos permite apenas colocar em uma lista completa de registros a serem adicionados. E ele irá empacotá-lo na instrução SQL mais eficiente possível para salvar as alterações. Certo, então é por isso que escrevi esse método personalizado aqui. Então, estamos adicionando intervalo em vez de adicionar. Muito bem, agora que temos o nosso repositório pronto, vamos saltar para o nosso manipulador e ver que mudanças são necessárias lá. Tudo bem, então em nosso manipulador tinha comentado essas linhas são apenas descomentar eles sabem que estamos aqui. Então, estamos injetando nosso serviço de usuário em nosso comando ou criando a alocação. Saiba que algumas outras mudanças serão necessárias porque nosso detalhe de criação está pedindo muita informação com base no que dissemos. A nova operação ou o novo objetivo é. Chegaremos a isso em poucos. Mas a retina quer se concentrar no que o manipulador faz depois que ele é, ele validou os dados que vieram, certo. Então, depois de validar o que está no DTO, prosseguimos para tentar compilar a lista de alocações a serem enviadas para o banco de dados. Então vamos ver o que acontece aqui. Em primeiro lugar, obtemos o tipo de folha que está sendo alocado, certo? Então nós fazíamos I GET pedidos debaixo daquele repositório que já foi injetado cortesia fora do Fatah. Precisávamos dele para o validador. Tudo bem, então deixe que o ponto do repositório GET solicitação ponto detalhe de alocação ingênua o ID do tipo elif. Recebemos todos os funcionários cortesia do nosso serviço de usuário. Também estabelecemos o período este ano. E então inicializamos uma lista de alocações de licenças. Então, para cada funcionário que está no sistema, verificamos se a alocação existe. Nós apenas continuamos. Caso contrário, queremos adicionar um novo registro de alocação onde o ID do funcionário é igual a EMP dot ID e deixar dy por dt é igual ao tipo de folha, mas ID e o número de dias. E o período é o período certo? Agora, eu não estou sendo rigoroso com as regras de negócios. Algumas regras de negócio dizem que, com base no ponto do ano, essa localização deve ser diferente, o que é perfeitamente plausível. O que quer que Masi queira fazer, você aplica essa matemática contra os dias padrão e você se inscreveu. Mas o ponto é que você está alocando os dias para o empregado neste momento. Claro, se você quisesse pegar o Grendel, então você iria querer fazê-lo em uma base um-para-um em vez uma operação em massa para todos por um período inteiro de um ano, certo? Então você pode brincar um pouco com ele. Mas agora estamos lidando com uma operação a granel. Então, depois de termos adicionado todos esses registros de alocação para esta lista, então nós apenas esperamos nossa chamada para as alocações em nosso repositório, que está enviando sobre a lista e EF Core, nós vamos fazer o resto. E então podemos ver que a resposta é verdadeira, sucesso é verdade, e a mensagem é criação ou alocações bem-sucedidas, qualquer que você preferir. Saiba para o nosso cria alocação DTO, estamos pedindo o número deles. E nós estávamos pedindo o período porque pelo menos no sistema antigo, que são capazes de clicar diretamente em um funcionário e colocar no número de folhas que estamos alocando dinheiro descontroladamente. E o período para o qual estamos alocando, como o RH disse, eles meio que não precisam ou não querem isso, certo? Não, então tudo bem. Podemos sempre modificar nossa DTL, redimensioná-la um pouco. E, claro, isso teria alguns efeitos de ondulação com toda a herança dos detalhes de alocação. Então isso significa que temos que modificar mais do que apenas os campos, certo? Então eu teria que remover essa herança e a nota off para modificar também o validador para não incluir todas as regras relativas à interface são OF para remover todo esse incluir Andon depois de reescrever a regra apenas para o Cria. Então eu apenas reescrevi essa regra onde nós validamos o ID do tipo de folha que está sendo aplicado para são alocados para, nós certificamos que é maior que 0 e nós verificamos se ele existe também. Agora vamos saltar para a nossa API e deixá-lo saber que ele também deve estar retornando a resposta do comando base. Se você ainda não fez isso. Certifique-se de fazer isso para que o documento Swagger com o atualizado e, em seguida, duas alterações precisem ser contabilizado pelo nosso novo cliente de serviço no aplicativo. Porque primeiro, nós alteramos os parâmetros para o DTO. Não, você só precisa de um parâmetro. E também precisamos deixar o servidor saber que ele deve esperar a resposta do comando base. Então, agora que fizemos essas alterações, vamos usar em swag para regenerar esses códigos de cliente de serviço. Basta lembrar sempre que é melhor executar o projeto. E, em seguida, mesmo que você já tenha salvo, porque eu acabei de abrir minha versão salva deste modelo. Mesmo que você o tenha salvo, é melhor reabrir o projeto, recriar a cópia local e, em seguida, você pode gerar novamente seu código C-Sharp. Então agora vamos saltar para o nosso aplicativo cliente onde estaremos configurando o nosso contrato, É implementações e, claro, a interface do usuário. Então agora todos nós temos o nosso contrato. Vou deixar o serviço de alocação e ele nos diz que há retornos resposta com o tipo int. E vai ser chamado criativamente vocações, e é só pegar um ID tipo folha. Mais uma vez, o RH simplificou para nós. Então, se você tivesse criado todas as VMs e assim por diante, isso é que eu tenho que teria sido um exagero com base nos novos requisitos, mas tudo bem. Então, tudo o que realmente precisamos é criar uma alocação intravenosa. E então na implementação que colocamos na pasta de serviços, é claro, sabemos que herdamos do serviço HTTP base e o ID do serviço de alocação, muito parecido com o que fizemos, os tipos de folha, também injetamos ou de baixo custo armazenamento e cliente AAE neste serviço. E então em nosso método, essa é a alocação de licenças de creatinina, tudo o que temos nosso tipo de resposta, que é a resposta relativa ao tipo int. Criamos nossos detalhes, que nesta situação é realmente apenas o detalhe a ver. O tipo de folha tem esse valor. Tudo bem, então sabemos que o detalhe Criar, deixar, criar licença alocação agora é atualizado para querer apenas esse valor desde que atualizamos nossa documentação e o código resultante através e slug, adicionamos ao nosso token portador e somos trigo Ligue. Tudo bem, então eu nem sou a verdadeira lata, nós sempre podemos voltar e garantir que o endpoint da API esteja protegido apenas para administradores. E também podemos fazer essa previsão do nosso lado da aplicação, certo? Então, o token do portador é definitivamente importante para lembrar. Sempre será importante para as comunicações APEC. Então, depois de fazermos isso, verificamos se o seu sucesso, em seguida, definimos como verdadeiro, já que não há dados reais voltando, porque havia apenas retornando a resposta do B. Não vamos devolver uma identificação ou algo assim. Então eu não preciso definir os dados de resposta para ter qualquer valor realmente. E então nós compilador erros retornou resposta. Tocar em qualquer erro. Como eu disse antes, certifique-se de tê-lo registrado no CSS de ponto de inicialização. Então você simplesmente não usa balas ou o startup.js. E se ele tivesse escrito as linhas, sem comentá-las, então descomente, se não, então sinta-se livre para saber, coloque essa linha. Agora vamos fazer alterações ou interface de usuário. Então, o melhor lugar que eu tenho suposto para colocar esse recurso para uma alocação em massa de tipos de folhas é no tipo de folha LR. Então, nessa página eu acabei de adicionar um novo formulário onde teremos advogado com o mesmo tipo de identificação de rota caras para vê-lo procurando fórmula para excluir. Então aqui estamos repetindo o formulário. Então, como eu mencionei, às vezes bip, em vez de ter vários formulários, teria um e, em seguida, usar JavaScript para acionar o único formulário. Mas tudo bem nesta situação, tudo o que quero saber é que funciona, certo? Então temos o ASB real e alocar. É preciso o mesmo ID de rota e temos um botão que diz alocar. E este só está dizendo, tem certeza que quer alocar para todos os funcionários? Esse é o aviso que você obteria. Agora temos um método post em nosso controlador de tipos de folha chamado Olá Kate. Então eu só coloquei isso bem embaixo do deletar, certo? Então, no nosso caso, estamos tentando obter a resposta do serviço de alocação de licenças. Então subponto disse que temos que injetar isso em nosso controlador. Certo, tentamos obter a resposta. Eu só uso o Controle M e O, apenas anote para tipo de recolher todo o código para que você possa usar isso para arquivos de código B. Então, nosso método de alocação vai chamar serviço de alocação criar altercações, passando esse ID. E, em seguida, se ele irá redirecionar com sucesso para a ação para o índice. E bem, eu só vou devolver um pedido ruim aqui, caso não tenha sido bem sucedido. Então sabemos que não foi ela. Mais tarde você pode adicionar algum jQuery ou algo para lidar com o tipo de retorno de uma maneira melhor, mas certo, não, nós não estamos priorizando isso. Só queremos ter certeza de que estamos colocando todas as coisas e a fundação no lugar, certo? Então vamos realmente dar uma volta. Vamos tentar alocar. Lembre-se de colocar em vários projetos start-up. E tendo feito login como o usuário administrador, navegamos para nossos tipos de folha e, em seguida, tentamos alocar. Então, ainda assim, nosso prompt Tem certeza de que clicamos em OK e estamos recebendo um erro. Estamos recebendo um erro, Erro HTTP 400. Então isso indica que um pedido ruim. Tudo bem, então algo definitivamente deu errado. Então, depois de rastrear e rastrear esse erro, ele caiu bem aqui no validador. Então, o que acontece é que quando estamos criando, não está se deparando como válido que criar alocação de licença V2 não está sendo válido. Isso é porque ele está vendo que um tipo de folha não existe. Agora sabemos que isso é impossível porque nós apenas clicamos no tipo de folha. Está na mesma linha. Sabemos que existe e a flecha está bem aqui. Então esse é o meu, uh, mas então eu testes de unidade provavelmente teria pego que nós já escrevemos em unittest. Então temos que passar tempo rastreando essas coisas, não. Mas a questão é que devemos voltar se ela existir, porque estamos vendo se ela existe ou é verdadeira. Então deve existir. Então isso deve ser verdade. Então eu não deveria estar voltando, voltando não é verdade ou não aerado. Então isso é um erro da minha parte. Então, por causa desse erro, na verdade, terá que ir a todos os validadores apenas para ser saudável. Então certifique-se de que nenhum desses validadores está cometendo o mesmo erro. Agora a coisa boa é que nós meio que criamos os centrais. Então não temos muitas, muitas mudanças em mim. Então aqueles decolar que não assinar fora o tipo de folha existe, verificar e nós deve ser bom para ir. Certo, então vamos tentar outra vez. Vamos tentar fazer as alocações. Tudo bem, então estamos de volta e então vamos tentar alocar novamente. Chegamos ao nosso prompt, ele faz a sua coisa, e a página é atualizada para que não haja indicadores, certo? Poderíamos, claro, citando algumas mensagens para dizer, você sabe, esta ação chamará aqueles concluídos com sucesso. Mas o fato de que ele realmente atualizou a página de acordo com o nosso código. Se for bem sucedido, redirecione para o índice da praia atual, o que é bom. Foi mal sucedido assim em pedido de manteiga. Pelo menos sabemos que a nossa alocação está a funcionar. Vamos verificar no banco de dados para ver o que nossos locais foram criados. E vemos aqui que temos alocações para o tipo de folha um para o período de 2021 e o empregado a quem é atribuído. Então temos três funcionários no sistema ou IL-3 no meu sistema, provavelmente estamos vendo um ou dois se você tem o usuário pré-implantado e ele criou um usuário desde então. Mas a questão é que temos tantos funcionários no sistema, você teria essas alocações. Então, se eu fizer isso novamente com segurança, que é id2, clique, eu localizo, clique em Ok, e faz sua coisa. Se eu atualizar esses dados, agora vamos ver alocações para licença médica para todos os funcionários. Então a alocação div não está funcionando. Isso é o que a arte do RH, isso é o que eles recebem. Então, mais tarde você vê o da base para estender isso, se você quisesse dar uma tela dedicada, você teria que ir pescar o empregado, permitir-lhes editar a alocação do vale do dinheiro. E então, você sabe, configurar seu manipulador e seu endpoint de API para ser específico para isso. Não vamos ficar tão detalhados agora. Só queremos fazer as funções básicas. E até agora terminamos com a alocação de licenças. 34. Gestão de pedidos de Leave - Parte 1 - Emprego, Emprego.: Certo pessoal, então estamos enrolando a Nestlé e vamos passar para o próximo módulo, que será o nosso módulo de pedidos de licença. Então nossa jornada aqui começa com uma modificação para um objeto de domínio de solicitação de licença onde estamos adicionando solicitando ID de funcionário, tudo bem, porque quem está logado é aquele que vai fazer a solicitação. Portanto, precisamos ser capazes de dizer que esta solicitação veio deste usuário. Como de costume, após uma modificação em nossos objetos de domínio, temos nosso comando de migração e, em seguida, temos nosso comando update database. Então você pode ir em frente e fazer aqueles dois. E uma vez que você tenha concluído isso com sucesso, podemos passar para a nossa próxima atividade. Vamos rever nossos detalhes Criar solicitações de licença. Então dissemos que o Quest D2 precisa ter as datas de início e término, o tipo de folha sendo aplicado, bem como solicita comentários. Observe que não há nada terrível o ID do usuário, certo? Então você provavelmente está se perguntando, ok, então como sabemos qual usuário está logado de cada vez? Então lembre-se que estamos usando a autenticação Tolkien, que significa que entre o MVC acima na API, podemos acessar diferentes bits de informação do Tolkien. Um pouco de informação no token seria o ID desse usuário. No entanto, eu não quero acessá-lo de nenhum desses lugares porque eu não preciso acessá-lo até que eu realmente estou criando solicitação de licença. E temos o manipulador aqui que é tomado, que pedidos de comando ou comandos objeto. E, em seguida, ele vai em frente e validá-lo e, em seguida, criar que a solicitação se ele é válido, e em seguida, passá-lo o banco de dados. Então, isso significa que entre essas duas etapas, precisamos ter certeza de que colocamos os novos dados de ID de funcionário. Então lembre-se que nós tínhamos usado o contexto acessor buck quando estávamos fazendo a autenticação no aplicativo MVC. A coisa legal sobre isso é que nós somos capazes de usar esse acessador de contexto todo o caminho aqui em nossa camada de aplicação, em nossos comandos. Então, vamos acessar o contexto HTTP da API de dentro do manipulador. Assim não teremos que acessá-lo até que seja absolutamente necessário. Então, no arquivo de inicialização da API, eu vou adicionar o acessor contextos HTTP services.js gravável, a chamada do método swat Swagger doc. Isso, em seguida, me permite injetar no comando meu HTTP contexts acessor. E eu posso ir em frente e inicializar o campo, mas eu preciso de uma biblioteca para isso, e que é a abstração do núcleo do Microsoft dot ASP NET. Então vá em frente e instale a versão mais recente. Estou usando NuGet, renomear nosso campo de acordo com nossa convenção de nomes. E, em seguida, dentro do manipulador, eu posso facilmente salvar var ID de usuário é igual ao meu contexto HTTP contextos de ponto HTTP, dot usuário dot reivindicações padrão de primeira ordem. Então, é uma boca cheia, mas vamos apenas avaliar o que está acontecendo aqui. Até este ponto, obtivemos o princípio das reivindicações. Isso afirma princípio é o mesmo princípio que somos capazes de construir no aplicativo inquilino em virtude do Tolkien, certo, então, porque o token está vindo do nosso cliente para a API, somos capazes de acessar as informações do token a partir do manipulador cortesia da API. E, em seguida, podemos acessar esse usuário, olhar dentro da lista de reivindicações e encontrar o padrão do primeiro andar que tem a mesma chave de tipo de nome. No entanto, você deseja avaliar se o que um tipo aqui corresponde ao nome reivindicado que teríamos dado para o ID do usuário. Então essa é outra razão pela qual eu sugiro não usar as cordas mágicas porque um erro de ortografia aqui poderia jogar fora a coisa toda. O que podemos fazer isso na atividade de limpeza mais tarde. Mas agora estamos recebendo a reivindicação UID, que nós sentamos manualmente. E então eu estou apenas usando o padrão ou quatro, se for pequeno, nós não obtemos outra exceção, mas eu realmente estou recebendo o valor. Tudo bem, então é assim que eu consigo o ID de usuário. Agora que eu tenho esse ID de usuário, mais tarde eu posso ver o ponto de solicitação de licença solicitando ID de funcionário é ID de usuário. Agora eu fiz isso todo o caminho até aqui porque eu posso querer usar este ID de usuário e outra operação mais tarde. Então eu só estou mantendo isso aqui. E outra coisa que podemos nos interessar é o endereço de e-mail. Por isso não estamos a receber o e-mail de uma forma ligeiramente diferente. Estamos vendo o endereço de e-mail é igual ao seu acessador de contextos GTP, todos os que user.name encontrar primeiro. E então estamos procurando a reivindicação exata de e-mail por seu tipo. Uma vez que faz uma técnica diferente do que fizemos aqui em cima. E estamos recebendo esse valor. Então você pode tomar várias abordagens para obter isso. Esses pedaços de informação porque ele poderia ter apenas obtido o princípio de reivindicações em uma varredura e, em seguida, usar a primeira lei encontrar, a primeira lei padrão depois para obter qualquer pedaço de informação que você quer. Não há problema, mas pelo menos você sabe ou sabe como obter o endereço de e-mail para que possamos saber dizer para esse endereço de e-mail e enviar nosso e-mail no momento apropriado. Agora, antes de passar a partir deste manipulador particular há outras operações de limpeza até que eu gostaria de realizar antes de permitir que um usuário para prosseguir com um pedido de licença. E então vamos pensar sobre o que exatamente precisa acontecer durante esse processo. Em um usuário precisa declarar que eles querem ter um determinado tipo de folha durante um determinado período. Eles podem adicionar comentários adicionais se quiserem. E então eles submetem isso. Eles só podem obter esse pedido se tiverem a alocação. Então isso significa que nem vamos colocá-lo no sistema. Se o que eles solicitaram exceder sua alocação atual. Se eles pedirem e sua alocação estiver presente, então tudo bem. Mais tarde, quando um administrador aprova isso, então vamos em frente e fazemos algumas deduções para ter certeza de que quando eles solicitaram cinco dias, então o 5D é menor em sua alocação. Então, essas são as coisas que queremos nos entusiasmar. Agora este é um, este é o mais complicado dos módulos. Então, há um pouco de trabalho a fazer aqui. Então vamos começar com a verificação da alocação, porque se eles não têm a alocação, então eles não podem ter uma operação válida daqui para frente, certo? Então vamos em frente e injetar ou eu deixo o repositório de alocação no sistema. E então o que queremos fazer é ser capaz de procurar a alocação para este empregado em particular, que é um método que não temos R. Então vamos saltar para essa história e implementar isso. Então, estamos criando uma tarefa que retorna alocação de licença, eu estou chamando getUser alocações e está tomando esse ID de usuário string, bem como deixar ID, direita, então vamos pular aqui e ir em frente e implementar o na classe repositório de implementação. E então o que vamos fazer aqui é fazer uma pesquisa e retornar nosso contexto de banco de dados procurando alocações de licença, encontrando o padrão de primeira ordem em que o ID do funcionário corresponde ao ID do usuário e o ID do tipo de folha corresponde à folha. Nada de contrariar o encarregado. Eu posso ir em frente e obter essa alocação chamando repositório de alocação de licença alocação de usuários Git alocações, passando o ID do usuário e que a solicitação ponto deixar, solicitação detalhe ponto folha ID tipo. Agora vou calcular o número de dias solicitados. Então eu estou fazendo um rápido caucasiano entre a data final e a data de início para obter o número total de dias. E eu estou me certificando de que eu obtê-lo, mas como um inteiro. E então eu vou dizer se o número de dias solicitados é maior que o número de dias em seu registro de alocação. Vou adicionar este erro de validação. Então esta corporação poderia ter acontecido aqui, exatamente como estamos vendo, eu estou fazendo isso manipulador e eu estou usando o resultado de validação fluente para apenas adicionar isso porque no caso de não ser válido, eu quero ter certeza de que esta validação também é presente. E assim, quando ele é retornado com os erros que também estará lá. Não, eu estou fazendo isso no manipulador, mas eu poderia facilmente ter feito isso no validador também. Mas então, é claro, eu teria que injetar tudo isso e criar uma validação personalizada no NDA para garantir que eu faça esse cálculo e tudo mais. Por isso, estou a dar-te as opções com base na tua situação. Você pode querer manter todas essas coisas dentro dos validadores. Você pode nem estar usando validador. Então você pode estar fazendo toda essa validação aqui. Depende de como você deseja colocar seu código de aplicativo para fora. Então agora podemos apenas ir em frente e limpar qualquer outra coisa neste manipulador, podemos ter que rever dados, mas pelo menos estamos olhando para como expandimos nosso manipulador e começar a colocar algumas outras coisas em sua vida HTTP, contexto, manipulá-lo, acesso ou outro, desculpe. Então, quando seguirmos em frente, você pode limpar quaisquer pequenas mensagens ao longo do caminho e certificar-se de que seu código pode compilar. Então, apenas uma construção rápida. Agora vamos avançar para o nosso aplicativo. Queremos obter o recurso em que um funcionário pode solicitar licença antes de colocar em quaisquer outros recursos administrativos e qualquer coisa, certo? Então quero que nos certifiquemos de que temos esse modelo de visão. Eu teria apresentado isso antes, mas deixar solicitações VM e carregar todos os modelos de visualização aqui. E esses modelos de visão estão realmente vindo do código existente em grande parte. Portanto, o Criar solicitações de licença, VM, e isso leva a data de início, a data de término, a hora, o ID da folha e alguma área para comentários. Não, eu pularia para o contrato para o serviço de pedidos I leave onde temos alguns métodos que não estamos implementando todos eles ainda, estamos lidando com um crédito para que você possa ir em frente e colocá-los todos dentro E crie a implementação de serviço correspondente e permita que ela implemente todos eles. Mas focando no método de criação, o que temos é um núcleo semelhante ao que fizemos com os tipos de folhas. No entanto, você notaria que eu tenho uma linha vermelha embaixo da parte onde eu estou pedindo uma resposta. Isso ocorre porque, no que diz respeito ao serviço de IA, cliente ou código de inserção, ainda estamos procurando apenas uma tarefa. Isso porque na API, eu preciso fazer duas coisas. Eu preciso deixar a documentação ou que no posto, deve levar a resposta do comando base. Lembre-se que nós tínhamos equipado todos os nossos manipuladores para devolver isso. E isso é essencial porque quando usamos n swag para regenerar ou codificar, que estou prestes a fazer, então ele saberá que deve esperar esse tipo de resposta. Mais uma vez, criar a cópia local mais recente, ir em frente e gerar e saber que isso é feito quando eu saltar de volta para o meu código, não há linhas vermelhas porque agora ele sabe que ele está retornando a resposta do comando base. Então está tudo bem. Tudo bem, então isso é basicamente o que estamos fazendo ao criar o pedido de folha. Então vamos agora nos concentrar na configuração do controlador eo código de suporte. Eu fui em frente e criei um controlador com operações de leitura-gravação, você sabe, para fazer isso, Não. E eu injetei o serviço do tipo folha e o serviço de pedidos de licença. Então você provavelmente está se perguntando, ok, por que eu preciso do tipo folha e deixar solicitações de serviço se eu estou apenas criando solicitações de licença, bem, a coisa é que a visão que eu já criei precisa ter um drop- para os tipos de folhas porque quando alguém vem pedir licença, é baseado no seu fluxo. Mas da maneira que estamos construindo, eles vêm para solicitar, deixar isso fora para selecionar em uma lista suspensa qual tipo de licença eles estão selecionando para, a data de início, a data de término. E, em seguida, eles são capazes de colocar em seus comentários antes de ir em frente e selecionar solicitação. Tudo bem, então isso é basicamente o que eu estou fazendo e esta é a visão vinda do sistema antigo. Então, literalmente, eu copiei e colei essa visão do sistema antigo. A única atualização foi que mudamos o modelo para ser o novo modelo em oposição a qualquer nova espécie lá. Mas só estou mostrando que é da mesma classe. Então você sempre pode ir e obter o arquivo de código e apenas copiar e colar. E você deve estar pronto para zero como quantidades de alfa. É por isso que isto está aqui. Eu não estou usando nenhum catador de encontro. Não estou complicando a interface ainda. Então eu estou removendo isso. Será que Becker amigos Nosso apenas usando contas tipo de entrada dependendo do seletor de data padrão dado a nós pelo navegador. Então Buck no controlador, precisamos preparar essa lista suspensa antes do carregamento da interface. Então, em vez de quatro, obter método Criar, o que eu tenho é uma chamada para o serviço de tipo folha para obter todos os tipos de folha, armazená-los nesta variável. E então eu tenho itens de tipo folha onde estou criando uma nova lista de seleção com tipos de folhas e usando id e nome como a chave e os campos de texto. E então eu estou criando o novo modelo onde eu estou passando em tipos de folha como item de tipo de folha. Então, lembrar cria solicitações de licença. Tivemos que olho público inúmeros selecionar esta propriedade item, e isso poderia facilmente ter sido lista de seleção. Tudo bem? Então, qualquer que funcione, mas nos permite trabalhar com selecionar isso porque é realmente mais fácil digitar no trabalho com. Então isso é tudo o que está acontecendo aqui. E então retornamos a vista mostrando o modelo. Conhecendo o método post, nós praticamente seguimos o mesmo procedimento se o estado do modelo é válido. Porque lembre-se que em nosso modelo de visão temos uma regra de validação poucos, então queremos ter certeza de que tudo é atendido antes de podermos prosseguir. Na verdade, estou percebendo que estou perdendo uma regra de validação sobre o ID do tipo de folha em si. Portanto, eles devem selecionar um ID de tipo de folha antes de prosseguir. Tudo bem, então deixe-me espaçar todos eles para que você possa ver tudo. Lá vamos nós. Então, se o estado do modelo é válido, então vá em frente e largura na resposta do trabalho do serviço de solicitação de licença, que vai tentar criar uma solicitação de licença. E, em seguida, se for bem sucedido, então podemos redirecionar para o índice. Não há nenhuma página de índice aqui ainda, mas isso não é problema. E então podemos adicionar qualquer modelo, modelo de estado setas provenientes de nossos erros de validação de resposta. Mas então se a página tem que recarregar, o que precisamos fazer é realmente recarregar a lista de seleção de tipos de folhas, certo? Então, uma coisa com listas suspensas no caso de você não estar tão familiarizado com elas. Sempre que você está carregando a página, você tem que carregar a lista. Então, carregamos a primeira camada da página, onde carregar essa lista e, em seguida, retornar o modelo. Temos que fazer a mesma coisa aqui. O que nós já temos os dados vindos do modelo? Então nós só precisamos reatribuir os dados para a lista de seleção recém-carregada antes de retornar o pH juntamente com quaisquer erros que precisam ser exibidos. Agora, aposto que autorize o discurso que é bastante padrão neste momento. E em nosso arquivo de layout temos algumas mudanças. Então eu coloquei os links lá apenas para que os funcionários possam ir e criar nossa visão. A minha folha, ainda não terminei a minha licença, mas aqui estão as nossas ligações, certo? Então, no mesmo Isso é verificar se o usuário está autenticado. Estou vendo se é um funcionário que está conectado porque os administradores não têm alocações, então eles não precisam ir e solicitar sair, certo? Então, se é um funcionário que está logado, então eles podem ver dois novos NovaLink cisne indo para solicitações e criar. E diz que os pedidos saem, embora eu vá embora, que ainda não fizemos, mas estamos chegando lá devagar, mas com certeza, certo? Então, depois de fazer tudo isso, vamos em frente e definir ou vários projetos iniciais mais uma vez e testar isso. Então agora eu vou fazer login como o administrador do usuário, mas o funcionário. E uma vez que eu faço isso, eu vejo meus dois links na barra de navegação. Então, quando eu vou para solicitações de licença, eu estou recebendo esse erro. É um erro 403 e eu vejo isso e eu sei exatamente o porquê. Então eu mencionei que ainda estamos para compensar todas as exceções que podem ser lançadas através da API. Este é um deles. Este é um 43 que é uma exceção não autorizada. O problema é que quando estávamos testando pontos finais doadores de lote de hotel, tínhamos definido administrador autorizado em todos os controladores de tipos de folha. Então sei que este funcionário precisa ter a lista de tipos de folhas exibir para ele. O aplicativo está fazendo essa solicitação neste endpoint, mas ele não é um administrador. Então, o que podemos fazer aqui é t o autor está fora ou pelo menos as funções estipulação fora do autorizado e apenas autorizar aqueles que estão aumentando os dados para que o post PUT e excluir esses ajustes feitos. Podemos tentar esta operação novamente. E voilá, então não, podemos navegar com segurança até lá como um empregado. Então vamos tentar aplicar para as folhas de férias. Então eu acredito que este título, você pode ver que ele está indo todo o caminho de volta para janeiro, eu acho que o início do tempo, nós sempre podemos definir padrões porque você provavelmente não quer essa extensão de tempo. Mas não vamos fazer isso. Farnell, o que eu vou fazer é simplesmente selecionar o primeiro de janeiro a 5 de janeiro e perceber que é o mês, o ano. Esse é o formato que ele está usando. Tudo isso é personalizável, mas não vamos entrar em todos os originais. Então saia de férias. E então quando eu pedir licença, eu estou recebendo outro erro. Então este erro, ele está dizendo que o parâmetro não pode ser nulo. Então eu suspeito que esta é uma seta voltando de nossa API que não está sendo tratada mais uma vez, mas vamos para o modo de depuração e ver exatamente qual é o problema. E aqui está o culpado. A parte legal está em nós tentando obter o endereço de e-mail. Então deixe-me apenas recuar um pouco. Nós temos o usuário, nós temos as reivindicações. E se você olhar lá dentro, nós temos a reivindicação do endereço de e-mail. Tudo bem. Então o endereço de e-mail está presente. No entanto, acredito que estou usando o valor errado aqui. Diga se eu voltar para onde gerou o JWT, que está no serviço de autenticação. Eu usei o mesmo nome de reivindicação que era simplesmente e-mail. Certo. Então, se eu clicar com o botão direito do mouse ou com a tecla Control pressionada, você verá que é apenas um e-mail de texto estático. No entanto, em contraste, ele está realmente vendo que limpo com uma chave diferente. E essa chave é mais adequada fora do esquema de sabão XML. E esse tipo de afirmação seria, na verdade, ou esse texto estaria presente em tipos limpos. Então deixe-me parar e ir em frente e mudar isso para tipos limpos pensamento e-mail. Então, ele falhou na recuperação do endereço de e-mail e é por isso que nós não fizemos. Bem, você tem esse erro, certo? Então, se verificarmos nossa tabela de pedidos de licença, tenho certeza que vamos realmente ver alguns dados, certo? Então você vê aqui nós temos férias e , portanto, é cada vez que ele foi comprado, certo? Por isso, está realmente a funcionar. Estava apenas falhando na recuperação do endereço de e-mail. Então, com essa correção, devemos ser capazes de continuar sem obstáculos. Mas então você vê que algo completamente não relacionado com a operação chave causou a falha, é por isso que tentamos toda essa tentativa pegar apenas para enviar o e-mail sem incomodar todo o resto. Bem, então vemos que este é também um ponto de falha. Concedido, acabamos de consertá-lo. Bem, nós poderíamos teoricamente pegar isso e também colocá-lo dentro do try catch para que qualquer e-mail relacionado não lance um erro. Agora que temos o processo de solicitação, não nos deixe fazer uma pausa e quando voltarmos, veremos o processo de aprovação deles. 35. Gestão de pedidos de Leave - Admin: Agora que temos o nosso pedido de licença para o empregado disse, não. Precisamos realmente colocar em algumas outras coisas para que o administrador possa realmente ver as solicitações pendentes e aprovar ou rejeitar. Agora, isso vem com algumas mudanças quebrando para resolver os manipuladores e alguns outros pedidos, alguns dos detalhes, algumas coisas que fizemos até este ponto, mas como de costume, eu vou apenas guiá-lo através de todas as modificações necessárias em algum lugar para começar fora com a gordura que é realmente foi em frente e criou que classe constantes de custo para os tipos de reivindicação são discutidos. Removendo as cordas mágicas como colocar UID muitos corpos, certo? Então eu criei um tipo de reivindicações personalizadas, apenas uma classe estática pública. Está em constantes sob o projeto de aplicação. E temos contras públicas String UID é igual a UID. Então isso agora nos permite no serviço de auth dizer fenótipos de traje ponto UID e passar isso em e em qualquer outro lugar que possamos precisar para fazer referência a este tipo de planície costeira como fizemos nos outros manipuladores. Em seguida, podemos apenas ir em frente e dizer tipos de reivindicação personalizados ponto UID. Saiba que outra modificação que estou fazendo é o nosso serviço de usuário. Eu tinha um método para que todos os funcionários agora têm outro para obter apenas um funcionário com base no ID do usuário. Tudo bem, então, na implementação desse método, basicamente, eu estou apenas dizendo para obter o funcionário encontrar por ID e então eu estou retornando um novo objeto empregado com os vários campos incluídos. Saiba que também atualizei nossa lista de solicitações de licença, DTO, e adicionei as datas de início da hora e, na verdade, essas datas não estavam lá antes, bem como o objeto do funcionário e a ID do funcionário solicitante. Então saiba quando o administrador está visualizando a lista de solicitações, eles podem ver o que as solicitações, as datas de início e as datas de término da solicitação cetera, bem como os detalhes da pessoa que o solicitou, teria feito um modificação semelhante às solicitações de licença, onde nos certificamos de incluir informações dos funcionários. Agora, uma modificação rápida no mapeador e neste ponto é opcional porque eu quero que você pense criticamente, não apenas faça o que eu faço, mas pense sobre isso. Temos um campo chamado dados solicitados nos objetos de domínio de solicitações de licença. Então isso foi criado como foi modelado fora do sistema anterior. Agora lembre-se que estamos refinando o sistema e nos livrando de alguns dos despedimentos e citações de caracóis. E eu acho que esta é uma dessas cotações corre porque as solicitações de data que realmente é a data criada. Então, já estamos capturando a data. Cada registro é criado. Eu não tenho que colocar o pedido novamente, e francamente, nós não fizemos isso em um manipulador quando o pedido foi feito. Então o que eu estou fazendo aqui é que eu estou realmente fazendo um mapeamento, nosso mapeamento personalizado para nossos certos campos. Então, estou vendo que sempre que você estiver mapeando do objeto de domínio para o DTO, procure nos detalhes ou no destino e obtenha o campo de data solicitada. E então eu quero que seja mapeado diretamente para o que está no campo criativo e deixar objeto de domínio de solicitação. Certo, mais uma vez, isso é opcional. Que sinceridade, como as taxas que eu estou apenas mostrando a você o poder do outono superior nos ajuda a apenas crescer, certifique-se de que todos os dados estão lá, é lugar relevante e apropriado. Agora, vamos para os nossos encarregados. Então eu fiz algumas alterações no manipulador de solicitações de licença e alocação de licenças e perda para a lista e o detalhe. Então eu vou começar com a lista já que essa eu acho que tem mais mudanças do que não. Então um, eu modifiquei a solicitação para ter este sinalizador para dizer que está logado usuário, seja, estamos tentando obter a lista de solicitações de licença para o usuário conectado são para um administrador. Então, no manipulador, eu estou injetando o acessor de contextos HTTP, bem como eu usá-lo. Acho que não estão lá antes. Conhecer alguns injetá-los e qualquer outra coisa que não estava lá antes. Não, sinta-se livre para ir em frente e replicar. Mas então dentro do manipulador, o que estou fazendo de forma diferente, não, eu estou inicializando os pedidos de licença este top, top. E eu tenho outra lista para o detalhe que será devolvido, que neste caso é deixar pedidos lista PTO. Então eu estou verificando se o pedido diz que é para o usuário conectado ou não, certo? Então, se é para o usuário conectado, eu quero ir em frente e obter esse ID de usuário lá. Estou usando minha constante, ver como é agradável e limpo. Tudo bem, então eu estou recebendo o ID de usuário e, em seguida, eu realmente implementado outro método para obter solicitações de licença com detalhes relativos ao ID de usuário. Então vamos para a implementação do método. Então, no contrato para eu deixar solicitações que eu tenho que obter pedidos de licença com detalhes, o original que escrevemos juntos e este novo com o ID de usuário string. De modo que um com o ID de usuário basicamente apenas adiciona em uma condição em que o ID solicitante no registro é igual ao ID de usuário que está sendo passado. Nós ainda incluímos os detalhes do tipo de folha e enviamos de volta essa lista. Agora, depois de fazer tudo isso, eu usei o serviço do usuário para obter o funcionário relativo ao ID do usuário que está, lá. E então eu faço um mapeamento do objeto de domínio em nossos detalhes. Em seguida, para cada objeto de solicitação na lista de solicitações ou detalhes, estamos atribuindo o valor dos funcionários para ele. Então, mais uma vez, isso seria se eu estivesse conectado como um usuário e eu quisesse ver minha lista de solicitações. Isso vai lidar com isso. Agora, se o administrador solicitar, é praticamente o mesmo que era antes, onde nós apenas obtemos todos eles com os detalhes. E, em seguida, para cada pedido, nós vamos realmente procurar o empregado em tempo real, certo? Então, enquanto conhecemos o empregado porque eu sou o usuário conectado, então é apenas um de mim. Não sabemos se há muitos empregados diferentes. Então, para cada pedido, vamos buscar esse empregado e colocá-lo dentro disso. E no final do dia, devolvemos os pedidos. Da mesma forma, estou fazendo uma operação semelhante para as alocações de licença, onde eu estou buscando todas as alocações do banco de dados têm um método semelhante e praticamente esse código parece da mesma maneira. Tudo bem, então apenas da mesma forma que adicionamos a solicitação de licença de alocação ingênua com detalhes relativos ao ID do usuário. É da mesma forma implementado método como esse para ou deixar alocações onde o ID do funcionário é o ID do usuário e somos o mesmo se declaração. Adicionamos o mesmo tipo de inundação ao nosso pedido, certo? Então nos solicite quem está logado usuário e, em seguida, temos a declaração if. Se está logado, então praticamente o mesmo procedimento que acabamos de ver. Relativo para deixar alocações. No entanto, então eu tenho obter pedidos de licença detalhes. Então é quando você quer um pedido de licença. Então imagine isso. Quando o administrador vê a lista de solicitações de licença, ele ou ela precisa clicar nessa solicitação de licença para, em seguida, ir para uma tela para ver se ele está pendente, é aprovado ou ser capaz de aprovar centenas ou rejeitado naquele momento. Certo. Então eu modifiquei as solicitações get com detalhes onde eu coloquei nesta linha para incluir as informações do funcionário. Então praticamente todas as modificações até agora são jogadas no fogo que precisamos colocar nas informações dos funcionários. Então, uma vez que atualizamos essa classe de solicitação , precisamos saber, deixar nosso endpoint ou comportamento refletir esse novo parâmetro, certo? Então, no começo, eu vou passar em um booleano. É o usuário conectado que procuramos? Se é o que eu estou inadimplente em quedas, certo? Então é assim que você pode colocar em um parâmetro padrão onde se você não fornecer um valor, então ele é falso, certo? Então, independentemente do seu valor, vamos passá-lo para o objeto de solicitação e, em seguida, o manipulador vai atender a decisão como acabamos de ver. Então eu fiz isso em ambas as alocações de licença e o manipulador de solicitações de licença recebe. Como de costume, uma vez que você atualize seu EPA, qualquer coisa com o azul virou para ter qualquer coisa no controle, você deseja executar novamente e agrupar e obter uma nova cópia desse código de cliente. Não quero saltar de volta para o nosso aplicativo cliente. Vamos olhar para o nosso contraste. Então, os próximos que eu quero absolutamente prestar atenção seria a aprovação da solicitação e para obter a lista de solicitações de licença de administrador. Tudo bem, e nós também precisamos obter pedidos de licença por ID. Então, pelo menos esses três precisam ser implementados agora. Então eu tenho outros métodos lá, e no final deste curso eles serão implementados. Mas eu não vou gastar muito tempo na toca do coelho de tentar obter cada característica. Para este módulo, vamos apenas focar no funcionário ser capaz de pedir licença e o administrador ser capaz de aprová-lo ou rejeitá-lo. Então, depois de ter incluído esses três métodos no contrato, passamos para a implementação. Então, é claro que agora tenho certeza que você atualizou seu código de cliente. Então tudo o que tenho aqui deve funcionar para você. Então, para o pedido de licença aprovado, o que estamos fazendo é tomar int id e a bandeira ou o booleano para ver é aprovado Sim ou não. Em seguida, vamos formular ou solicitações onde colocamos detalhes de aprovação de solicitação de licença de alteração, e passamos em que aprovado e o ID. E, em seguida, aguardamos o cliente chamando alteração aprovação assíncrono, onde ele envia sobre o id e a solicitação. Nosso pedido de licença é bastante direto para a frente. É apenas retornando pedidos de licença modelo vista. Nós adicionamos nosso token de portador claro, que também fizemos na aprovação do pedido. E então vamos em frente e tentar Fitch a partir dos pedidos de licença get-go, obter uma sincronização com o meu ID e retornar a versão esfregada do pedido de licença na forma do pedido de folha ViewModel. Vamos olhar para isso em alguns mais uma vez. próximo método digno de nota seria o get admin leave requests por lista. Agora eu vou explicar o que eu estou indo para é no aplicativo original sobre o que nós tínhamos feito foi nós temos todos os pedidos de licença e nós tentamos agrupá-los e, em seguida,. Descobrir é para o total de pedidos de licença, é para quantos são aprovados pendentes, et cetera, et cetera? É exatamente o que estou fazendo aqui. Então eu estou recebendo todas as solicitações de licença e notas desta vez eu tenho que o parâmetro é registrado no usuário dois-pontos false. Só estou nomeando o perímetro. Esta parte é realmente opcional, mas acho útil. Então isso é que eu não consigo lembrar o que o valor realmente significa em termos de chamada de função. Mas eu estou passando em quedas porque este não é o usuário conectado. Este é o administrador, certo? Então, o administrador está recebendo todas as solicitações de licença e, em seguida, eu estou apenas criando esse modelo admin licença solicitações exibir modelo. E estamos transmitindo o número total de solicitações, quantas são aprovadas, rejeitadas e colocando na lista de solicitações de licença em geral, e estamos retornando o modelo. Tudo bem, então, mais uma vez, todos são trabalhos pesados acontecem dentro do serviço? Não, dentro de nossas configurações de mapeamentos, atualizei isso para refletir alguns dos novos mapeamentos que podemos esperar. Assim, para um detalhe de solicitação de licença para deixar VM solicitação, há uma ligeira diferença no tipo de dados entre as ações. Tudo bem, então de um lado nós temos datetime, mas então o detalhe que é gerado através ou em código swag realmente nos dá um deslocamento de data e hora. Eu não estou totalmente certo por que ele faz isso, mas a solução seria que quando estamos mapeando, nós apenas dizer quatro membros puro solicitado, ir em frente e mapeá-lo a partir do tempo ponto-ponto solicitado. E fazemos isso para a data de início, e fazemos isso para a data de término. E isso realmente vai cuidar desse erro. Então, se você não fizer isso, se você quiser testá-lo, você pode comentar isso. Tente executar o código que exigiria mapeamento. E então você veria o erro superior do outono dizendo que o mapeamento está falhando para os campos relacionados ao Beta. Tudo bem, então você pode fazer isso para as solicitações de licença para deixar solicitações, VM, deixar detalhes da lista de solicitações para a VM solicitações de licença. E, em seguida, além desses novos, Eu também tenho um aqui para o funcionário onde eu também criei o empregado VM, que se parece exatamente com o funcionário ETO saber dentro das solicitações de licença exibir arquivo modelo. Vamos apenas rever alguns dos modelos de visão, pelo menos aqueles que são absolutamente necessários para que possamos completar esta atividade. Então nós adicionamos o empregado VM com empregado dentro deste modelo de visão, é claro, em última análise, vamos ver quaisquer duas propriedades com o mesmo nome. Vai tentar mapeá-los, certo? Então, está implícito que o empregado vai mapear para empregado a partir do detalhe para o ViewModel, certo? Nós também temos a solicitação de administrador ViewModel que nós não necessariamente olhar antes, não. Então isso é como esses campos e total de solicitações, solicitações aprovadas, solicitações pendentes, solicitações rejeitadas e a lista de solicitações de licença. Então você pode ir em frente e certificar-se de que você tem representação para o ViewModel em seu código. Mas voltando ao nosso controlador de pedidos de licença é C. Você sabe que eu tenho três novas ações são 14, o índice, um para os detalhes e um para aprovar solicitações. Então índice que tomará modelo e este modelo será do tipo admin deixar Solicitações Exibir VM ou o que ele está chamando o serviço de solicitação de licença ponto get, alavanca admin, lista de missões são o administrador verá esta página onde mais uma vez essas estatísticas e a lista de pedidos pendentes estarão em exibição. Nosso método de detalhes basicamente estará lá para quando eles estiverem vendo a lista e eles clicarem em um dos itens. E, em seguida, queremos ir e buscar que deixar pedidos com todos os seus detalhes e retornar a vista em conformidade. Então temos o Aprovar Solicitações, não aprovar solicitações vai basicamente ver ir em frente e aprovar a solicitação, ele HTTP post. Então, vamos colocar um farm nessa página onde vamos chamar isso passando esse ID de solicitação de licença, bem como se ele é aprovado ou não. Então, se eles estão aprovando ou rejeitando qualquer um, ele vai passar isso. E então você está vendo como ele passa para a API, para o manipulador e o que ocorre antes de implementarmos essas exibições. No entanto, quero apenas que acompanhemos toda a extensão do que acontece quando é aprovado. Então eu vou saltar para as atualizações, para o manipulador de solicitações que sofreu alguma quantidade de mudanças também. E eu vou te guiar por isso. É claro que você pausa e replica conforme necessário. Então nós sabemos injetando o repositório de licença Qi Shun além de qualquer outra coisa que estava sendo injetado neste arquivo. E a razão para isso é que precisamos ser capazes deduzir a alocação quando houver uma aprovação. Então o que estamos fazendo aqui é refatorar nosso método tratado para isso. Então eu recebo as solicitações de licença em primeiro lugar, e então eu vejo se estamos lidando com um detalhe de solicitação de licença do que eu quero executar a validação porque o que estava acontecendo inicialmente ou a maneira como escrevemos o código inicialmente, o estava sendo executado independentemente de ser nulo ou não. Saber se o teste de validação para validar o nosso nulo, então isso também vai lançar um erro. E jogar tudo fora. Então, estamos apenas validando nosso DTO de solicitação de licença quando ele está presente. E então, se tudo estiver bem, vamos em frente e fazer nosso mapeamento e nossas atualizações. Agora. Caso contrário, se for o detalhe de alteração dv requests que não é nulo, que neste caso de aprovação é, então não é em vez de aguardar o método de status de aprovação de alteração do repositório de solicitações de licença passando na solicitação. E a gordura que queríamos provar. Então eu vou dizer se o ponto de solicitação alterar detalhes de aprovação, que é aprovado, valor de ponto, se isso é verdade, certo? É tudo isso realmente avalia equivalente a verdadeiro. Mas é claro, ao lidar com Booleans, você não precisa necessariamente ver o equivalente ao verdadeiro. Podemos ver se o booleano, certo? E não precisamos nos preocupar com outra exceção, porque sempre deve ser, sempre deve ter um valor. Então esse é outro objeto que podemos fazer em relação aos detalhes porque neste momento eu acho que nós o tornamos anulável, o que não, nós pensamos sobre isso é errado. Ele sempre deve ter um valor tanto que eu vou remover esse booleano e nós podemos atualizar nosso código de cliente swag de acordo, mas mais tarde podemos fazer isso. Então, estou atualizando esse detalhe para ser sempre verdadeiro ou falso. Então, se for verdade, então teremos a alocação para o empregado. Então var alocação é igual para obter aplicativos de usuários. Este é um novo método. Então este novo método, mais uma vez, você colocá-lo dentro do contrato. Mas quando você implementá-lo, é basicamente pegar a string usando o ID do usuário e o ID do tipo de folha. Então nós vamos e dizemos, me dê a alocação de folhas. Primeiro, nossa assíncrona padrão, onde o ID do funcionário é muito o ID do usuário que está sendo passado e o ID do tipo de folha corresponde ao que está sendo passado. Então, depois de fazer tudo isso, passamos o empregado solicitante junto com os pedidos de licença. Então nós temos o pedido de salto aqui. Temos o empregado que o solicitou e sabemos o tipo de folha cortesia do pedido mais uma vez. E então nós vamos dizer, me dê o número de B, certo? Então, já vimos que na criação estão no pedido em vez, quantos D estão sendo solicitados. Nessa situação, você poderia tomar outra decisão. Você poderia decidir armazenar o número de Ds no banco de dados desde o início ou calculado em tempo real como estamos fazendo, não. Então, isso é com você. De qualquer forma, obtemos o número de cervejas, vamos em frente e adotamos o número destes do d é solicitado a partir do número de dias para a alocação. E então executamos uma atualização para essa alocação, então retornamos. Não, em termos de nossas opiniões que muito nossos controladores, criamos o índice e criamos os detalhes. Verdade seja dita, o índice é uma cópia dividida do que vem do código antigo. Então, se você baixou todo o código-fonte ou você pode simplesmente bem, É no GitHub. Você pode realmente tirar tudo dessa página de índice de pedidos de licença correspondente e, por favor, aqui, eu não modifiquei nada. Quaisquer modificações necessárias seriam devidas a diferenças de nomenclatura. Por exemplo, aqui eu tenho item.name empregado em vez de item.name solicitando empregado. Fora isso, porém, o código é praticamente o mesmo. Agora, para os detalhes, eu fiz algumas modificações porque no código original, nós repetimos esta seção de alerta três vezes. E o que fizemos foi dizer, se aprovado, então mostrar este código de alerta com um nome de classe diferente em texto oculto diferente. Caso contrário, se for verdade, mostre-o novamente com a direita. Então, em vez de repetir isso e isso é outra parte, seca, não se repita. Então entre no fator, você sempre quer dizer, bem, algo precisa ser repetido em algum momento, certo? Ou alguma operação precisa ser refeita. Mas qual posso refazer com o menor caminho de resistência R, que seria mais fácil de manter a longo prazo. Então minha refatoração do que foi feito nos detalhes originais do pH seria que eu estou criando duas variáveis aqui. Um interessante, um para cabeçalho, texto de cabeçalho. E, em seguida, se a aprovação for nula, então eu dou ClassName e bater leva seus valores. Se for verdade, dou-lhes valores diferentes, etc., para. E então eu carrego o div com o outro em um momento onde eu passo dinamicamente o nome da classe e os textos de cabeçalho, porque tudo o resto dentro desse alerta vai ser o mesmo independentemente, certo? Então eu digo o nome do empregado e então eu coloquei o nome e sobrenome do empregado. A data solicitada é que eles solicitaram voltar do modelo. E então praticamente tudo o resto é o mesmo até a última parte onde estamos verificando se ele é aprovado ou não. Então, em vez de ter que vincular botões como o código original já tinha até eles em fazendas onde eles discutiam por que fóruns são muito mais seguros. Então, para o método post é o axônio provar pedido. E neste eu tenho o ID que é um oculto, e ele tem um valor para a idéia do módulo também tem outro oculto que tem o nome aprovado e o valor é verdadeiro. Repito esse feed para a rejeição, exceto que o valor para o aprovado é falso. Então, quando eles clicam em qualquer um desses botões vai chamar aprovar solicitações, que é, em seguida, vai obter ID e custos aprovados que não basta passar pelo que o manipulador faz com todas essas informações. Tudo bem, então nós temos este módulo por algum tempo, e este é geralmente o módulo mais difícil e demorado. Eu tentei reduzir o tempo o máximo possível, mas então há muito mais a fazer, mas pelo menos você tem os conceitos fundamentais para que você possa pegá-lo e continuar. Então vamos apenas visualizar o que este pedido de licença será parecido do ponto de vista do administrador. E solicitações semanais de clivagem verão a lista de solicitações de licença. Então eu já aprovei e rejeitei um e é assim que esse código se parece. E este está pendente de aprovação e vemos a data de início, a data de fim, o tipo de licença de férias, o nome do empregado, tudo é bom e, você sabe, cuspir para nós. Então, se eu clicar em revisar, vamos até a página onde diz aprovação pendente que eles solicitaram e então eu posso aprovar ou rejeitar. Então, se eu clicar em Aprovar, ele irá redirecionar assumindo que não há erros. E, na verdade, há um erro. Tudo bem, então o problema aqui é que eu estou usando o código do criar, a fim de fazer o cálculo, o que é completamente incorreto porque eu deveria estar usando o objeto de solicitação de alavanca e não solicitar ponto leave request details, Certo, então deixe-me atualizar isso e podemos tentar novamente essa operação. Tudo bem, então vamos tentar de novo. Vou clicar em Aprovar. E lá vemos que não foi aprovado. Saber que o problema que vamos ter que resolver mais tarde é o fato de que temos várias operações sendo realizadas contra várias tabelas. Mas adivinha o que aconteceu? Um participante e a outra parte não, significa que isso foi aprovado, mas a dedução não aconteceu porque tivemos uma falha naquele lago. Certo. Então nós realmente fizemos a aprovação com sucesso, mas então a parte de dedução não passou, então ele não foi atualizado. E o que queremos fazer é fazer algo como o nosso fanfarrão, deve ser tudo ou nada. Então, se uma parte campos, então tudo deve sentir. Então é aí que a unidade de trabalho tipo de entra em jogo ou no nível de banco de dados chamamos de transações. Então, mais tarde, analisaremos todos esses problemas de limpeza com nosso aplicativo. Sempre que um aplicativo tão grande, você tem que olhar para fora para essas coisas. 36. Unidade de trabalho para operações castas: Nesta lição, vamos configurar um middleware de manipulação de exceção global para nossa API. Então o que acontece é que tivemos exceções personalizadas que criamos desde quase o início do projeto. Temos lançado exceções em certos pontos de nossos manipuladores. No entanto, não temos necessariamente dito ao todo API que deve responder quando exceções são lançadas. Então, é claro, você vai querer sempre falhar graciosamente se houver um tipo de exceção, queremos enviar de volta um código que é indicativo do tipo de exceção. Por exemplo, atualizei todos os meus manipuladores de atualização para também lançar uma exceção não encontrada. Então, depois de saber, deixe-me corrigir este. Tão aberto para saber. Eu não tinha o código. Se você já tinha o código, então isso é bom. Isso é parabéns para você, certo? Mas estávamos lançando exceções de validação quando a validação falha. Mas então o que acontece se o registro a ser encontrado não foi telefone, então queremos uma exceção não encontrada. Então eu adicionei que em cada cheque para ver se alocação de licença é encontrado, se as solicitações de licença, Isso é um barco para ser atualizado seu telefone e se a licença desculpe, o tipo de folha, seu objetivo. Se o tipo de folha é telefone, nós apenas lançamos uma exceção não encontrada. Tudo bem? Então, lançar a exceção é fácil o suficiente. Lidar com isso é outra coisa. Portanto, note que não há nenhuma tentativa capturas em. Seria uma espécie de arrogante para a frente tentar e colocar a captura tentativa e cada um deles. Então, o que vamos fazer é configurar e lidar com exceções middleware no nível da API porque o controlador usa mídia para chamá-lo de manipulador, mas também não temos nenhuma faixa de captura aqui, então estamos sempre retornando, ok? Mas, em seguida, há momentos em que a exceção é lançada e está bem, pode ser lançada. E na API é literalmente apenas jogando algum dólar de resposta aleatória no cliente. Queremos ter certeza de que sabemos o que está sendo lançado. Então vá em frente e crie uma nova pasta no projeto de API chamado middleware. E nessa pasta crie um arquivo chamado middleware de exceção. Então esse é o nosso middleware de exceção cruzada. E eu vou apenas orientá-los sobre o que isso vai estar fazendo na web ou em detalhes. Então nós temos uma classe nesse arquivo, naquela outra classe chamada detalhes de erro. Só estou te guiando pelas partes mais simples primeiro. E os detalhes do erro só tem o tipo de erro e uma mensagem de erro. Então, pelo menos, podemos sempre informar ao cliente que isto foi o que deu errado baseado na circunstância com que nos deparamos, certo? Agora. Tudo o que disse que temos dentro da classe para middleware excepcional, temos campo privado somente leitura chamado próximo, e que é do tipo de solicitação delegado. Então nós instanciamos isso no construtor. E então temos um método chamado invocar uma pia. Então pública AsyncTask invocar assíncrono e leva um parâmetro chamado contextos HTTP. Então nós já meio que olhamos para o que os contextos HTTP nos permitem fazer. Basicamente, permite ver o pedido, a resposta, tudo com um fluxo de trabalho completo entre cliente e servidor é armazenado dentro deste contexto HTTP. Então isso vai estar agindo como um interceptor, vai tentar ver. Ele vai dizer fazer a próxima opção que deve ser concluída através dos contextos HTTP. Isso é basicamente o que isso está fazendo. Dela. Os contextos http fazem a sua próxima opção. Se houver uma exceção, vamos pegá-la e depois vamos lidar com isso. Agora, vamos para a forma como lidamos com isso. Portanto, a exceção de identificador de tarefa privada é coletor onde dando-lhe o contexto HTTP e a exceção que foi capturada. Saiba que estamos apenas dizendo que queremos uma resposta punted para ser aplicação barra JSON porque é a API. Então sabemos que tudo o que respondermos será na forma de JSON. Também estamos definindo um erro interno padrão do servidor, escola de status do código de status HTTP é padrão para o que é 500. Então vamos dizer que o resultado é igual a, Eu nunca quero serializar objetos em uma nova instância de seta com a mensagem de exceção. Certo, então vamos serializar tudo isso nos resultados nulos quando entrarmos no interruptor. Onde basicamente vendo que tipo de exceção é esse, porque exceção é o tipo de dados base. Mas como vimos, temos nossas próprias exceções. Temos a exceção de validação, temos o deixe-me sair a exceção de pedidos de manteiga. Temos a exceção não encontrada. Então podemos explicar todas essas contas por um mau pedido. Não estou contabilizando validação. - Eu. Vá em frente e atualize isso. Então o que estamos fazendo aqui agora é ver me dizer que tipo de exceção é. Eu sei que é uma exceção, mas de que tipo era realmente não era um pedido tão ruim. Uma exceção da validação, em vez disso, deve a sua eu não sou encontrado. Baseado no único ponto a fazer é que vamos mudar o status quo. Então é padrão para 50, 100. Ou seja, se foi apenas o pouco excepcional, talvez tenha sido uma falha no nível do banco de dados, talvez tenha sido uma falha de rede que não podemos resolver. E quatro, então é definitivamente um 500. 500 significa que é um sistema, o sistema que a API está usando, é culpa do sistema. No entanto, solicitações ruins indicariam que você é culpado como um cliente, mas você me enviou dados de lixo. Então eu vou te dizer que é um pedido ruim, que foi há 400 anos atrás. Se for uma exceção de validação, isso também é um tipo de solicitação ruim porque você me enviou mas dados, mas você sempre pode olhar através e ver o que outro código pode ou melhor para o tipo de exceção. Tudo bem, mas você sempre quer ficar no intervalo de 400 com códigos de erro, certo? Então é aí que estamos. Então, quero dizer para você, isso é sozinho. Então este diz Mas pedido e não encontrado exceção é um 40 para o significado que eu não poderia encontrar o que você está procurando. Então 40 por isso, se nenhum desses fosse o caso, então nós apenas quebramos e isso permaneceria como um 500. Então vemos responder com o código de status e retornar com o resultado. Resultado, o que significa que toda a mensagem que fazia parte da mensagem de exceção. Então lembre-se que quando estamos configurando nossas exceções ou lançando nossas exceções de nossos caçadores, estávamos sempre sentando a mensagem. E essa mensagem é o que está sendo serializado aqui. Estou sendo enviado bokeh provocou essa resposta. Nulo se quiser que seja um pouco mais explícito. Porque tudo o que estamos fazendo é enviar sobre seta com mensagem de exceção, podemos usar nossos detalhes de erro. Eu poderia ter dito novos detalhes de erro e, em seguida, mensagem de erro seria a mensagem eo tipo de erro poderia ser outra coisa. Então eu diria Eric Type Tool e, em seguida, provavelmente apenas dizer falha, nosso erro, o que quer que seja para que você possa ser criativo. Quer dizer, cabe a você o que, mais uma vez, é isso que eles receberiam em sua resposta, o que quer que você coloque lá. Então, um modo que terminamos de configurar esse middleware, precisamos saltar para o arquivo de inicialização para API. E inserção do Configure sexual. Vamos dizer a ele para usar o middleware. Então eu vou apenas fazer isso acima de tudo o resto. Eu não quero dizer até DOT usar middleware, exceção no middleware. Vá em frente e adicione as referências que faltam. E lá vamos nós. Então todos nós temos nosso middleware tentando capturar globalmente e, em seguida, lidar com graciosamente como ele responde a qualquer cliente que é sua vocação. Eu só queria voltar para a implementação mais uma vez e ter um ajuste rápido. Eu não sei por que eu tinha se isso fora inicialmente. Então, com os resultados para a exceção de validação, nós definitivamente queremos que os erros de exceção sejam Buck no corpo, certo? Então as mensagens de validação, uma coisa, tudo bem. Mas então queremos que os resultados sejam iguais à serialização JSON da validação das setas, certo? Então, mais uma vez, você tem muitas opções sobre como lidar com a situação. Então, estamos colocando a mensagem de exceção por padrão, mas estamos substituindo-a no caso do erro de validação. Então, será a lista de erros. 37. Manejo com expressão API: Muito bem, pessoal, bem-vindos de volta. Esta lição é inspirada no ponto de falha que vimos quando estávamos alterando o status de aprovação dos pedidos de licença, vimos que uma parte da operação foi concluída e a outra parte falhou. Mas precisamos que ambas as partes funcionem antes de atualizarmos o banco de dados. Então o que estamos fazendo agora é configurar o que chamamos de unidade de trabalho, que basicamente diz que eu tenho todo esse trabalho para fazer. Tenho todos esses pontos de contato. Vou fazer todas as operações e depois fazer um último commit no banco de dados, ou seremos bem sucedidos ou não. Então o que tínhamos era cada repositório salvando as alterações por conta própria. Então, se isso, se houvesse uma operação que exigisse dois repositórios para salvar em um lado do que os outros campos, então teríamos em dados consistentes no banco de dados e queremos evitar isso. Então eu fui em frente e configurar esta unidade de contrato de trabalho para que saibamos onde os contratos vivem em sua pasta de persistência aplicativo I unidade de trabalho. Está herdando de eu descartável. E é basicamente apenas fazendo referência às três interfaces de repositório que conhecemos. Tudo bem, então eu deixo alocação, deixo solicitações e tipo de folha, e ele tem um método que diz Salvar nós implementação vive na mesma pasta que a implementação para os outros repositórios. Então, essa é a camada de persistência repositórios pasta unidade de trabalho. Então, dentro desta implementação, estamos herdando das unidades de trabalho. Temos nosso contexto de banco de dados sendo injetado. Tudo bem, e nós fizemos referência a todos os repositórios, então eu tenho campos privados para cada repositório. Tão equivocado este arquivo está agindo como se eu me registrasse para os repositórios que temos, quero manter os repositórios únicos. Às vezes, você realmente veria uma unidade de trabalho onde ela é construída em torno dos repositórios genéricos. Então, e cada implementação será apenas genérica porque há tantos métodos únicos em nossos repositórios querem manter o repositório exclusivo está sendo referenciado aqui. Então, mais tarde cúpula, nós realmente temos a propriedade pública que muito é cada e deixe-me apenas BreakLine para que você possa vê-lo mais claramente. Então o público, eu deixo o repositório de alocação, ele vai ser chamado de repositório de alegações DV. Eu sou basicamente estamos apenas realizando eu fico assim que estamos vendo, Me dê o campo privado e se ele é nulo em inicializar uma nova instância da implementação repositório de alocação folha e passar nesse contexto que nós injetá-lo. Porque lembre-se que cada implementação tem esse contexto sendo injetado. Certo, então é por isso que temos que nos certificar de que injetamos no contexto e depois passamos para cada um deles. Então essas três linhas parecem a mesma barra nos nomes e nos tipos que estão sendo referenciados. Em seguida, temos um método de eliminação que vai ser chamado em segundo plano onde nós apenas descartar o contexto e, em seguida, suprimir a coleta de lixo final. E então nossa tarefa de salvar vai ter nossas mudanças de salvamento. Então, em outras palavras, você vai estar fazendo tudo seria colocar, nós estaríamos adicionando, vai estar fazendo o que quer que seja. Esses repositórios têm que fazer individualmente, mas então estamos fazendo um último Salvar. Tudo bem, então depois de ter implementado isso ou ter replicado tudo isso. Vamos dar uma olhada em algumas das alterações que são necessárias nos outros repositórios. Então vamos começar com um repositório genérico. Antes do que tínhamos eram indivíduos Salvar alterações no anúncio, a exclusão e os métodos de atualização. Certo, então agora estou recebendo a Groenlândia porque não há mais uma chamada assíncrona dentro dessas tarefas assíncronas? Bem, podemos resolver isso mais tarde, mas meu ponto é que eu removi todas as linhas Salvar alterações desses métodos específicos porque não queremos que eles vejam se temos que fazer várias coisas. Você deseja adicionar algo e excluir algo e fazer uma atualização. Queremos um último commit no banco de dados. Todos ou nada por unidade de trabalho estão em cada manipulador. Porque lembre-se, os manipuladores estão basicamente lidando com cenários. Então queremos que o cenário completo seja concluído, tudo ou nada. Então, removemos todo o mar de alterações do repositório genérico, bem como de qualquer outro repositório individual que possa ter um Salvar alterações sendo usado lá. Assim como em alocações onde a média tinha que salvar alterações, eu removi isso. E nas solicitações de licença tínhamos as alterações Salvar sendo feitas dentro desse método para atualizar, certo. Para alterar o status de aprovação, removi tudo isso. Agora, com essas remoções, precisamos atualizar nossos manipuladores para nos adaptarmos adequadamente. Então eu vou pular para o Criar solicitações de licença, e eu vou mostrar a vocês exatamente que tipo de refatoração aconteceria. Um, teríamos interagido com dois ou três repositórios neste manipulador. Então teria injetado eu deixar repositório, eu deixo repositório de alocação, et cetera, et cetera. Saiba que só temos que injetar ou uma unidade de trabalho. E antes que eu vá mais longe, deixe-me apenas salientar que nós sabemos que tem que registrá-lo em vez do registro de serviços de persistência. No mesmo lugar que você teria registrado todos os repositórios onde estamos apenas começando nossa unidade de trabalho ocular. Então isso o torna um componentes injetáveis. Tudo bem, então agora podemos substituir todos os indivíduos pela unidade de trabalho I. Não, você se depara com um monte de linhas de FRD. Bem, saiba onde você teve o sublinhado deixar o repositório tipo como o campo privado. Agora você pode substituir isso com unidade de trabalho repositório tipo folha ponto porque você está dando a ele o mesmo repositório apenas através da unidade de trabalho. Então este é o nosso registo para todos os repositórios fora de mim. Menção disso antes. Então eu estou apenas destacando todas as mudanças que eu teria feito saber que eu estou usando a unidade de trabalho na unidade quadrada de trabalho para o repositório de alocação de licença, unidade de quatro para o repositório de solicitações de licença. E, em seguida, quando temos uma operação que está aumentando os dados, fazemos um Save. Vê isso? Agora, enquanto eu estou neste manipulador de solicitação de licença de criação, eu só queria apontar um outro ponto de falha que eu vi em meus testes e você provavelmente encontrou e eu só quero que nós abordemos isso aqui. Isso é quando não há alocação porque eu tentei pedir licença de maternidade com um empregado que não tem licença de maternidade. Então você tem duas maneiras de lidar com isso. primeiro lugar, você poderia filtrar essa lista de tipos de folha somente em tipos de licença que são alocados para esse usuário. Assim, o usuário nunca seria capaz de se candidatar a algo para o qual não tem alocação. E francamente, eu acho que essa é uma boa maneira de fazer isso cria uma nova chamada de repositório onde você obtém essas listas apontadas e você enviou, mas não menos importante, eu acho que isso é fácil o suficiente. Eu, no entanto, fiz um ajuste neste manipulador no entretanto para dizer obter a alocação. Então lembre-se que temos a alocação e então calculamos que o d é solicitado. E se o d for solicitado, excedido, então adicionamos um erro de resultados de validação, certo? Bem, o que estou fazendo aqui é ver se a alocação não é. Então, com a nova versão de C Sharp, você não tem que ver é equivalente para saber que a vaga é não, certo? Então, se isso voltar como nulo, então adicionamos um erro de resultado de validação para o ID do tipo de folha, dizendo que você não tem nenhuma alocação para este tipo de folha. Então isso é uma simples adição. Você pode ir em frente e replicar isso ou você pode tentar por conta própria para obter a lista filtrada para esse usuário específico que está prestes a solicitar licença e exibir apenas os tipos de folha para os quais eles estão qualificados, qualquer que funcione. Agora vamos pular para o manipulador de comandos de licença de atualização, que é onde vimos os pontos de falha reais que estamos tentando resolver AGORA com a unidade de trabalho. Então, mais uma vez, injetar apenas as unidades foram forçadas a este manipulador. E você verá que é muito mais compacto, certo? E, em seguida, cada linha, você só tem que dizer unidades são quatro pontos o repositório apropriado e ponto ponto ponto o método. Saiba quando estamos aumentando os dados. Lembre-se que dissemos que se a solicitação vem com o DTO, então vamos em frente e fazer nosso mapeamento chamado atualização. E então eu vou chamar as unidades de trabalho para salvar. Tudo bem. Mais tarde, não se foi a aprovação da solicitação de alteração e foi aqui que vimos a falha, vamos em frente e mudar a aprovação deles. E, em seguida, se fosse aprovado, em seguida, ele iria atualizar a alocação. E então esse funcionou, mas então esse campo, então foi aprovado e o da pessoa não foi adotado, o que causou inconsistência. Então, não, essa pessoa teria saído de férias por 10 dias e voltaria e veremos que ainda são muitas vezes estes e pedaços quebrados e ninguém notaria. Então vamos querer ter certeza de que nosso sistema não está em falta. Certo. Então, atualizamos a alteração do status de aprovação. Tudo bem. Então, se for aprovado, atualizamos o número de dias e economizamos. Então, se isso falhar, isso acontece no banco de dados. Agora, com essa mudança e a unidade de onde está sendo introduzida, é na verdade um fator maior porque você vai realmente ter que ir em cada manipulador único que estava lidando com o aumento dados e uma unidade injetora de trabalho para provavelmente mudar referências mais antigas para os repositórios, todos em todo o lugar. E, em seguida, três, certifique-se de que você chamar o método de salvar unidade de trabalho. Agora que você fez aquele enorme fator de risco, certo? E especialmente quando você tiver feito isso para o manipulador de comando tipo folha e outros pontos de contenção que surgirão é nossos testes de unidade. Porque lembre-se, pelo menos fizemos os testes de unidade para o manipulador de comando tipo folha juntos e sabemos que você está mudando a injeção, você está mudando algo sobre isso. Então, na verdade, se você compilar nesse ponto, você provavelmente obteria alguns erros nos arquivos de teste porque nulo certas coisas não existem mais. Isso é 12. O fato de que a operação mudou em geral, precisamos atualizar artistas. Vamos começar com as brincadeiras porque é provavelmente onde você está recebendo o primeiro erro de que o repo Mach não existe mais ou que os meninos zombaria não são mais do tipo que ele precisa. Isso é bom. Então o que eu fiz foi criar um novo arquivo Mock que eu chamo de unidades de trabalho simuladas. E está seguindo o mesmo princípio da fumaça anterior, onde eu estou apenas instanciando uma simulação de nossa unidade de trabalho. Chama-se “obter unidades de trabalho”. Isso é um método. E eu tenho simulação, você vai w é igual a uma nova instância da unidade de simulação de trabalho. Não, eu tenho o tipo de folha simulada. Deixe-me corrigir esse repo tipo de folha simulada. Era com isso que estávamos lidando, certo? Então esse é o teste que escrevemos para testar os tipos de folhas. Saiba que estou usando a unidade de onde eu tenho que zombar do repositório dentro da unidade de trabalho. E eu já tenho o código para zombar das unidades do repositório tipo elif, desculpe, certo, então eu já tenho isso. Esse método não precisa mudar nada. Tudo bem. Estamos preenchendo com dados de teste e fizemos tudo isso. Não, eu preciso colocar esse Mach na unidade de simulação de trabalho. Então, tudo o que estou fazendo aqui é ver zombaria. O tipo repo é igual a chamar essa classe simulada e obter o repositório de tipo folha. E então meu aviso de configuração é que o repositório tipo folha retornará esse objeto simulado. Então eu devolvo as unidades de trabalho simuladas. Então agora no teste real para o manipulador de tipo de folha, e eu acabei de comentar algumas das linhas apenas para mostrar o que exatamente eu mudei. Eu introduzi um novo campo de tipo simulado I unidades de trabalho chamado simulação. Você vai w, w unidade de trabalho. E então eu tenho instanciado dentro do construtor chamando minhas unidades simuladas de trabalho ponto a2 unidades ou garfo. Depois, tudo o resto permanece igual. Não alinhe. Bem, para mim, 42, 43, onde eu estou vendo que o manipulador não é uma nova instância que leva a unidade simulada de trabalho em oposição à ondulação simulada já usou anteriormente e esse objeto, então tudo o resto fluirá. Então, pelo menos não nos testes temos que dizer unidade simulada do objeto ponto de trabalho, repositório tipo folha ponto obtém tudo. Da mesma forma simulação unidade de trabalho ponto ponto repositório lifo obtém tudo. Caso contrário, os testes vão passar e então você está pronto para ir. Então, mais uma vez, o teste de unidade mostraria que você preenche pontos ou potenciais pontos de falha em diferentes partes de sua aplicação apenas no caso de eles serem, ou eles passaram por atividades de refatoração maciças. Mas isso é realmente tudo para esta atividade em que estamos adicionando as unidades de trabalho. Espero que vejam o valor nele e continuemos a melhorar a nossa aplicação nas lições subsequentes. 38. Mande a expiração de Tokens: Nesta lição, vamos configurar um middleware de manipulação de exceção global para nossa API. Então o que acontece é que tivemos exceções personalizadas que criamos desde quase o início do projeto. Temos lançado exceções em certos pontos de nossos manipuladores. No entanto, não temos necessariamente dito ao todo API que deve responder quando exceções são lançadas. Então, é claro, você vai querer sempre falhar graciosamente se houver um tipo de exceção, queremos enviar de volta um código que é indicativo do tipo de exceção. Por exemplo, atualizei todos os meus manipuladores de atualização para também lançar uma exceção não encontrada. Então, depois de saber, deixe-me corrigir este. Tão aberto para saber. Eu não tinha o código. Se você já tinha o código, então isso é bom. Isso é parabéns para você, certo? Mas estávamos lançando exceções de validação quando a validação falha. Mas então o que acontece se o registro a ser encontrado não foi telefone, então queremos uma exceção não encontrada. Então eu adicionei que em cada cheque para ver se alocação de licença é encontrado, se as solicitações de licença, Isso é um barco para ser atualizado seu telefone e se a licença desculpe, o tipo de folha, seu objetivo. Se o tipo de folha é telefone, nós apenas lançamos uma exceção não encontrada. Tudo bem? Então, lançar a exceção é fácil o suficiente. Lidar com isso é outra coisa. Portanto, note que não há nenhuma tentativa capturas em. Seria uma espécie de arrogante para a frente tentar e colocar a captura tentativa e cada um deles. Então, o que vamos fazer é configurar e lidar com exceções middleware no nível da API porque o controlador usa mídia para chamá-lo de manipulador, mas também não temos nenhuma faixa de captura aqui, então estamos sempre retornando, ok? Mas, em seguida, há momentos em que a exceção é lançada e está bem, pode ser lançada. E na API é literalmente apenas jogando algum dólar de resposta aleatória no cliente. Queremos ter certeza de que sabemos o que está sendo lançado. Então vá em frente e crie uma nova pasta no projeto de API chamado middleware. E nessa pasta crie um arquivo chamado middleware de exceção. Então esse é o nosso middleware de exceção cruzada. E eu vou apenas orientá-los sobre o que isso vai estar fazendo na web ou em detalhes. Então nós temos uma classe nesse arquivo, naquela outra classe chamada detalhes de erro. Só estou te guiando pelas partes mais simples primeiro. E os detalhes do erro só tem o tipo de erro e uma mensagem de erro. Então, pelo menos, podemos sempre informar ao cliente que isto foi o que deu errado baseado na circunstância com que nos deparamos, certo? Agora. Tudo o que disse que temos dentro da classe para middleware excepcional, temos campo privado somente leitura chamado próximo, e que é do tipo de solicitação delegado. Então nós instanciamos isso no construtor. E então temos um método chamado invocar uma pia. Então pública AsyncTask invocar assíncrono e leva um parâmetro chamado contextos HTTP. Então nós já meio que olhamos para o que os contextos HTTP nos permitem fazer. Basicamente, permite ver o pedido, a resposta, tudo com um fluxo de trabalho completo entre cliente e servidor é armazenado dentro deste contexto HTTP. Então isso vai estar agindo como um interceptor, vai tentar ver. Ele vai dizer fazer a próxima opção que deve ser concluída através dos contextos HTTP. Isso é basicamente o que isso está fazendo. Dela. Os contextos http fazem a sua próxima opção. Se houver uma exceção, vamos pegá-la e depois vamos lidar com isso. Agora, vamos para a forma como lidamos com isso. Portanto, a exceção de identificador de tarefa privada é coletor onde dando-lhe o contexto HTTP e a exceção que foi capturada. Saiba que estamos apenas dizendo que queremos uma resposta punted para ser aplicação barra JSON porque é a API. Então sabemos que tudo o que respondermos será na forma de JSON. Também estamos definindo um erro interno padrão do servidor, escola de status do código de status HTTP é padrão para o que é 500. Então vamos dizer que o resultado é igual a, Eu nunca quero serializar objetos em uma nova instância de seta com a mensagem de exceção. Certo, então vamos serializar tudo isso nos resultados nulos quando entrarmos no interruptor. Onde basicamente vendo que tipo de exceção é esse, porque exceção é o tipo de dados base. Mas como vimos, temos nossas próprias exceções. Temos a exceção de validação, temos o deixe-me sair a exceção de pedidos de manteiga. Temos a exceção não encontrada. Então podemos explicar todas essas contas por um mau pedido. Não estou contabilizando validação. - Eu. Vá em frente e atualize isso. Então o que estamos fazendo aqui agora é ver me dizer que tipo de exceção é. Eu sei que é uma exceção, mas de que tipo era realmente não era um pedido tão ruim. Uma exceção da validação, em vez disso, deve a sua eu não sou encontrado. Baseado no único ponto a fazer é que vamos mudar o status quo. Então é padrão para 50, 100. Ou seja, se foi apenas o pouco excepcional, talvez tenha sido uma falha no nível do banco de dados, talvez tenha sido uma falha de rede que não podemos resolver. E quatro, então é definitivamente um 500. 500 significa que é um sistema, o sistema que a API está usando, é culpa do sistema. No entanto, solicitações ruins indicariam que você é culpado como um cliente, mas você me enviou dados de lixo. Então eu vou te dizer que é um pedido ruim, que foi há 400 anos atrás. Se for uma exceção de validação, isso também é um tipo de solicitação ruim porque você me enviou mas dados, mas você sempre pode olhar através e ver o que outro código pode ou melhor para o tipo de exceção. Tudo bem, mas você sempre quer ficar no intervalo de 400 com códigos de erro, certo? Então é aí que estamos. Então, quero dizer para você, isso é sozinho. Então este diz Mas pedido e não encontrado exceção é um 40 para o significado que eu não poderia encontrar o que você está procurando. Então 40 por isso, se nenhum desses fosse o caso, então nós apenas quebramos e isso permaneceria como um 500. Então vemos responder com o código de status e retornar com o resultado. Resultado, o que significa que toda a mensagem que fazia parte da mensagem de exceção. Então lembre-se que quando estamos configurando nossas exceções ou lançando nossas exceções de nossos caçadores, estávamos sempre sentando a mensagem. E essa mensagem é o que está sendo serializado aqui. Estou sendo enviado bokeh provocou essa resposta. Nulo se quiser que seja um pouco mais explícito. Porque tudo o que estamos fazendo é enviar sobre seta com mensagem de exceção, podemos usar nossos detalhes de erro. Eu poderia ter dito novos detalhes de erro e, em seguida, mensagem de erro seria a mensagem eo tipo de erro poderia ser outra coisa. Então eu diria Eric Type Tool e, em seguida, provavelmente apenas dizer falha, nosso erro, o que quer que seja para que você possa ser criativo. Quer dizer, cabe a você o que, mais uma vez, é isso que eles receberiam em sua resposta, o que quer que você coloque lá. Então, um modo que terminamos de configurar esse middleware, precisamos saltar para o arquivo de inicialização para API. E inserção do Configure sexual. Vamos dizer a ele para usar o middleware. Então eu vou fazer isso acima de tudo. Eu não quero dizer até DOT usar middleware, exceção no middleware. Vá em frente e adicione as referências que faltam. E lá vamos nós. Então todos nós temos nosso middleware tentando capturar globalmente e, em seguida, lidar com graciosamente como ele responde a qualquer cliente que é sua vocação. Eu só queria voltar para a implementação mais uma vez e ter um ajuste rápido. Eu não sei por que eu tinha se isso fora inicialmente. Então, com os resultados para a exceção de validação, nós definitivamente queremos que os erros de exceção sejam Buck no corpo, certo? Então as mensagens de validação, uma coisa, tudo bem. Mas então queremos que os resultados sejam iguais à serialização JSON da validação das setas, certo? Então, mais uma vez, você tem muitas opções sobre como lidar com a situação. Então, estamos colocando a mensagem de exceção por padrão, mas estamos substituindo-a no caso do erro de validação. Então será a lista de erros. 39. Mande a expiração de Tokens: Muito bem, continuamos a melhorar a nossa aplicação, e desta vez estamos a mudar o nosso foco de volta para a nossa aplicação cliente. Assim, alguns cenários aqui que não foram contabilizados, ou pelo menos provavelmente os encontramos, mas não os abordamos totalmente. Número 1, quando você provavelmente percebe agora que se você se conectou há cerca de uma hora e o próximo Buffon sua vez de usar um sistema. Eles estão recebendo exceções da API para 100 porque o token que está lá, mesmo que você esteja atribuído ao aplicativo, tolkien expirou. Então, o cliente faz as coisas, está tudo bem. Mas quando você tenta acessar a API e enviar sobre um token estático, o AICPA está rejeitando e o aplicativo não sabe o que fazer. Então você provavelmente está recebendo essas páginas de exceção. E outra coisa é que queremos configurar sua própria página personalizada para quando uma solicitação de navegação não autorizada é enviada. Significa que você é um usuário, mas está tentando acessar uma página de administração. Você teria visto MIGA o erro e você provavelmente chegou a seta onde ele está tentando ir para uma página chamada Acesso negado, que é uma das páginas padrão que nós não scuffled neste aplicativo cliente. Então eu vou mostrar a vocês como podemos tirar ainda mais proveito de todo o contexto HTTP, o pipeline de solicitação. Nós apenas fizemos isso com o tratamento de exceção para a API e tudo o que nós vamos olhar para ele no aplicativo cliente e como podemos lidar com esses diferentes cenários de forma global. Então vamos começar com o middleware costal que eu tenho configurado. E estou ligando para o seu pedido de middleware. Alguns chamá-lo solicita o middleware porque eu queria sentar-se entre todos os pedidos de navegação que já acontece em nossa aplicação. E então, assim como vimos com a API, sempre podemos interceptar, interrogar e, em seguida, tomar uma decisão como a palavra deve ir se ele atender a um certo critério sobre. Mas vamos começar com uma pasta chamada middleware no MVC up e o arquivo é chamado de requisições, o middleware. Então esta vai ser uma aula pública que leva o delegado de solicitação em seguida. E eu também estou injetando meu serviço de armazenamento local vai, lembre-se que é de onde estamos acessando o Tolkien a qualquer momento. Então vamos em frente e inicializá-los no construtor, e então temos nossa tarefa método, invocar um dissipador. Então este método tem um grande try-catch, certo? Ganhou grande try-catch. Então, vamos tentar. E a linha mais simples seria exatamente como vimos na API, seria tão simples. Tente aguardar o próximo leilão e, em seguida, pegar e lidar com quaisquer exceções. Tudo bem. No entanto, antes de avançarmos e permitirmos que ele tente a próxima ação, queremos fazer algumas verificações. Então a verificação que estamos fazendo é, bem um, estamos recebendo os endpoints. Então esta linha EP representa o ponto final. Então HTTP contextos recursos de ponto, obter o recurso de endpoint AI e obter os endpoints, significa onde você está indo, onde você ferramenta Rosing. Então eu vou ver, este ponto final tem algum atributo de metadados? Então lembre-se quando nossos controladores, estes são basicamente atributos de metadados, certo? Então, ele tem algum atributo de metadados, tipo autorize atributo? Bem, autorizado é do tipo autorizar atributo. Então eu estou vendo onde quer que você está navegando ferramenta, há um atributos autorizados nunca controlar ou são sempre ponto final tem um autor como atributo vai para casa não tem nenhum usuário, não tem nenhum. Então, se isso acontecer, que significa que temos algo, não é nulo, então queremos dizer, ok, já que este endpoint está autorizado a certificar-se que há um Tolkien e ainda mais para que este token seja válido. Então eu vou dizer atributo autor não é igual a nulo. Ou desculpe, se não for igual a nulo, então me dê o depósito local. Tolkien, certo, então vá e verifique se ele existe. E também estou vendo que é válido porque estou assumindo que é válido em todos os momentos. No entanto, se existe, precisamos validá-lo ainda mais alma, certo? Então eu estou vendo se o Tolkien existe, então pegue o Tolkien real, então eu estou usando o identificador de segurança, o manipulador Tolkien. Sabemos o que precisamos para injetar uma declaração de uso para isso. E então eu estou vendo Obter o conteúdo Tolkien, em seguida, obter o prazo de validade, e, em seguida, verificar se a expiração está concluída. Tudo bem. Então, se a data de expiração é menor do que o ponto de data/hora 10, que significa que temos estamos muito passado ou onde nenhum passado, qualquer que seja o tempo vai se sentar como exploração, então o token não é válido. Então eu vou dizer se o token não é válido ou o Tolkien não existe, e notar os sinais de exclamação. Então isso poderia ter sido facilmente é equivalente a falso, que é o que eu vou fazer para aumentar a legibilidade. Então, se qualquer um destes é falso, então queremos chamar um método que eu criei abaixo chamado sinusoids e redirecionar passando no contexto HTTP. Assim, os contextos HTTP vive. Desse middleware, não há problema, nós apenas passá-lo junto e então nós retornamos. Então isso significa que qualquer opção é dita aqui aponta a próxima opção. Nunca chegaremos a este caso se interceptarmos a esta altura. Nenhum outro que estou fazendo é se o atributo auth tem as regras. Então nós podemos realmente colocar em várias linhas, você pode ver vírgula administrador, esta vírgula que, de modo que muitas regras que você precisa verificar. Mas neste caso, eu só quero ter certeza de que se os atributos do autor, como vemos aqui, é limitado a apenas administradores e o usuário não está na função de administrador. Então eu quero redirecionar para home slash não autorizado. Então isso foi quando ele estava disposto ao acesso negado por padrão. Então, estamos apenas substituindo e vendo ir para nossa página personalizada. Por favor, redirecione e retorne. Então, se o token é válido, mas você não é um administrador tentando chegar a um caminho de administrador, vamos redirecionar para, e esse é o fim disso. Agora há situações em que podemos pegar uma exceção ao tentar passar por essa operação. Uma dessas situações seria com a API. Então, às vezes, pode haver algum problema de sincronização com o tempo, que significa que podemos considerar o Tolkien como não expirado e válido. Mas então, quando ele vai para a EPA, a EPA ainda lança uma exceção vendo 40 um ano não autorizado. Tudo bem, então nessa situação, o que vamos fazer é sair e redirecionar também tem uma situação semelhante ao middleware de exceção API, onde estamos vendo a exceção. Se for um tipo de exceção de API, execute essa ação. Caso contrário, basta redirecionar para a página de erro da barra inicial geral, redirecionar e quebrar. Então vamos olhar para o que acontece neste Seinfeld e redirecionar. Tudo o que estamos fazendo, estamos enviando todos fora do contexto http, assim como o que teríamos bilhões para, eu uso um serviço, o tempo dos logotipos. E, em seguida, vamos redirecionar você para o caminho para usuários de barra de login. Então parafusos da página de login e, em seguida, vá em frente e redirecione, então retornamos. Então isso é tudo o que acontece dentro dessas áreas. Tudo bem? E então, basicamente, isso sempre faz isso lá. Então, se tudo isso for ignorado, tudo isso é ignorado. Não há nenhum atributo, então vá em frente e circule o próximo pedido. Se pegarmos uma exceção, ou vamos para a página de erro ou estamos supondo que se é uma exceção API, Senado e redirecionamento, É claro, pode haver diferentes tipos de exceções EPA são cenários diferentes com eles. Assim, você pode facilmente ter outro método costal para ver se a exceção da API é do tipo. Esse tipo de resposta, em seguida, vá para esse tipo de fala porque esse objeto de exceção EPA realmente contém código de resposta. Então, podemos obter o código de status em vez disso. Lá vamos nós, podemos obter o código de status que está sendo enviado de volta. Então, se for 40, 1, então redirecionamento seno Alton. Se for talvez 500, então faça isso. Portanto, lembre-se de que tínhamos configurado nossos diferentes tipos de códigos de resposta na API. Então sabemos que podemos obter pedidos de manteiga, podemos obter validação, podemos não ter telefone, certo? Assim, com base no tipo de código de status que estamos esperando da API, ele vai voltar na exceção e, em seguida, podemos lidar com isso. Então essa é uma maneira rápida e suja de lidar com o que acontece quando os Tolkien expiram ou se temos diferentes exceções que não somos capazes de lidar. E como você vê mais exceções, é claro, você pode colocar mais recursos de manuseio no middleware. - Não. Apenas rápido em casa. Alguns redirecionando para ou é que eu estou redirecionando para um acesso negado ou não autorizado discurso. Não é nada de fundos que é criado no controlador doméstico e nova ação não é autorizada. E eu só tenho uma página que literalmente apenas diz que o texto não está autorizado. Isso é tudo o que está acontecendo. Há jumbotron não autorizar, então você pode enlouquecer com sua criatividade. Encontre um bom PCC personalizado. Você não deve transmitir a saída líquida. Isso é tudo o que realmente está acontecendo. Então vamos testar isso. Eu só vou tentar navegar para uma página que eu sei que eu não posso obter muito enquanto eu não estou logado. E então você vê não autorizado. Tudo bem. Neste ponto, nós provavelmente poderíamos ver se há uma tentativa Ambrose para uma página onde há tag não autorizada e o usuário não é mau, autenticado, e então redirecionado para a página de login, certo? Isso faria mais sentido se eu estivesse logado como usuário. E uma vez que eu tenho, eu estou apenas dando idéias para segurar, para controlar o seu aplicativo cresce se eu tentar fazer login como um usuário regular. E então eu mais uma vez tentando chegar à página de administração, eu não estou autorizado. No entanto, posso navegar para uma página que estou autorizado a Bowl Tool e estou recebendo um erro. Então eu nem sequer testei este corretamente e ele está bem na sua frente e isso é bom. É bom ver que essas falhas causariam essa outra exceção. E é mais do que provável porque eu tenho a regra de autenticação sem o atributo autor com mais regras nele, certo? Então eu estou tentando chegar a um lugar que não tem linhas nos atributos de autenticação. E então por causa dessa falha é pegar a exceção. Então agora ele vai para a página de erro de barra inicial, que só vai dizer que houve um erro ao tentar concluir seu comando. Então é claro que é um arenque vermelho porque esse não é realmente o problema. Estou a tentar chegar àquela página. Está bem. Não estou autorizado. Isso parece um pouco melhor se eu tentasse chegar a um que os pedidos criam. Tudo bem, então aí está. Então, sempre que houver um sinalizador de autorização com mais linhas, isso vai lançar um erro. E isso é o que acontece porque os pedidos de licença são autorizados, mas não tem nenhuma regra de estipulação. Então vamos apenas refluxo para isso rapidamente. E essa foi uma boa área para obter porque inspirou um código muito melhor e muito mais funcional neste refator. Então eu me livrei de algumas das cordas mágicas e eu acho que contabilidade situação muito mais global no que diz respeito às regras, estipulações, certo? Inicialmente, era apenas se você não é administrador, então você não pode entrar. Mas, se você tiver várias funções e até mesmo usuários com várias funções, você quer ter certeza de que está contabilizando todas as situações, certo? Então, nesta situação eu disse que se as funções de ponto auth ou os atributos de autor papéis não é igual a nulo, há papéis na lista. Em seguida, vá em frente e obtenha a função do usuário. Certo, então estamos recebendo o papel do tipo de reivindicação. Claro que você não precisa colocar em uma declaração de uso para isso. E então obtemos esse valor. Então vejo se a lista de regras não contém essa regra. Tudo bem, então várias funções podem ser usadas para proteger endpoint. Um usuário pode ter várias funções. Se este usuário não tem nenhuma função e isso é apenas contabilizar para o nosso usuário com uma regra. Então deixe-me, deixe-me voltar atrás. Isso ocorre quando apenas uma função é atribuída a um usuário. Você pode precisar fazer um pouco mais acabado, talvez um para cada loop ou usar algum outro método para descobrir se alguma das regras dos usuários, em qualquer uma das regras e em vez dos atributos, mas certo, e todos nós obtemos o uma regra para o usuário e verifique se a lista de regras sobre adolescentes a função desse usuário. E se não, então eles não estão autorizados para esse pedido em particular. E é basicamente isso. Então você pode brincar com isso e você pode ver que esta variável cheia, mas se você não escrever a citação cuidadosamente o suficiente, ele poderia jogar fora do aplicativo e desistir uma pequena tela de um erro quando não há realmente nada errado ou quando a culpa é sua. Então você quer ter muito cuidado quando você tem 18 citação para o middleware. Mas é realmente muito poderoso. 40. Melhorar a auditoria de dados: Nesta lição, vamos estar olhando para melhorar a auditoria. Então, até agora nós implementamos alguma quantidade de auditoria em nossas mudanças salvar onde nós levamos cada entidade uma vez que ele está fora da entidade de domínio base, nós começamos a definir os dados Last Modified eo big criado automaticamente. Não temos que fazer isso toda vez que estamos criando esses objetos para serem salvos, certo? Então, o que vamos fazer é criar um segundo contexto de banco de dados que realmente assumirá essa auditoria porque o que não estamos fazendo agora é adicionar os nomes do usuário ou o nome do usuário para o criado pelo último modificado por. Então precisamos de uma maneira de obter o usuário completar a ação no banco de dados automaticamente. Então começamos essa atividade com um novo arquivo que estou chamando de contexto de banco de dados auditável. Agora é uma classe abstrata e herda do contexto DB. Ele tem um construtor que é muito semelhante à cena anterior em contexto de banco de dados de gerenciamento de licença, exceto que ele leva apenas contexto de banco , opções, opções, portanto, não é digitado ou está no outro, você teria visto tipos como ele realmente tem digitação para o contexto de banco de dados. Bem, não vamos fazer isso desta vez, estamos apenas tomando opções. Tudo bem, então temos a nossa própria implementação de um salvar mudanças. Portanto, esta não é uma tarefa assíncrona virtual pública de substituição. Retornando int salvar alterações. É preciso um parâmetro chamado string username, que eu estou assumindo como padrão para ser sistema, significa que se nenhum nome de usuário é fornecido, então sistema é o que vai entrar nessa coluna nome de usuário. Então você pode fazer isso, se quiser. Se você tem um padrão, caso contrário você pode apenas atender esse nulo. Então, mais uma vez, isso não é uma sobreposição. Então nós realmente temos o mesmo para cada loop que está passando pela entrada e as lesões de camionista mudança baseada em detecção para entidades de linha de base. Tudo bem. E então dizemos “vá em frente e defina a última data de modificação e a data de adição ou a data de criação a qualquer momento está sendo adicionado. Agora, eu antes de prosseguir, eu gostaria de filtrar ainda mais isso porque o instrutor de CI está transportando tudo se não for modificado, se for desanexado tudo, não precisamos dessas mudanças nas coisas vestimentas não sendo modificado ou adicionado. Então eu vou adicionar um filtro adicional a isso onde eu estou vendo obter essas entradas, analisá-los em entidade de domínio base. Mas onde seus estados, então q-dot estado é adicionado ou modificado. Portanto, só estamos interessados em colocar esses campos de auditoria em algo que está sendo atualizado ou criado. Então eu posso saber, digamos entrada ponto entidade última modificada por é igual ao nome de usuário que está sendo passado. Tudo bem, e então similaridade, eu posso ver que o CreatedBy é o nome de usuário que está sendo passado. Tudo bem, então tudo isso só para ter certeza de que temos o nome de usuário presente. Mas depois disso vamos ver o resultado var é igual a 08 base. Então BS mais uma vez é contexto DB. Então baseado em ponto salvar alterações assíncronas e, em seguida, retornamos esse resultado. Agora vamos analisar as alterações necessárias para os contextos DVI de gerenciamento de licença original. Primeiro, eu não preciso substituir, ver se muda aqui novamente,para ver se muda aqui novamente, eu possa remover isso completamente. Essa é uma ferramenta que eu sei que precisa herdar dos contextos de banco de dados auditáveis. Então é este contextos DVI é herdar do auditável, que é, em seguida, herdar de contextos DVI para o auditável está dando sua própria versão. Eu vou ver se as alterações antes que ele vai chamar a base Save Changes, que é cortesia de contextos DVI de qualquer maneira. Então, com tudo isso feito, agora podemos modificar nossas unidades de trabalho. Porque lembre-se, saiba que implementamos que temos nosso C de mudanças acontecendo aqui mesmo. E isso é chamado no contexto. Com isso injetado, eu posso ir para a minha função salvar e eu posso ver nome de usuário é igual aos contextos HTTP contextos acessor HTTP, o usuário encontrar o primeiro nome para o ID do usuário, porque lembre-se que é onde estamos armazenando o ID do usuário. Então bem, sim, então eu estou apenas usando os tipos de reivindicação personalizados ponto UID. Outra razão que queremos evitar muito CNS extrema e conveniente e limpo que parece, e estamos recebendo esse valor para que possamos passar esse nome de usuário para este método, que iria então saltar para aqui, inicializa coisas de auditoria e, em seguida, salvar o mudanças reais no contexto do banco de dados e retornar os resultados se precisarmos dele. Então é assim que você pode melhorar a auditoria. Assim, com este contexto de banco de dados auditável sentado entre a unidade de trabalho e os contextos DVI reais. Há poucas coisas que você pode fazer aqui. Algumas pessoas realmente teriam como um banco de dados de auditoria real ou uma tabela de auditoria ou um conjunto de tabelas. Eles querem registrar cada axônio que está sendo realizado contra essas entidades, não apenas sentando esses campos, mas talvez replicá-los para outro lugar. Tudo isso poderia acontecer aqui. Eu não vou dizer que tudo isso poderia causar algumas limitações. Mas eu vi onde as pessoas realmente fazem auditorias completas entre este, este pedaço de código e este pedaço de código, certo? Então unidade, assim para estende-se sobre tudo. E então para cada entidade que está lá esperando para ser salva, nós os manipulamos. E depois salvamos eles. 41. Conclusão: Eu quero dizer obrigado caras por estender-se até o final deste curso comigo, onde nós não tínhamos necessariamente um sistema de gerenciamento de licença de EHR totalmente funcional no final do curso. Mas analisamos algumas técnicas avançadas. Sei que pode tirar e aplicar nas suas rotinas diárias. Durante a duração deste curso, escrevemos código que era modulo testável, sustentável e reutilizável, e fomos sensíveis aos princípios arquitetônicos sólidos. Nós implementamos o mar QRS e mídia para padrões. Analisámos as melhores práticas para a separação de preocupações. Implementamos uma API. Nós olhamos para como protegê-lo com autenticação JWT e segurar para consumir isso e usar isso para nossa vantagem em um aplicativo cliente, temos feito tanto juntos e eu sou muito mais uma vez grato por sua dedicação e seu apoio e você tem alguma sugestão. Sinta-se livre para deixá-los na caixa de sugestões. E estou sempre aberta a comentários. Obrigado mais uma vez e tenha um ótimo.