Camada de Apresentação (API)

Criação do Projeto API

Um projeto web vazio é criado para servir como camada de apresentação na Arquitetura Limpa:

dotnet new web -o CleanArchitectureStore.Api
dotnet sln add .\CleanArchitectureStore.Api\

O projeto CleanArchitectureStore.Api representa a camada mais externa do sistema, responsável por expor a funcionalidade através de endpoints HTTP e gerenciar a comunicação com clientes externos.

Configuração de Dependências do Projeto

Referências aos Projetos Internos

Todas as camadas internas são referenciadas pela API:

dotnet add reference ..\CleanArchitectureStore.Application\
dotnet add reference ..\CleanArchitectureStore.Domain\
dotnet add reference ..\CleanArchitectureStore.Infrastructure\

Análise da hierarquia de dependência:

  • API → Application → Domain: Direção correta na Clean Architecture

  • API → Infrastructure: Necessário para configuração de serviços concretos

  • Domain ← Application ← Infrastructure: O domínio permanece independente

Pacote MediatR

O pacote MediatR é adicionado para suporte ao padrão mediator na camada de apresentação:

Observação: Embora o MediatR já esteja configurado na camada de aplicação, sua instalação na API é necessária para:

  1. Resolução de tipos ISender e IMediator nos endpoints

  2. Configuração do pipeline HTTP para injeção automática

  3. Suporte a behaviors específicos da camada web

Configuração de Banco de Dados

String de Conexão no appsettings.json

A configuração de conexão é definida com parâmetros explícitos:

Parâmetros importantes da connection string:

  • Server=127.0.0.1,1433: Endereço IP explícito evita problemas de resolução DNS

  • Encrypt=True: Habilita criptografia TLS para a conexão

  • TrustServerCertificate=True: Aceita certificados autoassinados (comum em desenvolvimento)

  • User ID=sa: Utiliza a conta de sistema do SQL Server

  • Password=...: Senha forte conforme políticas de segurança

Verificação e Inicialização do Container Docker

O container do SQL Server é verificado e iniciado conforme necessário:

Status esperado do container:

O container deve estar expondo a porta 1433, permitindo conexões externas.

Configuração do Program.cs

Configuração de Serviços

A configuração inicial do Program.cs estabelece todas as dependências necessárias:

Análise detalhada da configuração:

  1. AddDbContext<AppDbContext>:

    • Configura o contexto de dados com SQL Server

    • b.MigrationsAssembly("CleanArchitectureStore.Api") especifica que as migrações serão geradas no projeto da API

    • Esta configuração é necessária porque as migrações exigem um projeto executável para geração

  2. AddApplication():

    • Método de extensão definido em CleanArchitectureStore.Application.DependencyInjection

    • Registra todos os handlers do MediatR e serviços da camada de aplicação

  3. AddInfrastructure():

    • Método de extensão definido em CleanArchitectureStore.Infrastructure.DependencyInjection

    • Registra implementações concretas de repositórios e outros serviços de infraestrutura

Configuração de Migrações

A especificação b.MigrationsAssembly("CleanArchitectureStore.Api") é crítica porque:

  1. Separação de Responsabilidades: A infraestrutura define o modelo, mas a API executa as migrações

  2. Dependência de Projeto Executável: O comando dotnet ef requer um projeto executável

  3. Flexibilidade de Deploy: Diferentes apresentações (Web, Console, etc.) podem gerenciar migrações independentemente

Implementação de Endpoints com MediatR

Endpoint para Obtenção de Produto por ID

Um endpoint minimal API é implementado para demonstrar a integração com MediatR:

Análise passo a passo do endpoint:

  1. Parâmetros do Endpoint:

    • ISender sender: Injetado automaticamente pelo ASP.NET Core, representa o mediador para envio de commands

    • Guid id: Extraído da rota {id} através de model binding

    • CancellationToken cancellationToken: Token para cancelamento cooperativo de operações assíncronas

  2. Criação do Command:

    • new CleanArchitectureStore.Application.UseCases.Products.GetById.Command(id)

    • Utiliza o nome completo (fully qualified name) para evitar conflitos de namespace

    • O comando encapsula todos os dados necessários para o caso de uso

  3. Envio através do MediatR:

    • await sender.Send(command, cancellationToken)

    • O MediatR roteia automaticamente o comando para o handler apropriado

    • O handler processa a lógica e retorna um Result<Response>

  4. Transformação da Resposta:

    • result.IsSuccess: Verifica se a operação foi bem-sucedida

    • Results.Ok(result.Value): Retorna HTTP 200 com o valor em caso de sucesso

    • Results.BadRequest(result.Error): Retorna HTTP 400 com detalhes do erro em caso de falha

Vantagens da Abordagem com MediatR

  1. Desacoplamento Total: O endpoint não conhece o handler específico

  2. Testabilidade: O ISender pode ser simulado em testes de integração

  3. Pipeline Behaviors: Middleware para cross-cutting concerns (validação, logging, etc.)

  4. Flexibilidade: O mesmo comando pode ser consumido por diferentes apresentações

Preparação do Banco de Dados

Limpeza e Reconstrução

Antes da primeira execução, é recomendada uma limpeza completa:

Finalidade de cada comando:

  1. DROP DATABASE: Remove completamente o banco existente para início limpo

  2. dotnet clean: Limpa artefatos de compilação anteriores

  3. dotnet build: Recompila todos os projetos da solução

  4. Microsoft.EntityFrameworkCore.Design: Pacote necessário para comandos dotnet ef

  5. dotnet ef migrations add v1: Gera scripts de migração baseados no modelo atual

  6. dotnet ef database update: Aplica as migrações ao banco de dados

Inserção de Dados de Teste

Após a criação do banco, dados de exemplo são inseridos:

Verificação dos dados inseridos:

Execução e Teste da Aplicação

Inicialização do Serviço

A aplicação é iniciada na porta 5202:

Teste com Postman

Requisição:

Resposta (200 OK):

Fluxo Completo da Requisição

  1. Recepção HTTP: Endpoint minimal API recebe requisição GET

  2. Model Binding: Guid é extraído da rota e CancellationToken é capturado

  3. Criação do Command: Dados da requisição são encapsulados em um objeto Command

  4. Mediação: ISender roteia o Command para o Handler apropriado

  5. Processamento: Handler consulta repositório e aplica lógica de negócio

  6. Result Pattern: Operação retorna Result<Response> indicando sucesso/falha

  7. Transformação HTTP: Result é convertido em resposta HTTP apropriada

  8. Serialização JSON: Objeto Response é serializado para o cliente

Arquitetura Final Implementada

Diagrama de Camadas

Princípios da Clean Architecture Aplicados

  1. Independência de Frameworks: O domínio não referencia Entity Framework ou ASP.NET Core

  2. Testabilidade: Cada camada pode ser testada isoladamente

  3. Independência de UI: A lógica de negócio não depende da interface web

  4. Independência de Banco de Dados: O domínio não conhece detalhes de persistência

  5. Independência de Agentes Externos: A lógica de negócio não conhece APIs externas

Próximas Melhorias Possíveis

Validação de Commands

Pipeline Behaviors para Logging

Tratamento Global de Exceções

Esta implementação completa demonstra a integração bem-sucedida de todas as camadas da Clean Architecture, desde o domínio independente até a API exposta, com separação clara de responsabilidades e manutenção dos princípios fundamentais da arquitetura.

Atualizado