Partilhar via


Formatar dados de resposta em ASP.NET API Web Principal

ASP.NET Core MVC suporta a formatação de dados de resposta, usando formatos especificados ou em resposta a uma solicitação do cliente.

Resultados específicos do formato da ação

Alguns tipos de resultados de ação são específicos de 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 formatados em texto simples.

Uma ação não é necessária para retornar nenhum tipo específico. ASP.NET Core suporta qualquer valor de retorno de objeto. Os resultados de ações que retornam objetos que não são tipos de IActionResult são serializados usando a implementação apropriada IOutputFormatter. Para obter mais informações, consulte Tipos de retorno de ação do controlador em ASP.NET API da Web principal.

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

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

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

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

Para retornar dados formatados em texto simples, use ContentResult e o Content utilitário:

[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údos

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 é:

  • Executado por ObjectResult.
  • Incorporado nos resultados de ação específicos do código de status retornados dos métodos auxiliares. Os métodos auxiliares para os resultados da ação baseiam-se em ObjectResult.

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

O seguinte método de ação utiliza as funções 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 suporta os seguintes tipos de mídia:

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

Ferramentas como Fiddler ou curl podem definir o cabeçalho da Accept solicitação para especificar o formato de retorno. Quando o Accept cabeçalho contém um tipo suportado pelo servidor, esse tipo é retornado. A próxima seção mostra como adicionar formatters adicionais.

As ações do controlador podem retornar POCOs (Plain Old CLR Objects). Quando um POCO é retornado, o tempo de execução 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 204 No Content resposta 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 200 OK resposta. Uma solicitação para um item todo inválido retorna uma 204 No Content resposta.

O cabeçalho *Accept*

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

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

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

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

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

Se o cabeçalho Accept contiver */*, o cabeçalho será ignorado, a menos que RespectBrowserAcceptHeader esteja definido como true em MvcOptions.

Navegadores e negociação de conteúdo

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

  • O Accept cabeçalho é 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 RespectBrowserAcceptHeader propriedade como true:

var builder = WebApplication.CreateBuilder(args);

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

Configurar formatters

Os aplicativos que precisam oferecer suporte a formatos extras podem adicionar os pacotes NuGet apropriados e configurar o suporte. Existem formatters separados para entrada e saída. Os formatadores de entrada são usados pela Vinculação de Modelo. Os formatters de saída são usados para formatar respostas. Para obter informações sobre como criar um formatador personalizado, consulte Formatters personalizados.

Adicionar suporte ao formato XML

Para configurar os 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 do controlador retornam o formato apropriado com base no cabeçalho da Accept 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 realçado a seguir configura a formatação PascalCase em vez da formatação padrão camelCase:

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 ProblemDetails resposta:

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

Uma ProblemDetails resposta é sempre camelCase, mesmo quando o aplicativo define o formato como PascalCase. ProblemDetails segue RFC 7807, que especifica 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 JSON baseado em Newtonsoft.Json

Os formatadores JSON padrão utilizam 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 Web API, MVC e Razor Pages para usar Newtonsoft.Json:

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

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

Para configurar funcionalidades 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 [Produces] filtro. Como a maioria dos filtros, [Produces] pode ser aplicado na ação, no controlador ou no escopo global:

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

O filtro anterior [Produces] :

  • Força todas as ações dentro do controlador para retornar respostas formatadas em JSON para POCOs (Plain Old CLR Objects) ou ObjectResult e seus tipos derivados.
  • Retorne respostas formatadas em JSON mesmo que outros formatters estejam configurados e o cliente especifique um formato diferente.

Para obter mais informações, consulte Filtros.

Formatadores de casos especiais

Alguns casos especiais são implementados usando formatadores integrados. Por padrão, os tipos de retorno são formatados como string (texto/html se solicitado através do cabeçalho ). Este comportamento pode ser excluído removendo o StringOutputFormatter. Formatters são removidos em Program.cs. As ações que têm um tipo de retorno de objeto de modelo retornam 204 No Content ao retornar null. Este comportamento pode ser excluído removendo o HttpNoContentOutputFormatter. O código a seguir remove o StringOutputFormatter e 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, os formatos string de formatador JSON internos retornam tipos. Se o formatador JSON interno for removido e um formatador XML estiver disponível, os formatos string do formatador XML retornarão tipos. Caso contrário, os tipos que são retornados por string retornam 406 Not Acceptable.

Sem o HttpNoContentOutputFormatter, objetos nulos são formatados usando 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 de formato de 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 do formato, como .xml ou .json.

O mapeamento do caminho da solicitação deve ser especificado na rota que a API está usando. 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 [FormatFilter] atributo verifica a existência do valor de formato no RouteData e mapeia o formato de resposta para o formatador apropriado quando a resposta é criada.

Route Formatter
/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

As funcionalidades incorporadas fornecem uma gama limitada de serialização polimórfica, mas nenhum suporte para desserialização. A desserialização requer um conversor personalizado. Consulte Desserialização polimórfica para obter uma amostra completa de desserialização polimórfica.

Recursos adicionais

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

Visualizar ou descarregar amostra de código (como descarregar)

Resultados específicos do formato da ação

Alguns tipos de resultados de ação são específicos de 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. Ao retornar ContentResult ou uma cadeia de caracteres, são devolvidos dados de texto simples formatados.

Uma ação não é necessária para retornar nenhum tipo específico. ASP.NET Core suporta qualquer valor de retorno de objeto. Os resultados de ações que retornam objetos que não são tipos de IActionResult são serializados usando a implementação apropriada IOutputFormatter. Para obter mais informações, consulte Tipos de retorno de ação do controlador em ASP.NET API da Web principal.

O método Ok auxiliar interno 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. Usando as ferramentas de desenvolvimento para navegadores F12 ou http-repl com o código previamente mencionado:

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

Para retornar dados formatados em texto simples, use ContentResult e o Content utilitário:

// 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. O retorno de 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 executadas.

Negociação de conteúdos

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 é:

  • Executado por ObjectResult.
  • Incorporado nos resultados de ação específicos do código de status retornados dos métodos auxiliares. Os métodos auxiliares para os resultados da ação baseiam-se em ObjectResult.

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

O seguinte método de ação utiliza as funções 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 suporta application/json, text/jsone tipos text/plain de mídia. Ferramentas como Fiddler ou http-repl podem definir o cabeçalho da Accept solicitação para especificar o formato de retorno. Quando o Accept cabeçalho contém um tipo suportado pelo servidor, esse tipo é retornado. A próxima seção mostra como adicionar formatters adicionais.

As ações do controlador podem retornar POCOs (Plain Old CLR Objects). Quando um POCO é retornado, o tempo de execução 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 204 No Content resposta 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 200 OK resposta com os dados do autor. Uma solicitação de um alias inválido retorna uma 204 No Content resposta.

O cabeçalho *Accept*

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

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

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

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

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

Se o cabeçalho Accept contiver */*, o cabeçalho será ignorado, a menos que RespectBrowserAcceptHeader esteja definido como true em MvcOptions.

Navegadores e negociação de conteúdo

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

  • O Accept cabeçalho é 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 formatters

Os aplicativos que precisam oferecer suporte a formatos adicionais podem adicionar os pacotes NuGet apropriados e configurar o suporte. Existem formatters separados para entrada e saída. Os formatadores de entrada são usados pela Vinculação de Modelo. Os formatters de saída são usados para formatar respostas. Para obter informações sobre como criar um formatador personalizado, consulte Formatters personalizados.

Adicionar suporte ao formato XML

XML formatters implementados usando XmlSerializer são configurados chamando AddXmlSerializerFormatters:

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

O código anterior serializa resultados usando XmlSerializer.

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

Configurar os formatadores base System.Text.Json

Os recursos para os formatadores baseados em System.Text.Json podem ser configurados usando Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. A formatação padrão é camelCase. O código destacado 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 ProblemDetails resposta:

[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. A resposta de erro é sempre camelCase, mesmo quando o aplicativo define o formato como PascalCase. ProblemDetails segue RFC 7807, que especifica o uso de letras 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, com base em cada ação, podem ser configuradas usando JsonResult. Por exemplo:

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

Adicionar suporte ao formato JSON baseado em Newtonsoft.Json

Os formatadores JSON padrão são baseados em System.Text.Json. O suporte para Newtonsoft.Json formatadores e recursos baseados está disponível ao instalar o pacote NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson e configurá-lo no Startup.ConfigureServices.

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

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

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

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

As características dos formatters baseados em Newtonsoft.Json podem ser configuradas 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, com base em cada 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 [Produces] filtro. Como a maioria dos filtros, [Produces] pode ser aplicado na ação, no controlador ou no escopo global:

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

O filtro anterior [Produces] :

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

Para obter mais informações, consulte Filtros.

Formatadores de casos especiais

Alguns casos especiais são implementados usando formatadores integrados. Por padrão, os tipos de retorno são formatados como string (texto/html se solicitado através do cabeçalho ). Este comportamento pode ser excluído removendo o StringOutputFormatter. Formatters são removidos no método ConfigureServices. As ações que têm um tipo de retorno de objeto de modelo retornam 204 No Content ao retornar null. Este comportamento pode ser excluído removendo o HttpNoContentOutputFormatter. O código a seguir remove o StringOutputFormatter e 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, os formatos string de formatador JSON internos retornam tipos. Se o formatador JSON interno for removido e um formatador XML estiver disponível, os formatos string do formatador XML retornarão tipos. Caso contrário, os tipos que são retornados por string retornam 406 Not Acceptable.

Sem o HttpNoContentOutputFormatter, objetos nulos são formatados usando 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 de formato de 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 do formato, como .xml ou .json.

O mapeamento do caminho da solicitação deve ser especificado na rota que a API está usando. 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 [FormatFilter] atributo verifica a existência do valor de formato no RouteData e mapeia o formato de resposta para o formatador apropriado quando a resposta é criada.

Route Formatter
/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)

ASP.NET Core MVC suporta a formatação de dados de resposta, usando formatos especificados ou em resposta a uma solicitação do cliente.

Resultados específicos do formato da ação

Alguns tipos de resultados de ação são específicos de 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 formatados em texto simples.

Uma ação não é necessária para retornar nenhum tipo específico. ASP.NET Core suporta qualquer valor de retorno de objeto. Os resultados de ações que retornam objetos que não são tipos de IActionResult são serializados usando a implementação apropriada IOutputFormatter. Para obter mais informações, consulte Tipos de retorno de ação do controlador em ASP.NET API da Web principal.

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

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

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

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

Para retornar dados formatados em texto simples, use ContentResult e o Content utilitário:

[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údos

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 é:

  • Executado por ObjectResult.
  • Incorporado nos resultados de ação específicos do código de status retornados dos métodos auxiliares. Os métodos auxiliares para os resultados da ação baseiam-se em ObjectResult.

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

O seguinte método de ação utiliza as funções 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 suporta os seguintes tipos de mídia:

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

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

As ações do controlador podem retornar POCOs (Plain Old CLR Objects). Quando um POCO é retornado, o tempo de execução 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 204 No Content resposta 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 200 OK resposta. Uma solicitação para um item todo inválido retorna uma 204 No Content resposta.

O cabeçalho *Accept*

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

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

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

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

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

Se o cabeçalho Accept contiver */*, o cabeçalho será ignorado, a menos que RespectBrowserAcceptHeader esteja definido como true em MvcOptions.

Navegadores e negociação de conteúdo

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

  • O Accept cabeçalho é 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 RespectBrowserAcceptHeader propriedade como true:

var builder = WebApplication.CreateBuilder(args);

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

Configurar formatters

Os aplicativos que precisam oferecer suporte a formatos extras podem adicionar os pacotes NuGet apropriados e configurar o suporte. Existem formatters separados para entrada e saída. Os formatadores de entrada são usados pela Vinculação de Modelo. Os formatters de saída são usados para formatar respostas. Para obter informações sobre como criar um formatador personalizado, consulte Formatters personalizados.

Adicionar suporte ao formato XML

Para configurar os 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 do controlador retornam o formato apropriado com base no cabeçalho da Accept 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 realçado a seguir configura a formatação PascalCase em vez da formatação padrão camelCase:

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 JSON baseado em Newtonsoft.Json

Os formatadores JSON padrão utilizam 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 Web API, MVC e Razor Pages para usar Newtonsoft.Json:

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

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

Para configurar funcionalidades 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() });

Formato ProblemDetails e ValidationProblemDetails respostas

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

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

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

Quando o [ApiController] atributo é aplicado a uma classe de controlador, o controlador cria uma ValidationProblemDetails resposta quando a Validação de Modelo falha. Essa resposta inclui um dicionário que usa os nomes de propriedade do modelo como chaves de erro, inalteradas. 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 ValidationProblemDetails resposta retornada quando a Value propriedade é 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 à MvcOptions.ModelMetadataDetailsProviders coleção. 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 no seu construtor, que especifica uma política de nomenclatura personalizada para formatar nomes de propriedade.

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 ValidationProblemDetails resposta retornada para o modelo anterior quando a Value propriedade é 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 ValidationProblemDetails resposta 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 no seu construtor, que especifica uma política de nomenclatura personalizada para formatar nomes de propriedade. Para definir um nome personalizado para uma propriedade dentro de um modelo, use o [JsonProperty] atributo.

Especificar um formato

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

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

O filtro anterior [Produces] :

  • Força todas as ações dentro do controlador para retornar respostas formatadas em JSON para POCOs (Plain Old CLR Objects) ou ObjectResult e seus tipos derivados.
  • Retorne respostas formatadas em JSON mesmo que outros formatters estejam configurados e o cliente especifique um formato diferente.

Para obter mais informações, consulte Filtros.

Formatadores de casos especiais

Alguns casos especiais são implementados usando formatadores integrados. Por padrão, os tipos de retorno são formatados como string (texto/html se solicitado através do cabeçalho ). Este comportamento pode ser excluído removendo o StringOutputFormatter. Formatters são removidos em Program.cs. As ações que têm um tipo de retorno de objeto de modelo retornam 204 No Content ao retornar null. Este comportamento pode ser excluído removendo o HttpNoContentOutputFormatter. O código a seguir remove o StringOutputFormatter e 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, os formatos string de formatador JSON internos retornam tipos. Se o formatador JSON interno for removido e um formatador XML estiver disponível, os formatos string do formatador XML retornarão tipos. Caso contrário, os tipos que são retornados por string retornam 406 Not Acceptable.

Sem o HttpNoContentOutputFormatter, objetos nulos são formatados usando 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 de formato de 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 do formato, como .xml ou .json.

O mapeamento do caminho da solicitação deve ser especificado na rota que a API está usando. 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 [FormatFilter] atributo verifica a existência do valor de formato no RouteData e mapeia o formato de resposta para o formatador apropriado quando a resposta é criada.

Route Formatter
/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

As funcionalidades incorporadas fornecem uma gama limitada de serialização polimórfica, mas nenhum suporte para desserialização. A desserialização requer um conversor personalizado. Consulte Desserialização polimórfica para obter uma amostra completa de desserialização polimórfica.

Recursos adicionais