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

Outras categorias

Adicionando um Endpoint de Inserção POST com Validação em .NET Aspire no Linux

[[academy-video-youtube({"vid": "oAMMHR8kKnw", "start_time": "0", "title": "Adding a POST Insert Endpoint with Validation in .NET Aspire on Linux", "creator": "Tim Corey", "length": "20m 31s"})]]

Ler dados de uma API é apenas metade da história. Eventualmente, todo aplicativo precisa aceitar novos registros, e isso significa construir um endpoint POST que recebe um corpo de solicitação, valida a entrada, persiste no banco de dados e retorna um código de status significativo. Pular a etapa de validação é tentador durante a prototipação, mas APIs de produção que aceitam entrada não validada tornam-se uma fonte de dados corrompidos que é mais difícil de limpar do que de prevenir.

No vídeo "Adicionando um Endpoint POST Insert com Validação em .NET Aspire no Linux", Tim Corey adiciona um endpoint de inserção à API do Tiny Ticket, cria um tipo de registro de entrada dedicado, conecta o pipeline de validação embutido do .NET para APIs mínimas e configura o Swagger para iniciar automaticamente quando a API começa. O episódio cobre o ciclo completo desde o procedimento armazenado até o endpoint testado, incluindo o formato de resposta de erro de validação que .NET retorna nativamente. Se você está seguindo a série C# no Linux ou adicionando operações de gravação a uma API mínima pela primeira vez, este artigo aborda cada etapa.

Criando o Tipo de Registro de Inserção

[1:46 - 4:43] Antes de construir o endpoint, Tim cria um objeto de transferência de dados que representa a forma de uma solicitação de inserção. O existente TicketModel inclui campos como Id e CreatedDate que o banco de dados gera automaticamente. Aceitar esses em um corpo POST seria ignorado ou causaria conflitos, então um tipo separado limita a entrada apenas aos campos que o chamador deve fornecer.

public record TicketInsertRecord(string Title, string Description, int Priority);
public record TicketInsertRecord(string Title, string Description, int Priority);

Usar um record em vez de um class é uma escolha deliberada. Registros oferecem igualdade baseada em valor e imutabilidade por padrão, o que se adapta à semântica de um payload de solicitação: os dados chegam, são validados, são passados para o banco de dados, e nunca são modificados no meio do processo. As três propriedades (Title, Description, Priority) mapeiam diretamente para os parâmetros do procedimento armazenado spTickets_Insert.

Mapeando o Endpoint POST

[4:43 - 9:51] Com o tipo de registro definido, o registro do endpoint segue o mesmo padrão das rotas GET, mas usa MapPost e vincula o corpo da solicitação ao registro de inserção:

app.MapPost("/api/tickets", async (TicketInsertRecord ticket, IDbConnection db) =>
{
    await db.SaveDataAsync("spTickets_Insert", ticket);
    return Results.NoContent();
});
app.MapPost("/api/tickets", async (TicketInsertRecord ticket, IDbConnection db) =>
{
    await db.SaveDataAsync("spTickets_Insert", ticket);
    return Results.NoContent();
});

Observe que a rota é /api/tickets sem um segmento de ID, correspondendo às convenções do REST onde POST para uma URL de coleção cria um novo recurso. O manipulador chama o procedimento armazenado com o objeto inteiro ticket como o conjunto de parâmetros. Dapper mapeia as propriedades do registro para os parâmetros SQL por nome.

Retornar Results.NoContent() envia um código de status 204. Tim explica o raciocínio: a inserção foi bem-sucedida, mas não há nada significativo para retornar no corpo da resposta. Algumas APIs retornam o objeto recém-criado com um status 201 Created e um cabeçalho Location apontando para o novo recurso, que é uma alternativa válida. Para o projeto Tiny Ticket, 204 mantém as coisas simples.

Testando a Inserção pelo Swagger

[9:51 - 14:43] Tim launches the project and navigates to Swagger. O endpoint POST aparece com um esquema de corpo de solicitação correspondendo às propriedades TicketInsertRecord. Ele preenche um ticket de teste com um título, descrição e prioridade e então executa a solicitação.

Um 204 retorna, confirmando que a inserção foi bem-sucedida. Para verificar se os dados realmente persistiram, ele alterna para o endpoint GET all e executa-o. O novo ticket aparece na lista ao lado dos registros de teste originais.

