Formatar dados de resposta na API Web ASP.NET Core

O ASP.NET Core MVC dá suporte à formatação de dados de resposta, usando formatos especificados ou em resposta à solicitação de um cliente.

Resultados de ações específicas do formato

Alguns tipos de resultado de ação são específicos a um formato específico, como JsonResult e ContentResult. As ações podem retornar resultados que sempre usam um formato especificado, ignorando a solicitação de um cliente para um formato diferente. Por exemplo, retornar JsonResult, retorna dados formatados em JSON e retornar ContentResult, retorna dados de cadeia de caracteres de texto sem formação.

Não é necessário que uma ação retorne um tipo específico. O ASP.NET Core dá suporte a qualquer valor retornado de objeto. Os resultados de ações que retornam objetos que não são tipos IActionResult são serializados usando a implementação IOutputFormatter apropriada. Para obter mais informações, confira Tipos de retorno de ação do controlador na API web do AsP.NET Core.

Por padrão, o método auxiliar interno ControllerBase.Ok retorna dados formatados em JSON:

[HttpGet]
public IActionResult Get() =>
    Ok(_todoItemStore.GetList());

O código de exemplo retorna uma lista de itens pendentes. Usar as ferramentas de desenvolvimento do navegador F12 ou http-repl com o código anterior exibe:

  • O cabeçalho de resposta que contém content-type:application/json; charset=utf-8.
  • Os cabeçalhos de solicitação. Por exemplo, o cabeçalho Accept. O cabeçalho Accept é ignorado pelo código anterior.

Para retornar dados formatados como texto sem formatação, use ContentResult e o auxiliar Content:

[HttpGet("Version")]
public ContentResult GetVersion() =>
    Content("v1.0.0");

No código anterior, o Content-Type retornado é text/plain.

Para ações com vários tipos de retorno, retorne IActionResult. Por exemplo, ao retornar diferentes códigos de status HTTP com base no resultado da operação.

Negociação de conteúdo

A negociação de conteúdo ocorre quando o cliente especifica um cabeçalho Accept. O formato padrão usado pelo ASP.NET Core é JSON. A negociação de conteúdo é:

  • Implementada por ObjectResult.
  • Desenvolvida com base nos resultados de ação específica de código de status retornados dos métodos auxiliares. Os métodos auxiliares dos resultados da ação são baseados em ObjectResult.

Quando um tipo de modelo é retornado, o tipo de retorno é ObjectResult.

O seguinte método de ação usa os métodos auxiliares Ok e NotFound:

[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
    var todo = _todoItemStore.GetById(id);

    if (todo is null)
    {
        return NotFound();
    }

    return Ok(todo);
}

Por padrão, o ASP.NET Core dá suporte aos seguintes tipos de mídia:

  • application/json
  • text/json
  • text/plain

Ferramentas como o Fiddler ou o Postman podem definir o cabeçalho da solicitação Accept para especificar o formato de retorno. Quando o cabeçalho Accept contém um tipo compatível com o servidor, esse tipo é retornado. A próxima seção mostra como adicionar formatadores adicionais.

As ações do controlador podem retornar POCOs (Objetos CLR Antigos Simples). Quando um POCO é retornado, o runtime cria automaticamente um ObjectResult que encapsula o objeto. O cliente obtém o objeto serializado formatado. Se o objeto que está sendo retornado for null, uma resposta 204 No Content será retornada.

O exemplo a seguir retorna um tipo de objeto:

[HttpGet("{id:long}")]
public TodoItem? GetById(long id) =>
    _todoItemStore.GetById(id);

No código anterior, uma solicitação para um item todo válido retorna uma resposta 200 OK. Uma solicitação para um item todo inválido retorna uma resposta 204 No Content.

O cabeçalho Accept

A negociação de conteúdo ocorre quando um cabeçalho Accept é exibido na solicitação. Quando uma solicitação contém um cabeçalho de accept, o ASP.NET Core:

  • Enumera os tipos de mídia no cabeçalho accept na ordem de preferência.
  • Tenta encontrar um formatador que pode produzir uma resposta em um dos formatos especificados.

Se não for encontrado nenhum formatador que possa atender à solicitação do cliente, o ASP.NET Core:

  • Retornará 406 Not Acceptable se MvcOptions.ReturnHttpNotAcceptable estiver definido como true, ou -
  • Tenta localizar o primeiro formatador que pode produzir uma resposta.

Se nenhum formatador estiver configurado para o formato solicitado, o primeiro formatador que pode formatar o objeto será usado. Se nenhum cabeçalho Accept for exibido na solicitação:

  • O primeiro formatador que pode manipular o objeto é usado para serializar a resposta.
  • Não há nenhuma negociação acontecendo. O servidor está determinando qual formato retornar.

