← ASP.NET Core: aplicações, contratos e operação
04 / 10 · 60 MIN

Respostas, erros e contratos de API

Relaciona o estado HTTP, a representação e os tipos de retorno com o resultado observado, incluindo erros anteriores ao handler.

O corpo não substitui o estado

Uma string devolvida diretamente por um Minimal API é escrita como texto, com text/plain no comportamento predefinido. Um objeto comum é serializado como JSON. Nenhuma destas escolhas deve ser confundida com a decisão de estado: TypedResults.Ok("404") continua a representar sucesso HTTP, embora o texto pareça um código de erro.

Se o contrato exige 404 para recurso ausente, usa um resultado que expresse esse estado. Um objeto { error = "missing" } dentro de Ok obriga o cliente a adivinhar uma convenção contraditória. Define primeiro o resultado da operação e depois o estado, os campos e a representação correspondentes.

Alternativas tipadas do handler

TypedResults devolve tipos concretos de resultados. Results<Ok<Item>, NotFound> declara duas alternativas e conserva metadata útil para descrever a resposta. O handler pode devolver Ok<Item> ou NotFound; acrescentar BadRequest nesse corpo exige rever o tipo de retorno para incluir essa alternativa.

Esta é uma restrição sobre os retornos da função. Um pedido pode falhar em autenticação, routing ou binding antes de Find. Não interpretes a união como garantia de que a aplicação inteira só pode responder 200 ou 404. O contrato público deve considerar essas fronteiras e o middleware efetivamente configurado.

Descrever não executa a operação

O tipo concreto de TypedResults pode fornecer metadata de resposta automaticamente. Se um helper declarar apenas IResult, a assinatura perde parte dessa informação estática. Conservar o tipo concreto, declarar a união correta ou fornecer metadata explícita coerente são opções para recuperar uma descrição útil.

Essa metadata não grava dados, não verifica permissões e não transforma um ramo Ok num erro. Uma descrição que anuncia 404 enquanto o handler devolve 200 com error=missing precisa de correção no comportamento. As revisões devem comparar assinatura, ramos e descrição, sem usar a documentação como prova de efeitos que o código não executa.

Compor Problem Details

AddProblemDetails regista o serviço de representação de erros. Middleware de exceções e de páginas de estado liga situações do pipeline a esse serviço. No exemplo, UseExceptionHandler trata exceções a jusante e UseStatusCodePages pode produzir uma representação para estados de erro sem corpo, quando a escrita é suportada.

O registo isolado não envolve automaticamente todos os handlers num catch. Também não promete reescrever um corpo já emitido. Para aceitar o contrato, identifica a origem do erro, a existência de corpo, o momento em que a resposta começa e o writer disponível. Só depois conclui qual representação pública pode ser produzida.

Detalhes públicos e diagnóstico

A Developer Exception Page é destinada ao ambiente de desenvolvimento. Pode incluir stack trace, parâmetros da query, cookies e cabeçalhos. Disponibilizá-la a visitantes em produção transforma detalhes de investigação em dados públicos, sem que isso seja necessário ao contrato do cliente.

Um erro público deve permitir interpretar a falha com campos delimitados. A investigação pode usar registos internos apropriados, com controlo do que é recolhido. Ocultar a stack mas copiar mensagens de SQL, cookies ou o pedido inteiro para detail não resolve essa fronteira. O formato Problem Details também não torna automaticamente seguro qualquer texto nele colocado.

Negociar também os erros

O writer predefinido de Problem Details suporta representações JSON e os tipos Accept compatíveis documentados. Um cliente que só aceita application/xml não ganha suporte XML por existir AddProblemDetails. Se TryWriteAsync devolver false, o ramo precisa de uma política explícita; não se deve documentar um corpo que não foi escrito.

As opções incluem acordar formatos suportados com o cliente, fornecer um writer adequado ou definir o fallback e a negociação pública. Repetir a mesma chamada não acrescenta suporte. A escolha deve preservar o estado da falha e ser coerente com o contrato, incluindo situações em que já não é possível alterar a resposta.

Ler o contrato completo

O catálogo do exemplo é deliberadamente fixo: só existe Item 42. Para /items/42, Find devolve Ok<Item>; para /items/7, NotFound. Com Accept compatível, o tratamento de estados pode preencher o erro sem corpo. Para /items/blue, o binding int falha antes de Find. Não existe base de dados nem uma alegação de pesquisa em produção.

Ao rever as alternativas de resposta, distingue o resultado do handler do resultado final do pipeline. Uma evidência de 400 anterior não invalida a união da função; mostra outra fronteira a documentar. As perguntas pedem interpretar esses ramos e escolher a correção do contrato, sem executar C# ou publicar uma API.

// Program.cs: ASP.NET Core 10.0 Web SDK, net10.0, ImplicitUsings enabled.
// Fixed teaching catalogue: item 42 exists; no database or external call.
using Microsoft.AspNetCore.Http.HttpResults;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
app.MapGet("/items/{id}", Find);
app.Run();

static Results<Ok<Item>, NotFound> Find(int id)
{
    if (id == 42)
        return TypedResults.Ok(new Item(42, "Training item"));
    return TypedResults.NotFound();
}
public sealed record Item(int Id, string Name);
NA PRÁTICA

Com Accept compatível com o writer, /items/42 devolve 200 com o Item do modelo. /items/7 devolve 404 e o middleware pode produzir Problem Details para o erro sem corpo. /items/blue falha o binding antes de Find. A união do handler não enumera esse 400.

Armadilhas comuns

Devolver Ok com texto 404; assumir que TypedResults comprova persistência; tratar a união de retornos como lista de todos os erros do pipeline; anunciar JSON de erro sem verificar o writer e a negociação.

Tópicos relacionados: Rotas, binding e validação · Âmbito de testes e evidência de integração · Saúde, observabilidade e diagnóstico

Leva esta ideia contigo

O estado e a representação devem refletir o resultado real. Tipos e metadata ajudam a descrever o handler; a composição do pipeline e a política de erros continuam a determinar outras respostas.

Criar conta

Referência: Plain string response · ASP.NET Core 10.0 / .NET 10 / C# 14