O que o teste também revela é a lacuna sem validação: enviar um título vazio, uma descrição ausente ou uma prioridade de 99 todos têm sucesso com um 204. O banco de dados aceita o que quer que a API envie. Essa lacuna motiva a próxima seção.

Adicionando Validação Embutida

[14:43 - 18:28] Começando com .NET 10, APIs mínimas suportam um pipeline de validação embutido que lê atributos de anotação de dados do tipo de entrada e rejeita solicitações inválidas antes que o manipulador execute. Tim conecta-a em duas etapas.

Primeiro, registre os serviços de validação em Program.cs. Essa única linha ativa o pipeline completo:

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

Com o serviço registrado, o framework inspeciona cada corpo de solicitação quanto a atributos de validação antes que o manipulador execute. A segunda etapa é anotar o registro de inserção com as regras que cada campo deve satisfazer:

public record TicketInsertRecord(
    [Required, MinLength(1)] string Title,
    [Required] string Description,
    [Range(1, 5)] int Priority
);
public record TicketInsertRecord(
    [Required, MinLength(1)] string Title,
    [Required] string Description,
    [Range(1, 5)] int Priority
);

[Required] garante que o campo esteja presente e não seja nulo. [MinLength(1)] impede que strings vazias passem a verificação de obrigatoriedade (já que uma string vazia tecnicamente não é nula). [Range(1, 5)] restringe a prioridade a um nível válido. Esses atributos são os mesmos tipos System.ComponentModel.DataAnnotations que controladores ASP.NET MVC usaram por anos, mas agora funcionam em APIs mínimas sem middleware adicional.

Após salvar e reiniciar, Tim envia uma solicitação com um título vazio e uma prioridade de 10. A resposta retorna um 400 Bad Request com um corpo de erro estruturado:

{
    "errors": {
        "Title": ["The Title field is required."],
        "Priority": ["The field Priority must be between 1 and 5."]
    }
}

O pipeline de validação interrompe a solicitação antes que o manipulador execute, então nenhum dado inválido atinge o banco de dados. A resposta de erro segue o formato RFC 7807 Problem Details, que os consumidores de API podem analisar programaticamente.

Auto-Lançamento do Swagger na Inicialização

[19:44 - 20:31] Uma pequena melhoria de qualidade de vida fecha o episódio. Toda vez que Tim iniciava a API, ele tinha que digitar manualmente /swagger na URL do navegador. Para automatizar isso, ele abre o Properties/launchSettings.json do projeto da API e adiciona uma propriedade launchUrl ao perfil HTTPS:

{
    "profiles": {
        "https": {
            "launchUrl": "swagger"
        }
    }
}

Na próxima inicialização, o navegador abre diretamente para a Swagger UI em vez da página padrão. Isso economiza alguns segundos por ciclo de depuração, o que se acumula ao longo de uma sessão completa de desenvolvimento.

Conclusão

[20:09 - 20:31] Adicionar um endpoint POST a uma API mínima envolve criar um registro de entrada dedicado, mapeá-lo para MapPost com a URL da coleção, e chamar o procedimento armazenado com o registro como objeto de parâmetro. A validação no .NET 10 requer um registro de serviço e atributos de anotação de dados padrão nas propriedades do registro. O framework lida com o formato da resposta 400 automaticamente.

Navegação na série: Este artigo faz parte da série C# no Linux construindo o app Tiny Ticket. Anterior: Adicionando um Endpoint Get By ID. Próximo: Adicionando um Endpoint PUT Update.

Dica de exemplo: Quando seu procedimento armazenado de inserção retorna o ID do novo registro, mude o retorno de Results.NoContent() para Results.Created($"/api/tickets/{newId}", result) para dar aos chamadores um status 201 com um cabeçalho de localização que eles podem seguir para buscar o recurso criado.

Assista o vídeo completo no canal do YouTube dele e obtenha mais insights sobre como construir endpoints de gravação na série C# no Linux.

Hero Worlddot related to Adicionando um Endpoint de Inserção POST com Validação em .NET Aspire no Linux
Hero Affiliate related to Adicionando um Endpoint de Inserção POST com Validação em .NET Aspire no Linux

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