Pular para o conteúdo
.NETNegociação de conteúdo e formatters
Módulo 03Construindo a Web API

Negociação de conteúdo e formatters

intermediario 35 min de leitura·Atualizado · .NET 9
Resumo

Content negotiation permite que o cliente peça o formato da resposta pelo cabeçalho Accept (ex.: JSON ou XML). Configuramos os formatters e vemos como restringir tipos de mídia e criar um formatter customizado.

1. Objetivos de Aprendizagem#

  • Entender o que a API oferece "out of the box" na negociação de conteúdo.
  • Habilitar formatters adicionais (ex.: XML) e restringir media types.
  • Esboçar um output formatter customizado.

2. Pré-requisitos#

  • Endpoints GET retornando DTOs (Módulo 18).

3. Conceito#

Content negotiation é o processo pelo qual servidor e cliente concordam sobre o formato da resposta, usando o cabeçalho Accept da requisição. Por padrão, o ASP.NET Core responde em JSON (System.Text.Json). O porquê de suportar mais: interoperabilidade com clientes que exigem outros formatos.

Peças-chave:

  • RespectBrowserAcceptHeader — respeita o Accept do navegador.
  • ReturnHttpNotAcceptable — retorna 406 Not Acceptable se nenhum formatter atende.
  • Output formatters — convertem o objeto em bytes no formato pedido.

4. Mão na Massa#

4.1. Setup#

Para XML:

Shell
# incluso no framework; basta habilitar AddXmlDataContractSerializerFormatters()

4.2. Implementação Passo a Passo#

  1. Configure os formatters:
C#
builder.Services.AddControllers(config =>
{
    config.RespectBrowserAcceptHeader = true;
    config.ReturnHttpNotAcceptable = true;   // 406 quando o formato não é suportado
})
.AddXmlDataContractSerializerFormatters();   // habilita XML
  1. Teste pedindo XML:
Shell
curl -H "Accept: application/xml" http://localhost:5000/api/categorias
  1. Restringir media types em um controller/ação:
C#
[Produces("application/json")]
[HttpGet]
public IActionResult Get() => Ok();

4.3. Executando#

  • Accept: application/json → JSON.
  • Accept: application/xml → XML (se habilitado).
  • Accept: text/csv sem formatter e com ReturnHttpNotAcceptable=true406.

5. Exemplo Completo#

Esboço de um output formatter customizado (CSV):

C#
public class CsvOutputFormatter : TextOutputFormatter
{
    public CsvOutputFormatter()
    {
        SupportedMediaTypes.Add(new("text/csv"));
        SupportedEncodings.Add(System.Text.Encoding.UTF8);
    }

    protected override bool CanWriteType(Type? type) =>
        typeof(IEnumerable<CategoriaDto>).IsAssignableFrom(type) ||
        typeof(CategoriaDto).IsAssignableFrom(type);

    public override async Task WriteResponseBodyAsync(
        OutputFormatterWriteContext context, System.Text.Encoding encoding)
    {
        var buffer = new System.Text.StringBuilder();
        if (context.Object is IEnumerable<CategoriaDto> lista)
            foreach (var c in lista) buffer.AppendLine($"{c.Id},{c.Nome}");
        else if (context.Object is CategoriaDto c)
            buffer.AppendLine($"{c.Id},{c.Nome}");

        await context.HttpContext.Response.WriteAsync(buffer.ToString());
    }
}

Registro: config.OutputFormatters.Add(new CsvOutputFormatter());

6. Boas Práticas e Armadilhas#

FaçaEvite
Ativar ReturnHttpNotAcceptable para respostas HTTP corretasDevolver JSON silenciosamente quando o cliente pediu outro formato
Restringir media types com [Produces]/[Consumes]Aceitar qualquer formato sem controle
Só adicionar formatters que você realmente suportaPrometer formatos sem implementação
Atenção

o serializador XML (DataContractSerializer) não lida bem com records posicionais ou tipos sem construtor sem parâmetros. Ajuste os DTOs se for oferecer XML.

7. Segurança e Produção#

  • Formatters customizados que serializam objetos arbitrários podem vazar campos; controle o que é escrito explicitamente.

8. Exercícios#

  • Fácil: habilite XML e confirme o 406 para um formato não suportado.
  • Médio: aplique [Produces("application/json")] a um controller e observe o efeito na negociação.
  • Desafio: finalize o CsvOutputFormatter e teste com Accept: text/csv.

9. Resumo#

Content negotiation deixa o cliente escolher o formato via Accept. Configuramos formatters, retornamos 406 quando apropriado e esboçamos um formatter customizado.

10. Próximos Passos#

Módulo 22: propriedades de segurança e idempotência dos métodos HTTP.

11. Referências#

21-01 — Negociação de conteúdo e formatters | Curso ASP.NET Core