Se o cabeçalho Accept contiver */*, o Cabeçalho é ignorado, a menos que RespectBrowserAcceptHeader seja definido como verdadeiro em MvcOptions.

Navegadores e negociação de conteúdo

Ao contrário dos clientes de API típicos, os navegadores da Web fornecem cabeçalhos Accept. Os navegadores da Web especificam muitos formatos, incluindo curingas. Por padrão, quando a estrutura detecta que a solicitação vem de um navegador:

  • O cabeçalho Accept é ignorado.
  • O conteúdo é retornado em JSON, a menos que configurado de outra forma.

Essa abordagem fornece uma experiência mais consistente entre navegadores ao consumir APIs.

Para configurar um aplicativo para respeitar os cabeçalhos de aceitação do navegador, defina a propriedade RespectBrowserAcceptHeader como true:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.RespectBrowserAcceptHeader = true;
});

Configurar os formatadores

Os aplicativos que precisam dar suporte a formatos extras podem adicionar os pacotes NuGet apropriados e configurar o suporte. Há formatadores separados para entrada e saída. Formatadores de entrada são usados pelo Model Binding. Formatadores de saída são usados para formatar respostas. Para obter informações sobre como criar um formatador personalizado, confira Formatadores personalizados.

Adicionar suporte ao formato XML

Para configurar formatadores XML implementados usando XmlSerializer, chame AddXmlSerializerFormatters:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddXmlSerializerFormatters();

Ao usar o código anterior, os métodos de controlador retornam o formato apropriado com base no cabeçalho Accept da solicitação.

Configurar formatadores baseados em System.Text.Json

Para configurar recursos para os formatadores baseados em System.Text.Json, use Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. O código destacado a seguir configura a formatação PascalCase em vez da formatação camelCase padrão:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

O seguinte método de ação chama ControllerBase.Problem para criar uma resposta ProblemDetails:

[HttpGet("Error")]
public IActionResult GetError() =>
    Problem("Something went wrong.");

Uma resposta ProblemDetails é sempre camelCase, mesmo quando o aplicativo define o formato como PascalCase. ProblemDetails segue o RFC 7807, que especifica letras minúsculas.

Para configurar opções de serialização de saída para ações específicas, use JsonResult. Por exemplo:

[HttpGet]
public IActionResult Get() =>
    new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerOptions
        {
            PropertyNamingPolicy = null
        });

Adicionar suporte ao formato Newtonsoft.JsonON baseado em JS

Os formatadores JSON padrão usam System.Text.Json. Para usar os formatadores baseados em Newtonsoft.Json, instale o pacote NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson e configure-o em Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddNewtonsoftJson();

No código anterior, a chamada para AddNewtonsoftJson configura os seguintes recursos de API Web, MVC e Razor Pages para usar Newtonsoft.Json:

Alguns recursos podem não funcionar bem com formatadores baseados em System.Text.Json e exigem uma referência aos formatadores baseados em Newtonsoft.Json. Continue usando os formatadores baseados em Newtonsoft.Json quando o aplicativo:

  • Usa atributos Newtonsoft.Json. Por exemplo, [JsonProperty] ou [JsonIgnore].
  • Personaliza as configurações de serialização.
  • Depende dos recursos que o Newtonsoft.Json oferece.

Para configurar recursos para os formatadores baseados em Newtonsoft.Json, use SerializerSettings:

builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
    });

Para configurar opções de serialização de saída para ações específicas, use JsonResult. Por exemplo:

[HttpGet]
public IActionResult GetNewtonsoftJson() =>
    new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerSettings
        {
            ContractResolver = new DefaultContractResolver()
        });

Especificar um formato

Para restringir os formatos de resposta, aplique o filtro [Produces]. Assim como a maioria dos filtros, [Produces] pode ser aplicado na ação, controlador ou escopo global:

[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase

O filtro [Produces] anterior:

  • Força todas as ações dentro do controlador a retornar respostas formatadas em JSON para POCOs (Objetos CLR Antigos Simples) ou ObjectResult e seus tipos derivados.
  • Retornar respostas formatadas em JSON mesmo se outros formatadores estiverem configurados e o cliente especificar um formato diferente.

Para obter mais informações, veja Filtros.

Formatadores de letras maiúsculas e minúsculas especiais

Alguns casos especiais são implementados com formatadores internos. Por padrão, os tipos de retorno string são formatados como text/plain (text/html, se solicitado por meio do cabeçalho Accept). Esse comportamento pode ser excluído com a remoção do StringOutputFormatter. Os formatadores são removidos em Program.cs. Ações que têm um tipo de retorno de objeto de modelo retornarão 204 No Content ao retornar null. Esse comportamento pode ser excluído com a remoção do HttpNoContentOutputFormatter. O código a seguir remove o StringOutputFormatter e o HttpNoContentOutputFormatter.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    // using Microsoft.AspNetCore.Mvc.Formatters;
    options.OutputFormatters.RemoveType<StringOutputFormatter>();
    options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});

Sem o StringOutputFormatter, o formatador JSON interno formata os tipos de retorno string. Se o formatador JSON interno for removido e um formatador XML estiver disponível, o formatador XML formata os tipos de retorno string. Caso contrário, os tipos de retorno string retornam 406 Not Acceptable.

Sem o HttpNoContentOutputFormatter, os objetos nulos são formatados com o formatador configurado. Por exemplo:

  • O formatador JSON retorna uma resposta com um corpo de null.
  • O formatador XML retorna um elemento XML vazio com o atributo xsi:nil="true" definido.

Mapeamentos de URL do formato da resposta

Os clientes podem solicitar um formato específico como parte da URL, por exemplo:

  • Na cadeia de caracteres de consulta ou parte do caminho.
  • Usando uma extensão de arquivo específica de formato, como .xml ou .json.

O mapeamento do caminho da solicitação deve ser especificado na rota que está sendo usada pela API. Por exemplo:

[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
    private readonly TodoItemStore _todoItemStore;

    public TodoItemsController(TodoItemStore todoItemStore) =>
        _todoItemStore = todoItemStore;

    [HttpGet("{id:long}.{format?}")]
    public TodoItem? GetById(long id) =>
        _todoItemStore.GetById(id);

A rota anterior permite que o formato solicitado seja especificado usando uma extensão de arquivo opcional. O atributo [FormatFilter] verifica a existência do valor de formato no RouteData e mapeia o formato da resposta para o formatador adequado quando a resposta é criada.

Rota Formatador
/api/todoitems/5 O formatador de saída padrão
/api/todoitems/5.json O formatador JSON (se configurado)
/api/todoitems/5.xml O formatador XML (se configurado)

Desserialização polimórfica

Os recursos internos fornecem um intervalo limitado de serialização polimórfica, mas nenhum suporte para desserialização. A desserialização requer um conversor personalizado. Confira Desserialização polimórfica para obter um exemplo completo de desserialização polimórfica.

Recursos adicionais

O ASP.NET Core MVC tem suporte para formatar dados de resposta. Os dados de resposta podem ser formatados usando formatos específicos ou em resposta ao formato solicitado pelo cliente.

Exibir ou baixar código de exemplo (como baixar)

Resultados de ações específicas do formato

Alguns tipos de resultado de ação são específicos a um formato específico, como JsonResult e ContentResult. As ações podem retornar resultados formatados em um formato específico, independentemente das preferências do cliente. Por exemplo, retornar JsonResult retorna dados formatados em JSON. Retornar ContentResult ou uma cadeia de caracteres, retorna dados de cadeia de caracteres de texto sem formatação.

Não é necessário que uma ação retorne um tipo específico. O ASP.NET Core dá suporte a qualquer valor retornado de objeto. Os resultados de ações que retornam objetos que não são tipos IActionResult são serializados usando a implementação IOutputFormatter apropriada. Para obter mais informações, confira Tipos de retorno de ação do controlador na API web do AsP.NET Core.

O método auxiliar interno Ok retorna dados formatados em JSON:

// GET: api/authors
[HttpGet]
public ActionResult Get()
{
    return Ok(_authors.List());
}

O download de exemplo retorna a lista de autores. Usar as ferramentas de desenvolvimento do navegador F12 ou http-repl com o código anterior:

  • O cabeçalho de resposta que contém content-type:application/json; charset=utf-8 é exibido.
  • Os cabeçalhos de solicitação são exibidos. Por exemplo, o cabeçalho Accept. O cabeçalho Accept é ignorado pelo código anterior.

Para retornar dados formatados como texto sem formatação, use ContentResult e o auxiliar Content:

// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
    return Content("An API listing authors of docs.asp.net.");
}

No código anterior, o Content-Type retornado é text/plain. Retornando uma cadeia de caracteres entrega Content-Type de text/plain:

// GET api/authors/version
[HttpGet("version")]
public string Version()
{
    return "Version 1.0.0";
}

Para ações com vários tipos de retorno, retorne IActionResult. Por exemplo, retornar diferentes códigos de status HTTP com base no resultado das operações realizadas.

Negociação de conteúdo

A negociação de conteúdo ocorre quando o cliente especifica um cabeçalho Accept. O formato padrão usado pelo ASP.NET Core é JSON. A negociação de conteúdo é:

  • Implementada por ObjectResult.
  • Desenvolvida com base nos resultados de ação específica de código de status retornados dos métodos auxiliares. Os métodos auxiliares dos resultados da ação são baseados em ObjectResult.

Quando um tipo de modelo é retornado, o tipo de retorno é ObjectResult.

O seguinte método de ação usa os métodos auxiliares Ok e NotFound:

// GET: api/authors/search?namelike=th
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
    var result = _authors.GetByNameSubstring(namelike);
    if (!result.Any())
    {
        return NotFound(namelike);
    }
    return Ok(result);
}

Por padrão, o ASP.NET Core dá suporte a tipos de mídia application/json, text/json e text/plain. Ferramentas como o Fiddler ou o http-repl podem definir o cabeçalho da solicitação Accept para especificar o formato de retorno. Quando o cabeçalho Accept contém um tipo compatível com o servidor, esse tipo é retornado. A próxima seção mostra como adicionar formatadores adicionais.

As ações do controlador podem retornar POCOs (Objetos CLR Antigos Simples). Quando um POCO é retornado, o runtime cria automaticamente um ObjectResult que encapsula o objeto. O cliente obtém o objeto serializado formatado. Se o objeto que está sendo retornado for null, uma resposta 204 No Content será retornada.

Retornando um tipo de objeto:

// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
    return _authors.GetByAlias(alias);
}

No código anterior, uma solicitação para um alias de autor válido retorna uma resposta 200 OK com os dados do autor. Uma solicitação para um alias inválido retorna uma resposta 204 No Content.

O cabeçalho Accept

A negociação de conteúdo ocorre quando um cabeçalho Accept é exibido na solicitação. Quando uma solicitação contém um cabeçalho de accept, o ASP.NET Core:

  • Enumera os tipos de mídia no cabeçalho accept na ordem de preferência.
  • Tenta encontrar um formatador que pode produzir uma resposta em um dos formatos especificados.

Se não for encontrado nenhum formatador que possa atender à solicitação do cliente, o ASP.NET Core:

  • Retornará 406 Not Acceptable se MvcOptions.ReturnHttpNotAcceptable estiver definido como true, ou -
  • Tenta localizar o primeiro formatador que pode produzir uma resposta.

Se nenhum formatador estiver configurado para o formato solicitado, o primeiro formatador que pode formatar o objeto será usado. Se nenhum cabeçalho Accept for exibido na solicitação:

  • O primeiro formatador que pode manipular o objeto é usado para serializar a resposta.
  • Não há nenhuma negociação acontecendo. O servidor está determinando qual formato retornar.

Se o cabeçalho Accept contiver */*, o Cabeçalho é ignorado, a menos que RespectBrowserAcceptHeader seja definido como verdadeiro em MvcOptions.

