Ir para o conteúdo do rodapé
Iron Academy Logo
Aprenda C#
Aprenda C#

Outras categorias

Validação de Dados em .NET 10 APIs Mínimas

[[academy-video-youtube({"vid": "sW_AcN-nD0Y", "start_time": "0", "title": "Validação de Dados em APIs Minimalistas do .NET 10", "creator": "Tim Corey", "length": "~10m"})]]

APIs minimalistas sempre foram a alternativa enxuta ao ASP.NET Core baseado em controlador, mas por muito tempo tiveram uma lacuna notável: sem suporte embutido para validar dados recebidos. Você conectava verificações manuais em cada manipulador ou dependia de bibliotecas de terceiros. .NET 10 fecha essa lacuna com validação de anotação de dados de primeira classe para strings de consulta, cabeçalhos e corpos de solicitações, tudo isso sem pacotes extras.

Esta imersão profunda em APIs Minimalistas do .NET 10, com base na explicação de Tim Corey, explica como registrar o serviço de validação, anotar classes de modelo e evitar armadilhas comuns de modificadores de acesso que podem quebrar sua configuração.

A Configuração: Uma API Minimalista Simples

[0:44 - 1:35] A demonstração começa com um projeto de API Minimalista do ASP.NET Core bem enxuto rodando em .NET 10. A área de superfície é intencionalmente pequena: dois endpoints POST, cada um aceitando um modelo diferente.

app.MapPost("/person", (Person person) => Results.Ok(person));
app.MapPost("/login", (LoginModel login) => Results.Ok(login));
app.MapPost("/person", (Person person) => Results.Ok(person));
app.MapPost("/login", (LoginModel login) => Results.Ok(login));

O modelo Person possui campos de identidade básicos. LoginModel lida com credenciais: um endereço de e-mail, uma senha e um campo de confirmação de senha. Ambos são enviados como corpos JSON. Nesse ponto, não há nenhuma verificação de entrada; a API aceita qualquer coisa que recebe, incluindo strings vazias e endereços de e-mail malformados.

Scalar (a moderna UI OpenAPI que acompanha o .NET 10) é usada para enviar solicitações de teste diretamente do navegador, facilitando ver exatamente o que a API retorna antes e depois da validação.

Registrando o Serviço de Validação

[2:36 - 3:06] Antes que qualquer atributo de validação tenha efeito, você precisa optar pelo nível de serviço. Uma única chamada no bloco de registro de serviço habilita a imposição em todos os endpoints da API Minimalista:

builder.Services.AddValidation();
builder.Services.AddValidation();

Essa linha é todo o passo de configuração. Não há middleware para adicionar, nenhum estágio de pipeline para conectar. O framework assume automaticamente assim que o serviço é registrado. Se você pular essa chamada, seus atributos de anotação de dados estarão presentes no modelo, mas nunca avaliados, e as solicitações passam independentemente do que contêm.

Vale a pena lembrar como um primeiro passo de depuração: se a validação não faz nada silenciosamente, AddValidation() geralmente é a peça que falta.

Adicionando Validação a um Modelo de Classe

[3:00 - 3:55] Com o serviço registrado, adicionar validação a um modelo baseado em classe é uma questão de decorar propriedades com atributos de anotação de dados:

public class Person
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }
}
public class Person
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }
}

Após adicionar a diretiva de uso System.ComponentModel.DataAnnotations no início do arquivo, marcar FirstName e LastName como [Required] garante que eles sejam validados. Enviar uma solicitação POST com um corpo vazio através do Scalar agora retorna um 400 Bad Request com uma resposta de erro estruturada:

{
  "errors": {
    "FirstName": ["The FirstName field is required."],
    "LastName": ["The LastName field is required."]
  }
}

Sem tratamento de erro personalizado, sem atributos de filtro. O framework produz essa resposta automaticamente, e a verificação é executada antes que o corpo do seu manipulador seja executado, então você nunca precisa se proteger contra nulos dentro da lógica do endpoint.

Aplicando Validação a um Registro

[4:29 - 5:30] Os mesmos atributos funcionam em registros C#, mas a sintaxe difere ligeiramente porque as propriedades de registro são normalmente definidas no construtor primário em vez de como declarações de membros separadas.

public record LoginModel(
    [Required] [EmailAddress] string Email,
    [Required] string Password,
    [Required] string ConfirmPassword
);
public record LoginModel(
    [Required] [EmailAddress] string Email,
    [Required] string Password,
    [Required] string ConfirmPassword
);