Navegadores e negociação de conteúdo

Ao contrário dos clientes de API típicos, os navegadores da Web fornecem cabeçalhos Accept. Os navegadores da Web especificam muitos formatos, incluindo curingas. Por padrão, quando a estrutura detecta que a solicitação vem de um navegador:

  • O cabeçalho Accept é ignorado.
  • O conteúdo é retornado em JSON, a menos que configurado de outra forma.

Essa abordagem fornece uma experiência mais consistente entre navegadores ao consumir APIs.

Para configurar um aplicativo para honrar os cabeçalhos de aceitação do navegador, defina RespectBrowserAcceptHeader como true:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.RespectBrowserAcceptHeader = true; // false by default
    });
}

Configurar os formatadores

Os aplicativos que precisam dar suporte a formatos adicionais podem adicionar os pacotes NuGet apropriados e configurar o suporte. Há formatadores separados para entrada e saída. Formatadores de entrada são usados pelo Model Binding. Formatadores de saída são usados para formatar respostas. Para obter informações sobre como criar um formatador personalizado, confira Formatadores personalizados.

Adicionar suporte ao formato XML

Os formatadores XML implementados usando XmlSerializer são configurados chamando AddXmlSerializerFormatters:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddXmlSerializerFormatters();
}

O código anterior serializa os resultados usando XmlSerializer.