Atributos em parâmetros de construtor são aplicados às propriedades geradas, portanto, [Required] e [EmailAddress] se comportam exatamente como fariam em uma classe. Enviar uma solicitação com um e-mail malformado, digamos "notanemail", agora retorna um 400 que identifica o campo Email como inválido.

O atributo [Compare] também pode ser usado para assegurar que ConfirmPassword coincide com Password. Em um registro, os alvos de atributo precisam de um empurrão explícito porque o compilador deve saber que você quer dizer o membro gerado, não o próprio parâmetro do construtor.

[property: Compare(nameof(Password))]
string ConfirmPassword
[property: Compare(nameof(Password))]
string ConfirmPassword

O alvo [property:] informa ao compilador para anexar o atributo ao membro gerado em vez do parâmetro. Sem ele, [Compare] compila mas nunca é executado durante a verificação. Esta é a parte mais complicada de trabalhar com registros vs classes neste contexto: as propriedades de classe aceitam atributos naturalmente, enquanto os parâmetros de registro precisam do alvo explícito para qualquer coisa que opere no nível de membro.

A Requisito do Modificador de Acesso Público

[7:51 - 9:00] Uma armadilha comum é fácil de perder e não produz mensagem de erro quando você a encontra. O sistema de validação usa reflexão para inspecionar seus tipos de modelo em tempo de execução; para que a reflexão encontre os membros de um tipo, o próprio tipo deve ser marcado com public.

// Validation will NOT run; the class is internal by default
class Person { ... }

// Validation runs correctly
public class Person { ... }
// Validation will NOT run; the class is internal by default
class Person { ... }

// Validation runs correctly
public class Person { ... }

A mesma regra se aplica a registros. Se seu modelo for declarado sem um modificador de acesso, C# padroniza para internal, e o serviço o ignora completamente. Seu endpoint ainda recebe a solicitação, o manipulador ainda executa, e nenhum erro é retornado; as checagens simplesmente não fazem nada em silêncio.

Este é um comportamento do ASP.NET Core, não específico de APIs Mínimas, mas aparece com mais frequência aqui porque esses projetos tendem a ser compactos e os desenvolvedores às vezes definem modelos inline ou no mesmo arquivo que Program.cs sem pensar em visibilidade.

Uma maneira rápida de auditar seu projeto: qualquer tipo de modelo passado para um manipulador de endpoint deve ser explicitamente marcado com public. Se não for, nenhum número de atributos fará o framework disparar.

O Que Você Pode Validar

Os atributos de anotação de dados embutidos cobrem os cenários mais comuns sem qualquer trabalho extra:

  • [Required] rejeita valores nulos ou vazios
  • [EmailAddress] valida o formato de uma string de e-mail
  • [Compare] verifica se duas propriedades coincidem, útil para confirmação de senha
  • [Range] aplica limites numéricos ou de data
  • [StringLength] limita o comprimento da string com um mínimo opcional
  • [RegularExpression] valida contra um padrão personalizado

Todos estes funcionam em parâmetros de string de consulta, cabeçalhos de solicitação e corpos JSON. A mesma classe de modelo ou registro pode ser vinculada a partir de diferentes fontes sem alterar nenhum de seus atributos.

Conclusão

[7:46 - fim] Com AddValidation() registrado e seus modelos decorados, as APIs Mínimas aplicam automaticamente restrições de entrada tanto em classes quanto em registros. Para que isso funcione no .NET 10, basta chamar builder.Services.AddValidation() uma vez, decorar as propriedades do seu modelo com atributos de anotação de dados padrão e garantir que cada tipo de modelo seja marcado com public.

O alvo [property:] em registros e a exigência do modificador public são as únicas verdadeiras armadilhas. Eles são fáceis de esquecer e produzem falhas silenciosas em vez de erros de compilação, então mantenha-os em sua lista de verificação sempre que as verificações de entrada parecerem não fazer nada.

Assista ao vídeo completo no canal do Tim Corey no YouTube para a explicação completa do código-fonte.

Hero Worlddot related to Validação de Dados em .NET 10 APIs Mínimas
Hero Affiliate related to Validação de Dados em .NET 10 APIs Mínimas

Ganhe mais compartilhando o que você ama.

Você cria conteúdo para desenvolvedores que trabalham com .NET, C#, Java, Python ou Node.js? Transforme sua expertise em renda extra!

Equipe de Suporte Iron

Estamos online 24 horas por dia, 5 dias por semana.
Bater papo
E-mail
Liga para mim