Ao usar o código anterior, os métodos de controlador retornam o formato apropriado com base no cabeçalho Accept da solicitação.

Configurar formatadores baseados em System.Text.Json

Os recursos do formatadores com base em System.Text.Json podem ser configurados, usando Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. A formatação padrão é camelCase. O código realçado a seguir define a formatação PascalCase:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddJsonOptions(options =>
            options.JsonSerializerOptions.PropertyNamingPolicy = null);
}

O seguinte método de ação chama ControllerBase.Problem para criar uma resposta ProblemDetails:

[HttpGet("error")]
public IActionResult GetError()
{
    return Problem("Something went wrong!");
}

Com o código anterior:

  • https://localhost:5001/WeatherForecast/temperature retorna PascalCase.
  • https://localhost:5001/WeatherForecast/error retorna camelCase. O resposta de erro é sempre camelCase, mesmo quando o aplicativo define o formato como PascalCase. ProblemDetails segue o RFC 7807, que especifica letras maiúsculas e minúsculas

O código a seguir define PascalCase e adiciona um conversor personalizado:

services.AddControllers().AddJsonOptions(options =>
{
    // Use the default property (Pascal) casing.
    options.JsonSerializerOptions.PropertyNamingPolicy = null;

    // Configure a custom converter.
    options.JsonSerializerOptions.Converters.Add(new MyCustomJsonConverter());
});

As opções de serialização de saída, por ação, podem ser configuradas usando JsonResult. Por exemplo:

public IActionResult Get()
{
    return Json(model, new JsonSerializerOptions
    {
        WriteIndented = true,
    });
}

Adicionar suporte ao formato JSON com base em Newtonsoft.Json

Os formatadores JSON padrão são baseados em System.Text.Json. O suporte para formatadores e recursos baseados em Newtonsoft.Json está disponível por meio da instalação do pacote NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson e da configuração dele no Startup.ConfigureServices.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddNewtonsoftJson();
}

No código anterior, a chamada para AddNewtonsoftJson configura os seguintes recursos de API Web, MVC e Razor Pages para usar Newtonsoft.Json:

Alguns recursos podem não funcionar bem com formatadores baseados em System.Text.Json e exigem uma referência aos formatadores baseados em Newtonsoft.Json. Continue usando os formatadores baseados em Newtonsoft.Json quando o aplicativo:

  • Usa atributos Newtonsoft.Json. Por exemplo, [JsonProperty] ou [JsonIgnore].
  • Personaliza as configurações de serialização.
  • Depende dos recursos que o Newtonsoft.Json oferece.

Os recursos do formatadores com base em Newtonsoft.Json podem ser configurados, usando Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings:

services.AddControllers().AddNewtonsoftJson(options =>
{
    // Use the default property (Pascal) casing
    options.SerializerSettings.ContractResolver = new DefaultContractResolver();

    // Configure a custom converter
    options.SerializerSettings.Converters.Add(new MyCustomJsonConverter());
});

As opções de serialização de saída, por ação, podem ser configuradas usando JsonResult. Por exemplo:

public IActionResult Get()
{
    return Json(model, new JsonSerializerSettings
    {
        Formatting = Formatting.Indented,
    });
}

Especificar um formato

Para restringir os formatos de resposta, aplique o filtro [Produces]. Assim como a maioria dos filtros, [Produces] pode ser aplicado na ação, controlador ou escopo global:

[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{

O filtro [Produces] anterior:

  • Força todas as ações dentro do controlador a retornar respostas formatadas em JSON para POCOs (Objetos CLR Antigos Simples) ou ObjectResult e seus tipos derivados.
  • Se outros formatadores estiverem configurados e o cliente especificar um formato diferente, JSON será retornado.

Para obter mais informações, veja Filtros.

Formatadores de letras maiúsculas e minúsculas especiais

Alguns casos especiais são implementados com formatadores internos. Por padrão, os tipos de retorno string são formatados como text/plain (text/html, se solicitado por meio do cabeçalho Accept). Esse comportamento pode ser excluído com a remoção do StringOutputFormatter. Os formatadores são removidos no método ConfigureServices. Ações que têm um tipo de retorno de objeto de modelo retornarão 204 No Content ao retornar null. Esse comportamento pode ser excluído com a remoção do HttpNoContentOutputFormatter. O código a seguir remove o StringOutputFormatter e o HttpNoContentOutputFormatter.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        // requires using Microsoft.AspNetCore.Mvc.Formatters;
        options.OutputFormatters.RemoveType<StringOutputFormatter>();
        options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
    });
}

Sem o StringOutputFormatter, o formatador JSON interno formata os tipos de retorno string. Se o formatador JSON interno for removido e um formatador XML estiver disponível, o formatador XML formata os tipos de retorno string. Caso contrário, os tipos de retorno string retornam 406 Not Acceptable.

Sem o HttpNoContentOutputFormatter, os objetos nulos são formatados com o formatador configurado. Por exemplo:

  • O formatador JSON retorna uma resposta com um corpo de null.
  • O formatador XML retorna um elemento XML vazio com o atributo xsi:nil="true" definido.

Mapeamentos de URL do formato da resposta

Os clientes podem solicitar um formato específico como parte da URL, por exemplo:

  • Na cadeia de caracteres de consulta ou parte do caminho.
  • Usando uma extensão de arquivo específica de formato, como .xml ou .json.

O mapeamento do caminho da solicitação deve ser especificado na rota que está sendo usada pela API. Por exemplo:

[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
    [HttpGet("{id}.{format?}")]
    public Product Get(int id)
    {

A rota anterior permite que o formato solicitado seja especificado como uma extensão de arquivo opcional. O atributo [FormatFilter] verifica a existência do valor de formato no RouteData e mapeia o formato da resposta para o formatador adequado quando a resposta é criada.

Rota Formatador
/api/products/5 O formatador de saída padrão
/api/products/5.json O formatador JSON (se configurado)
/api/products/5.xml O formatador XML (se configurado)

O ASP.NET Core MVC dá suporte à formatação de dados de resposta, usando formatos especificados ou em resposta à solicitação de um cliente.

Resultados de ações específicas do formato

Alguns tipos de resultado de ação são específicos a um formato específico, como JsonResult e ContentResult. As ações podem retornar resultados que sempre usam um formato especificado, ignorando a solicitação de um cliente para um formato diferente. Por exemplo, retornar JsonResult, retorna dados formatados em JSON e retornar ContentResult, retorna dados de cadeia de caracteres de texto sem formação.

Não é necessário que uma ação retorne um tipo específico. O ASP.NET Core dá suporte a qualquer valor retornado de objeto. Os resultados de ações que retornam objetos que não são tipos IActionResult são serializados usando a implementação IOutputFormatter apropriada. Para obter mais informações, confira Tipos de retorno de ação do controlador na API web do AsP.NET Core.

Por padrão, o método auxiliar interno ControllerBase.Ok retorna dados formatados em JSON:

[HttpGet]
public IActionResult Get()
    => Ok(_todoItemStore.GetList());

O código de exemplo retorna uma lista de itens pendentes. Usar as ferramentas de desenvolvimento do navegador F12 ou http-repl com o código anterior exibe:

  • O cabeçalho de resposta que contém content-type:application/json; charset=utf-8.
  • Os cabeçalhos de solicitação. Por exemplo, o cabeçalho Accept. O cabeçalho Accept é ignorado pelo código anterior.

Para retornar dados formatados como texto sem formatação, use ContentResult e o auxiliar Content:

[HttpGet("Version")]
public ContentResult GetVersion()
    => Content("v1.0.0");

No código anterior, o Content-Type retornado é text/plain.

Para ações com vários tipos de retorno, retorne IActionResult. Por exemplo, ao retornar diferentes códigos de status HTTP com base no resultado da operação.

Negociação de conteúdo

A negociação de conteúdo ocorre quando o cliente especifica um cabeçalho Accept. O formato padrão usado pelo ASP.NET Core é JSON. A negociação de conteúdo é:

  • Implementada por ObjectResult.
  • Desenvolvida com base nos resultados de ação específica de código de status retornados dos métodos auxiliares. Os métodos auxiliares dos resultados da ação são baseados em ObjectResult.

Quando um tipo de modelo é retornado, o tipo de retorno é ObjectResult.

O seguinte método de ação usa os métodos auxiliares Ok e NotFound:

[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
    var todo = _todoItemStore.GetById(id);

    if (todo is null)
    {
        return NotFound();
    }

    return Ok(todo);
}

Por padrão, o ASP.NET Core dá suporte aos seguintes tipos de mídia:

  • application/json
  • text/json
  • text/plain

Ferramentas como o Fiddler ou o http-repl podem definir o cabeçalho da solicitação Accept para especificar o formato de retorno. Quando o cabeçalho Accept contém um tipo compatível com o servidor, esse tipo é retornado. A próxima seção mostra como adicionar formatadores adicionais.

As ações do controlador podem retornar POCOs (Objetos CLR Antigos Simples). Quando um POCO é retornado, o runtime cria automaticamente um ObjectResult que encapsula o objeto. O cliente obtém o objeto serializado formatado. Se o objeto que está sendo retornado for null, uma resposta 204 No Content será retornada.

O exemplo a seguir retorna um tipo de objeto:

[HttpGet("{id:long}")]
public TodoItem? GetById(long id)
    => _todoItemStore.GetById(id);

No código anterior, uma solicitação para um item todo válido retorna uma resposta 200 OK. Uma solicitação para um item todo inválido retorna uma resposta 204 No Content.

O cabeçalho Accept

A negociação de conteúdo ocorre quando um cabeçalho Accept é exibido na solicitação. Quando uma solicitação contém um cabeçalho de accept, o ASP.NET Core:

  • Enumera os tipos de mídia no cabeçalho accept na ordem de preferência.
  • Tenta encontrar um formatador que pode produzir uma resposta em um dos formatos especificados.

Se não for encontrado nenhum formatador que possa atender à solicitação do cliente, o ASP.NET Core:

  • Retornará 406 Not Acceptable se MvcOptions.ReturnHttpNotAcceptable estiver definido como true, ou -
  • Tenta localizar o primeiro formatador que pode produzir uma resposta.

Se nenhum formatador estiver configurado para o formato solicitado, o primeiro formatador que pode formatar o objeto será usado. Se nenhum cabeçalho Accept for exibido na solicitação:

  • O primeiro formatador que pode manipular o objeto é usado para serializar a resposta.
  • Não há nenhuma negociação acontecendo. O servidor está determinando qual formato retornar.

Se o cabeçalho Accept contiver */*, o Cabeçalho é ignorado, a menos que RespectBrowserAcceptHeader seja definido como verdadeiro em MvcOptions.

Navegadores e negociação de conteúdo

Ao contrário dos clientes de API típicos, os navegadores da Web fornecem cabeçalhos Accept. Os navegadores da Web especificam muitos formatos, incluindo curingas. Por padrão, quando a estrutura detecta que a solicitação vem de um navegador:

  • O cabeçalho Accept é ignorado.
  • O conteúdo é retornado em JSON, a menos que configurado de outra forma.

Essa abordagem fornece uma experiência mais consistente entre navegadores ao consumir APIs.

Para configurar um aplicativo para respeitar os cabeçalhos de aceitação do navegador, defina a propriedade RespectBrowserAcceptHeader como true:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.RespectBrowserAcceptHeader = true;
});

Configurar os formatadores

Os aplicativos que precisam dar suporte a formatos extras podem adicionar os pacotes NuGet apropriados e configurar o suporte. Há formatadores separados para entrada e saída. Formatadores de entrada são usados pelo Model Binding. Formatadores de saída são usados para formatar respostas. Para obter informações sobre como criar um formatador personalizado, confira Formatadores personalizados.

Adicionar suporte ao formato XML

Para configurar formatadores XML implementados usando XmlSerializer, chame AddXmlSerializerFormatters:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddXmlSerializerFormatters();

Ao usar o código anterior, os métodos de controlador retornam o formato apropriado com base no cabeçalho Accept da solicitação.

Configurar formatadores baseados em System.Text.Json

Para configurar recursos para os formatadores baseados em System.Text.Json, use Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. O código destacado a seguir configura a formatação PascalCase em vez da formatação camelCase padrão:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

Para configurar opções de serialização de saída para ações específicas, use JsonResult. Por exemplo:

[HttpGet]
public IActionResult Get() 
    => new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerOptions { PropertyNamingPolicy = null });

Adicionar suporte ao formato Newtonsoft.JsonON baseado em JS

Os formatadores JSON padrão usam System.Text.Json. Para usar os formatadores baseados em Newtonsoft.Json, instale o pacote NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson e configure-o em Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddNewtonsoftJson();

No código anterior, a chamada para AddNewtonsoftJson configura os seguintes recursos de API Web, MVC e Razor Pages para usar Newtonsoft.Json:

Alguns recursos podem não funcionar bem com formatadores baseados em System.Text.Json e exigem uma referência aos formatadores baseados em Newtonsoft.Json. Continue usando os formatadores baseados em Newtonsoft.Json quando o aplicativo:

  • Usa atributos Newtonsoft.Json. Por exemplo, [JsonProperty] ou [JsonIgnore].
  • Personaliza as configurações de serialização.
  • Depende dos recursos que o Newtonsoft.Json oferece.

Para configurar recursos para os formatadores baseados em Newtonsoft.Json, use SerializerSettings:

builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
    });

Para configurar opções de serialização de saída para ações específicas, use JsonResult. Por exemplo:

[HttpGet]
public IActionResult GetNewtonsoftJson()
    => new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });

Formatar as respostas ProblemDetails e ValidationProblemDetails

O seguinte método de ação chama ControllerBase.Problem para criar uma resposta ProblemDetails:

[HttpGet("Error")]
public IActionResult GetError()
    => Problem("Something went wrong.");

Uma resposta ProblemDetails é sempre camelCase, mesmo quando o aplicativo define o formato como PascalCase. ProblemDetails segue o RFC 7807, que especifica letras minúsculas.

Quando o atributo [ApiController] é aplicado a uma classe de controlador, o controlador cria uma resposta ValidationProblemDetails quando a Validação de Modelo falha. Essa resposta inclui um dicionário que usa os nomes das propriedades do modelo como chaves de erro, sem alterações. Por exemplo, o modelo a seguir inclui uma única propriedade que requer validação:

public class SampleModel
{
    [Range(1, 10)]
    public int Value { get; set; }
}

Por padrão, a resposta ValidationProblemDetails retornada quando a propriedade Value é inválida usa uma chave de erro de Value, conforme mostrado no exemplo a seguir:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-00000000000000000000000000000000-000000000000000-00",
  "errors": {
    "Value": [
      "The field Value must be between 1 and 10."
    ]
  }
}

Para formatar os nomes de propriedade usados como chaves de erro, adicione uma implementação de IMetadataDetailsProvider à coleção MvcOptions.ModelMetadataDetailsProviders. O exemplo a seguir adiciona uma implementação baseada em System.Text.Json, SystemTextJsonValidationMetadataProvider, que formata nomes de propriedade como camelCase por padrão:

builder.Services.AddControllers();

builder.Services.Configure<MvcOptions>(options =>
{
    options.ModelMetadataDetailsProviders.Add(
        new SystemTextJsonValidationMetadataProvider());
});

SystemTextJsonValidationMetadataProvider também aceita uma implementação de JsonNamingPolicy em seu construtor, que especifica uma política de nomenclatura personalizada para formatar nomes de propriedades.

Para definir um nome personalizado para uma propriedade dentro de um modelo, use o atributo [JsonPropertyName] na propriedade:

public class SampleModel
{
    [Range(1, 10)]
    [JsonPropertyName("sampleValue")]
    public int Value { get; set; }
}

A resposta ValidationProblemDetails retornada pelo modelo anterior quando a propriedade Value é inválida usa uma chave de erro de sampleValue, conforme mostrado no exemplo a seguir:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-00000000000000000000000000000000-000000000000000-00",
  "errors": {
    "sampleValue": [
      "The field Value must be between 1 and 10."
    ]
  }
}

Para formatar a resposta ValidationProblemDetails usando Newtonsoft.Json, use NewtonsoftJsonValidationMetadataProvider:

builder.Services.AddControllers()
    .AddNewtonsoftJson();

builder.Services.Configure<MvcOptions>(options =>
{
    options.ModelMetadataDetailsProviders.Add(
        new NewtonsoftJsonValidationMetadataProvider());
});

Por padrão, NewtonsoftJsonValidationMetadataProvider formata nomes de propriedade como camelCase. NewtonsoftJsonValidationMetadataProvider também aceita uma implementação de NamingPolicy em seu construtor, que especifica uma política de nomenclatura personalizada para formatar nomes de propriedades. Para definir um nome personalizado para uma propriedade dentro de um modelo, use o atributo [JsonProperty].

Especificar um formato

Para restringir os formatos de resposta, aplique o filtro [Produces]. Assim como a maioria dos filtros, [Produces] pode ser aplicado na ação, controlador ou escopo global:

[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase

O filtro [Produces] anterior:

  • Força todas as ações dentro do controlador a retornar respostas formatadas em JSON para POCOs (Objetos CLR Antigos Simples) ou ObjectResult e seus tipos derivados.
  • Retornar respostas formatadas em JSON mesmo se outros formatadores estiverem configurados e o cliente especificar um formato diferente.

Para obter mais informações, veja Filtros.

Formatadores de letras maiúsculas e minúsculas especiais

Alguns casos especiais são implementados com formatadores internos. Por padrão, os tipos de retorno string são formatados como text/plain (text/html, se solicitado por meio do cabeçalho Accept). Esse comportamento pode ser excluído com a remoção do StringOutputFormatter. Os formatadores são removidos em Program.cs. Ações que têm um tipo de retorno de objeto de modelo retornarão 204 No Content ao retornar null. Esse comportamento pode ser excluído com a remoção do HttpNoContentOutputFormatter. O código a seguir remove o StringOutputFormatter e o HttpNoContentOutputFormatter.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    // using Microsoft.AspNetCore.Mvc.Formatters;
    options.OutputFormatters.RemoveType<StringOutputFormatter>();
    options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});

Sem o StringOutputFormatter, o formatador JSON interno formata os tipos de retorno string. Se o formatador JSON interno for removido e um formatador XML estiver disponível, o formatador XML formata os tipos de retorno string. Caso contrário, os tipos de retorno string retornam 406 Not Acceptable.

Sem o HttpNoContentOutputFormatter, os objetos nulos são formatados com o formatador configurado. Por exemplo:

  • O formatador JSON retorna uma resposta com um corpo de null.
  • O formatador XML retorna um elemento XML vazio com o atributo xsi:nil="true" definido.

Mapeamentos de URL do formato da resposta

Os clientes podem solicitar um formato específico como parte da URL, por exemplo:

  • Na cadeia de caracteres de consulta ou parte do caminho.
  • Usando uma extensão de arquivo específica de formato, como .xml ou .json.

O mapeamento do caminho da solicitação deve ser especificado na rota que está sendo usada pela API. Por exemplo:

[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
    private readonly TodoItemStore _todoItemStore;

    public TodoItemsController(TodoItemStore todoItemStore)
        => _todoItemStore = todoItemStore;

    [HttpGet("{id:long}.{format?}")]
    public TodoItem? GetById(long id)
        => _todoItemStore.GetById(id);

A rota anterior permite que o formato solicitado seja especificado usando uma extensão de arquivo opcional. O atributo [FormatFilter] verifica a existência do valor de formato no RouteData e mapeia o formato da resposta para o formatador adequado quando a resposta é criada.

Rota Formatador
/api/todoitems/5 O formatador de saída padrão
/api/todoitems/5.json O formatador JSON (se configurado)
/api/todoitems/5.xml O formatador XML (se configurado)

Desserialização polimórfica

Os recursos internos fornecem um intervalo limitado de serialização polimórfica, mas nenhum suporte para desserialização. A desserialização requer um conversor personalizado. Confira Desserialização polimórfica para obter um exemplo completo de desserialização polimórfica.

Recursos adicionais