Aplicación de formato a datos de respuesta en ASP.NET Core Web API
ASP.NET Core MVC admite el formato de los datos de respuesta, mediante formatos especificados o en respuesta a la solicitud de un cliente.
Resultados de acción específicos del formato
Algunos tipos de resultado de acción son específicos de un formato determinado, como JsonResult y ContentResult. Las acciones pueden devolver resultados que siempre usan un formato especificado, ignorando la solicitud de un cliente para un formato diferente. Por ejemplo, devolver JsonResult
devuelve datos con formato JSON y devuelve ContentResult
datos de cadena con formato de texto sin formato.
No se requiere una acción para devolver ningún tipo específico. ASP.NET Core admite cualquier valor devuelto de objeto. Los resultados de acciones que devuelven objetos que no son tipos IActionResult se serializan con la implementación IOutputFormatter correspondiente. Para obtener más información, consulte Tipos de valor devuelto de acción del controlador en ASP.NET Core API web.
De forma predeterminada, el método auxiliar integrado ControllerBase.Ok devuelve datos con formato JSON:
[HttpGet]
public IActionResult Get() =>
Ok(_todoItemStore.GetList());
El código de ejemplo devuelve una lista de elementos de tareas pendientes. Con las herramientas para desarrolladores del explorador F12 o http-repl con el código anterior se muestra:
- El encabezado de respuesta que contiene content-type:
application/json; charset=utf-8
. - Encabezados de solicitud. Por ejemplo, el encabezado
Accept
. El código anterior omite el encabezadoAccept
.
Para devolver datos con formato de texto sin formato, use ContentResult y el método del asistente Content:
[HttpGet("Version")]
public ContentResult GetVersion() =>
Content("v1.0.0");
En el código anterior, el Content-Type
devuelto es text/plain
.
Para las acciones con varios tipos de valor devuelto, devuelva IActionResult
. Por ejemplo, la devolución de códigos de estado HTTP diferentes en función del resultado de las operaciones realizadas.
Negociación de contenido
La negociación de contenido se produce cuando el cliente especifica un encabezado Accept. El formato predeterminado que ASP.NET Core usa es JSON. La negociación de contenido:
- La implementa ObjectResult.
- Se integra en los resultados de acción específicos del código de estado devueltos por los métodos auxiliares. Los métodos auxiliares de los resultados de acción se basan en
ObjectResult
.
Cuando se devuelve un tipo de modelo, el tipo de valor devuelto es ObjectResult
.
El siguiente método de acción usa los métodos del asistente Ok
y NotFound
:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
De forma predeterminada, ASP.NET Core admite los siguientes tipos de medios:
application/json
text/json
text/plain
Las herramientas como Fiddler o curl pueden establecer el encabezado de solicitud Accept
para especificar el formato de devolución. Cuando el encabezado Accept
contiene un tipo que el servidor admite, se devuelve ese tipo. En la sección siguiente se muestra cómo agregar otros formateadores.
Las acciones del controlador pueden devolver POCO (objetos CLR antiguos sin formato). Cuando se devuelve un objeto POCO, el tiempo de ejecución crea automáticamente un ObjectResult
que encapsula al objeto. El cliente obtiene el objeto serializado con formato. Si el objeto que se va a devolver es null
, se devuelve una respuesta 204 No Content
.
En el ejemplo siguiente se devuelve un tipo de objeto:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
En el código anterior, una solicitud de un elemento todo válido devuelve una 200 OK
respuesta. Una solicitud de un elemento de tareas inválido devuelve una respuesta 204 No Content
.
El encabezado Accept
La negociación de contenido se lleva a cabo cuando en la solicitud aparece un encabezado Accept
. Cuando una solicitud contiene un encabezado Accept, ASP.NET Core:
- Enumera los tipos de medios del encabezado Accept en orden de preferencia.
- Intenta encontrar un formateador que pueda generar una respuesta en uno de los formatos especificados.
Si no se encuentra ningún formateador que pueda satisfacer la solicitud del cliente, ASP.NET Core:
- Devuelve
406 Not Acceptable
si MvcOptions.ReturnHttpNotAcceptable se establece entrue
, o - - Intenta encontrar el primer formateador que puede generar una respuesta.
Si no se ha configurado ningún formateador para el formato solicitado, se usará el primer formateador que pueda dar formato al objeto. Si no aparece ningún encabezado Accept
en la solicitud:
- El primer formateador que puede controlar el objeto se usa para serializar la respuesta.
- No tiene lugar ninguna negociación. El servidor está determinando el formato que se va a devolver.
Si el encabezado Accept contiene */*
, el encabezado se omite a menos que RespectBrowserAcceptHeader
esté establecido en true en MvcOptions.
Exploradores y negociación de contenido
A diferencia de los clientes de API típicos, los exploradores web proporcionan encabezados Accept
. Los navegadores web especifican muchos formatos, incluidos los comodines. De forma predeterminada, cuando el marco detecta que la solicitud procede de un explorador:
- El encabezado
Accept
se omite. - El contenido se devuelve en JSON, a menos que se configure de otra manera.
Esto proporciona una experiencia más coherente entre los exploradores al consumir las API.
Para configurar una aplicación para que respete las cabeceras de aceptación del navegador, establezca la propiedad RespectBrowserAcceptHeader en true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
Configuración de formateadores
Las aplicaciones que necesitan admitir formatos adicionales pueden agregar los paquetes NuGet adecuados y configurar la compatibilidad. Hay formateadores independientes para la entrada y la salida. El enlace de modelos usa formateadores de entrada. Los formateadores de salida se usan para dar formato a las respuestas. Para obtener información sobre la creación de un formateador personalizado, vea Formateadores personalizados.
Adición de compatibilidad con el formato XML
Para configurar formateadores XML implementados mediante XmlSerializer, llame a AddXmlSerializerFormatters:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
Cuando se usa el código anterior, los métodos de controlador devuelven el formato adecuado en función del encabezado Accept
de la solicitud.
Configurar System.Text.Json
formateadores basados en
Para configurar las características de los formateadores basados en System.Text.Json
, use Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. El código resaltado siguiente configura el formato PascalCase en lugar del formato camelCase predeterminado:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
El método de acción siguiente llama ControllerBase.Problem a para crear una ProblemDetails respuesta:
[HttpGet("Error")]
public IActionResult GetError() =>
Problem("Something went wrong.");
Una ProblemDetails
respuesta siempre es camelCase, incluso cuando la aplicación establece el formato en PascalCase. ProblemDetails
sigue a RFC 7807, que especifica minúsculas.
Para configurar las opciones de serialización de salida para acciones específicas, use JsonResult
. Por ejemplo:
[HttpGet]
public IActionResult Get() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions
{
PropertyNamingPolicy = null
});
Adición de compatibilidad con formato JSON basado en Newtonsoft.Json
Los formateadores JSON predeterminados usan System.Text.Json
. Para usar los Newtonsoft.Json
formateadores basados en , instale el Microsoft.AspNetCore.Mvc.NewtonsoftJson
paquete NuGet y configúrelo en Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
En el código anterior, la llamada a configura AddNewtonsoftJson
las siguientes características de API web, MVC y Razor Pages para usar Newtonsoft.Json
:
- Formateadores de entrada y salida que leen y escriben JSON
- JsonResult
- Revisión JSON
- IJsonHelper
- TempData
Es posible que algunas características no funcionen bien con formateadores basados en System.Text.Json
y requieren una referencia a los formateadores basados en Newtonsoft.Json
. Siga usando los formateadores basados en Newtonsoft.Json
si la aplicación:
- Usa atributos
Newtonsoft.Json
. Por ejemplo,[JsonProperty]
o[JsonIgnore]
. - Proporciona la configuración de la serialización.
- Se basa en las características que
Newtonsoft.Json
proporciona.
Para configurar las características de los formateadores basados en Newtonsoft.Json
, use SerializerSettings:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
Para configurar las opciones de serialización de salida para acciones específicas, use JsonResult
. Por ejemplo:
[HttpGet]
public IActionResult GetNewtonsoftJson() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver()
});
Especificación de un formato
Para restringir los formatos de respuesta, aplique el filtro [Produces]
. Al igual que la mayoría de los filtros, [Produces]
puede aplicarse a la acción, el controlador o el ámbito global:
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
El filtro [Produces]
anterior:
- Obliga a todas las acciones dentro del controlador a devolver respuestas con formato JSON para POCO (objetos CLR antiguos sin formato) o ObjectResult sus tipos derivados.
- Devuelve respuestas con formato JSON incluso si se configuran otros formateadores y el cliente especifica un formato diferente.
Para más información, consulte Filtros.
Formateadores de casos especiales
Algunos casos especiales se implementan mediante formateadores integrados. De forma predeterminada, los tipos de valor devueltos string
se formatean como texto/sin formato (texto/html si se solicita a través del encabezado Accept
). Este comportamiento se puede quitar mediante la eliminación de StringOutputFormatter. Los formateadores se quitan en el método Program.cs
. Las acciones que tienen un tipo de valor devuelto de objeto de modelo devuelven 204 No Content
al devolver null
. Este comportamiento se puede quitar mediante la eliminación de HttpNoContentOutputFormatter. El código siguiente quita StringOutputFormatter
y HttpNoContentOutputFormatter
.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
Sin StringOutputFormatter
, el formateador de JSON integrado aplica formato a los tipos devueltos string
. Si se quita el formateador JSON integrado y está disponible un formateador XML, el formateador XML aplica formato a los tipos devueltos string
. De lo contrario, los tipos devueltos string
devuelven 406 Not Acceptable
.
Sin HttpNoContentOutputFormatter
, se da formato a los objetos nulos mediante el formateador configurado. Por ejemplo:
- El formateador JSON devuelve una respuesta con un cuerpo de
null
. - El formateador XML devuelve un elemento XML vacío con el atributo
xsi:nil="true"
establecido.
Asignaciones de direcciones URL de formato de respuesta
Los clientes pueden solicitar un formato determinado como parte de la dirección URL, por ejemplo:
- En la cadena de consulta o en una parte de la ruta de acceso.
- Mediante el uso de una extensión de archivo específica del formato como .xml o .json.
La asignación de la ruta de acceso de la solicitud debe especificarse en la ruta que use la API. Por ejemplo:
[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);
Esta ruta anterior permite especificar el formato solicitado como una extensión de archivo opcional. El atributo [FormatFilter]
comprueba la existencia del valor de formato en RouteData
y asigna el formato de respuesta al formateador adecuado cuando se crea la respuesta.
Ruta | Formateador |
---|---|
/api/todoitems/5 |
Formateador de salida predeterminado |
/api/todoitems/5.json |
Formateador JSON (si está configurado) |
/api/todoitems/5.xml |
Formateador XML (si está configurado) |
Deserialización polimórfica
Las características integradas proporcionan una gama limitada de serialización polimórfica, pero no admiten ningún tipo de deserialización. La deserialización requiere un convertidor personalizado. Consulte Deserialización polimórfica para obtener una muestra completa de deserialización polimórfica.
Recursos adicionales
ASP.NET Core MVC tiene compatibilidad para formatear datos de respuesta. Se pueden formatear los datos de respuesta con formatos específicos o en respuesta al formato solicitado por el cliente.
Vea o descargue el código de ejemplo (cómo descargarlo)
Resultados de acción específicos del formato
Algunos tipos de resultado de acción son específicos de un formato determinado, como JsonResult y ContentResult. Las acciones pueden devolver resultados con un formato determinado, independientemente de las preferencias del cliente. Por ejemplo, la devolución de JsonResult
devuelve datos con formato JSON. Al devolver ContentResult
o una cadena se devuelven datos de cadena con formato de texto sin formato.
No se requiere una acción para devolver ningún tipo específico. ASP.NET Core admite cualquier valor devuelto de objeto. Los resultados de acciones que devuelven objetos que no son tipos IActionResult se serializan con la implementación IOutputFormatter correspondiente. Para obtener más información, consulte Tipos de valor devuelto de acción del controlador en ASP.NET Core API web.
El método auxiliar integrado Ok devuelve datos con formato JSON:
// GET: api/authors
[HttpGet]
public ActionResult Get()
{
return Ok(_authors.List());
}
La descarga de ejemplo devuelve la lista de autores. Con las herramientas para desarrolladores del explorador F12 o http-repl con el código anterior:
- Se muestra el encabezado de respuesta que contiene content-type:
application/json; charset=utf-8
. - Se muestran los encabezados de solicitud. Por ejemplo, el encabezado
Accept
. El código anterior omite el encabezadoAccept
.
Para devolver datos con formato de texto sin formato, use ContentResult y el método del asistente Content:
// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
return Content("An API listing authors of docs.asp.net.");
}
En el código anterior, el Content-Type
devuelto es text/plain
. Al devolver una cadena se proporciona Content-Type
de text/plain
:
// GET api/authors/version
[HttpGet("version")]
public string Version()
{
return "Version 1.0.0";
}
Para las acciones con varios tipos de valor devuelto, devuelva IActionResult
. Por ejemplo, la devolución de códigos de estado HTTP diferentes en función del resultado de las operaciones realizadas.
Negociación de contenido
La negociación de contenido se produce cuando el cliente especifica un encabezado Accept. El formato predeterminado que ASP.NET Core usa es JSON. La negociación de contenido:
- La implementa ObjectResult.
- Se integra en los resultados de acción específicos del código de estado devueltos por los métodos auxiliares. Los métodos auxiliares de los resultados de acción se basan en
ObjectResult
.
Cuando se devuelve un tipo de modelo, el tipo de valor devuelto es ObjectResult
.
El siguiente método de acción usa los métodos del asistente Ok
y 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);
}
De forma predeterminada, ASP.NET Core admite los tipos de medios application/json
, text/json
y text/plain
. Las herramientas como Fiddler o http-repl pueden establecer el encabezado de solicitud Accept
para especificar el formato de devolución. Cuando el encabezado Accept
contiene un tipo que el servidor admite, se devuelve ese tipo. En la sección siguiente se muestra cómo agregar otros formateadores.
Las acciones del controlador pueden devolver POCO (objetos CLR antiguos sin formato). Cuando se devuelve un objeto POCO, el tiempo de ejecución crea automáticamente un ObjectResult
que encapsula al objeto. El cliente obtiene el objeto serializado con formato. Si el objeto que se va a devolver es null
, se devuelve una respuesta 204 No Content
.
Devolución de un tipo de objeto:
// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
return _authors.GetByAlias(alias);
}
En el código anterior, una solicitud de un alias de autor válido devuelve una respuesta 200 OK
con los datos del autor. Una solicitud de un alias no válido devuelve una respuesta 204 No Content
.
El encabezado Accept
La negociación de contenido se lleva a cabo cuando en la solicitud aparece un encabezado Accept
. Cuando una solicitud contiene un encabezado Accept, ASP.NET Core:
- Enumera los tipos de medios del encabezado Accept en orden de preferencia.
- Intenta encontrar un formateador que pueda generar una respuesta en uno de los formatos especificados.
Si no se encuentra ningún formateador que pueda satisfacer la solicitud del cliente, ASP.NET Core:
- Devuelve
406 Not Acceptable
si MvcOptions.ReturnHttpNotAcceptable se establece entrue
, o - - Intenta encontrar el primer formateador que puede generar una respuesta.
Si no se ha configurado ningún formateador para el formato solicitado, se usará el primer formateador que pueda dar formato al objeto. Si no aparece ningún encabezado Accept
en la solicitud:
- El primer formateador que puede controlar el objeto se usa para serializar la respuesta.
- No tiene lugar ninguna negociación. El servidor está determinando el formato que se va a devolver.
Si el encabezado Accept contiene */*
, el encabezado se omite a menos que RespectBrowserAcceptHeader
esté establecido en true en MvcOptions.
Exploradores y negociación de contenido
A diferencia de los clientes de API típicos, los exploradores web proporcionan encabezados Accept
. Los navegadores web especifican muchos formatos, incluidos los comodines. De forma predeterminada, cuando el marco detecta que la solicitud procede de un explorador:
- El encabezado
Accept
se omite. - El contenido se devuelve en JSON, a menos que se configure de otra manera.
Esto proporciona una experiencia más coherente entre los exploradores al consumir las API.
Para configurar una aplicación para que respete los encabezados de aceptación del explorador, establezca RespectBrowserAcceptHeader en true
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
});
}
Configuración de formateadores
Las aplicaciones que necesitan admitir formatos adicionales pueden agregar los paquetes NuGet adecuados y configurar la compatibilidad. Hay formateadores independientes para la entrada y la salida. El enlace de modelos usa formateadores de entrada. Los formateadores de salida se usan para dar formato a las respuestas. Para obtener información sobre la creación de un formateador personalizado, vea Formateadores personalizados.
Adición de compatibilidad con el formato XML
Los formateadores XML que se implementan mediante XmlSerializer se configuran llamando a AddXmlSerializerFormatters:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddXmlSerializerFormatters();
}
El código anterior serializa los resultados mediante XmlSerializer
.
Cuando se usa el código anterior, los métodos de controlador devuelven el formato adecuado en función del encabezado Accept
de la solicitud.
Configurar formateadores basados en System.Text.Json
Las características para los formateadores basados en System.Text.Json
pueden configurarse mediante Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. El formato predeterminado es camelCase. El código resaltado siguiente establece el formato PascalCase:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null);
}
El método de acción siguiente llama ControllerBase.Problem a para crear una ProblemDetails respuesta:
[HttpGet("error")]
public IActionResult GetError()
{
return Problem("Something went wrong!");
}
Con el código anterior:
https://localhost:5001/WeatherForecast/temperature
devuelve PascalCase.https://localhost:5001/WeatherForecast/error
devuelve camelCase. La respuesta de error siempre es camelCase, incluso cuando la aplicación establece el formato en PascalCase.ProblemDetails
sigue a RFC 7807, que especifica minúsculas
El código siguiente establece PascalCase y agrega un convertidor 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());
});
Las opciones de serialización de salida se pueden configurar para cada acción mediante JsonResult
. Por ejemplo:
public IActionResult Get()
{
return Json(model, new JsonSerializerOptions
{
WriteIndented = true,
});
}
Adición de compatibilidad con el formato JSON basado en Newtonsoft.Json
Los formateadores JSON predeterminados se basan en System.Text.Json
. LA compatibilidad para los formateadores basados en Newtonsoft.Json
y sus características está disponible al instalar el paquete Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet y configurarlo en Startup.ConfigureServices
.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
}
En el código anterior, la llamada a configura AddNewtonsoftJson
las siguientes características de API web, MVC y Razor Pages para usar Newtonsoft.Json
:
- Formateadores de entrada y salida que leen y escriben JSON
- JsonResult
- Revisión JSON
- IJsonHelper
- TempData
Es posible que algunas características no funcionen bien con formateadores basados en System.Text.Json
y requieren una referencia a los formateadores basados en Newtonsoft.Json
. Siga usando los formateadores basados en Newtonsoft.Json
si la aplicación:
- Usa atributos
Newtonsoft.Json
. Por ejemplo,[JsonProperty]
o[JsonIgnore]
. - Proporciona la configuración de la serialización.
- Se basa en las características que
Newtonsoft.Json
proporciona.
Las características para los formateadores basados en Newtonsoft.Json
pueden configurarse mediante 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());
});
Las opciones de serialización de salida se pueden configurar para cada acción mediante JsonResult
. Por ejemplo:
public IActionResult Get()
{
return Json(model, new JsonSerializerSettings
{
Formatting = Formatting.Indented,
});
}
Especificación de un formato
Para restringir los formatos de respuesta, aplique el filtro [Produces]
. Al igual que la mayoría de los filtros, [Produces]
puede aplicarse a la acción, el controlador o el ámbito global:
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{
El filtro [Produces]
anterior:
- Obliga a todas las acciones dentro del controlador a devolver respuestas con formato JSON para POCO (objetos CLR antiguos sin formato) o ObjectResult sus tipos derivados.
- Si se configuran otros formateadores y el cliente especifica un formato diferente, se devuelve JSON.
Para más información, consulte Filtros.
Formateadores de casos especiales
Algunos casos especiales se implementan mediante formateadores integrados. De forma predeterminada, los tipos de valor devueltos string
se formatean como texto/sin formato (texto/html si se solicita a través del encabezado Accept
). Este comportamiento se puede quitar mediante la eliminación de StringOutputFormatter. Los formateadores se quitan en el método ConfigureServices
. Las acciones que tienen un tipo de valor devuelto de objeto de modelo devuelven 204 No Content
al devolver null
. Este comportamiento se puede quitar mediante la eliminación de HttpNoContentOutputFormatter. El código siguiente quita StringOutputFormatter
y HttpNoContentOutputFormatter
.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
// requires using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
}
Sin StringOutputFormatter
, el formateador de JSON integrado aplica formato a los tipos devueltos string
. Si se quita el formateador JSON integrado y está disponible un formateador XML, el formateador XML aplica formato a los tipos devueltos string
. De lo contrario, los tipos devueltos string
devuelven 406 Not Acceptable
.
Sin HttpNoContentOutputFormatter
, se da formato a los objetos nulos mediante el formateador configurado. Por ejemplo:
- El formateador JSON devuelve una respuesta con un cuerpo de
null
. - El formateador XML devuelve un elemento XML vacío con el atributo
xsi:nil="true"
establecido.
Asignaciones de direcciones URL de formato de respuesta
Los clientes pueden solicitar un formato determinado como parte de la dirección URL, por ejemplo:
- En la cadena de consulta o en una parte de la ruta de acceso.
- Mediante el uso de una extensión de archivo específica del formato como .xml o .json.
La asignación de la ruta de acceso de la solicitud debe especificarse en la ruta que use la API. Por ejemplo:
[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
[HttpGet("{id}.{format?}")]
public Product Get(int id)
{
Esta ruta anterior permite especificar el formato solicitado como una extensión de archivo opcional. El atributo [FormatFilter]
comprueba la existencia del valor de formato en RouteData
y asigna el formato de respuesta al formateador adecuado cuando se crea la respuesta.
Ruta | Formateador |
---|---|
/api/products/5 |
Formateador de salida predeterminado |
/api/products/5.json |
Formateador JSON (si está configurado) |
/api/products/5.xml |
Formateador XML (si está configurado) |
ASP.NET Core MVC admite el formato de los datos de respuesta, mediante formatos especificados o en respuesta a la solicitud de un cliente.
Resultados de acción específicos del formato
Algunos tipos de resultado de acción son específicos de un formato determinado, como JsonResult y ContentResult. Las acciones pueden devolver resultados que siempre usan un formato especificado, ignorando la solicitud de un cliente para un formato diferente. Por ejemplo, devolver JsonResult
devuelve datos con formato JSON y devuelve ContentResult
datos de cadena con formato de texto sin formato.
No se requiere una acción para devolver ningún tipo específico. ASP.NET Core admite cualquier valor devuelto de objeto. Los resultados de acciones que devuelven objetos que no son tipos IActionResult se serializan con la implementación IOutputFormatter correspondiente. Para obtener más información, consulte Tipos de valor devuelto de acción del controlador en ASP.NET Core API web.
De forma predeterminada, el método auxiliar integrado ControllerBase.Ok devuelve datos con formato JSON:
[HttpGet]
public IActionResult Get()
=> Ok(_todoItemStore.GetList());
El código de ejemplo devuelve una lista de elementos de tareas pendientes. Con las herramientas para desarrolladores del explorador F12 o http-repl con el código anterior se muestra:
- El encabezado de respuesta que contiene content-type:
application/json; charset=utf-8
. - Encabezados de solicitud. Por ejemplo, el encabezado
Accept
. El código anterior omite el encabezadoAccept
.
Para devolver datos con formato de texto sin formato, use ContentResult y el método del asistente Content:
[HttpGet("Version")]
public ContentResult GetVersion()
=> Content("v1.0.0");
En el código anterior, el Content-Type
devuelto es text/plain
.
Para las acciones con varios tipos de valor devuelto, devuelva IActionResult
. Por ejemplo, la devolución de códigos de estado HTTP diferentes en función del resultado de las operaciones realizadas.
Negociación de contenido
La negociación de contenido se produce cuando el cliente especifica un encabezado Accept. El formato predeterminado que ASP.NET Core usa es JSON. La negociación de contenido:
- La implementa ObjectResult.
- Se integra en los resultados de acción específicos del código de estado devueltos por los métodos auxiliares. Los métodos auxiliares de los resultados de acción se basan en
ObjectResult
.
Cuando se devuelve un tipo de modelo, el tipo de valor devuelto es ObjectResult
.
El siguiente método de acción usa los métodos del asistente Ok
y NotFound
:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
De forma predeterminada, ASP.NET Core admite los siguientes tipos de medios:
application/json
text/json
text/plain
Las herramientas como Fiddler o http-repl pueden establecer el encabezado de solicitud Accept
para especificar el formato de devolución. Cuando el encabezado Accept
contiene un tipo que el servidor admite, se devuelve ese tipo. En la sección siguiente se muestra cómo agregar otros formateadores.
Las acciones del controlador pueden devolver POCO (objetos CLR antiguos sin formato). Cuando se devuelve un objeto POCO, el tiempo de ejecución crea automáticamente un ObjectResult
que encapsula al objeto. El cliente obtiene el objeto serializado con formato. Si el objeto que se va a devolver es null
, se devuelve una respuesta 204 No Content
.
En el ejemplo siguiente se devuelve un tipo de objeto:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
En el código anterior, una solicitud de un elemento todo válido devuelve una 200 OK
respuesta. Una solicitud de un elemento de tareas inválido devuelve una respuesta 204 No Content
.
El encabezado Accept
La negociación de contenido se lleva a cabo cuando en la solicitud aparece un encabezado Accept
. Cuando una solicitud contiene un encabezado Accept, ASP.NET Core:
- Enumera los tipos de medios del encabezado Accept en orden de preferencia.
- Intenta encontrar un formateador que pueda generar una respuesta en uno de los formatos especificados.
Si no se encuentra ningún formateador que pueda satisfacer la solicitud del cliente, ASP.NET Core:
- Devuelve
406 Not Acceptable
si MvcOptions.ReturnHttpNotAcceptable se establece entrue
, o - - Intenta encontrar el primer formateador que puede generar una respuesta.
Si no se ha configurado ningún formateador para el formato solicitado, se usará el primer formateador que pueda dar formato al objeto. Si no aparece ningún encabezado Accept
en la solicitud:
- El primer formateador que puede controlar el objeto se usa para serializar la respuesta.
- No tiene lugar ninguna negociación. El servidor está determinando el formato que se va a devolver.
Si el encabezado Accept contiene */*
, el encabezado se omite a menos que RespectBrowserAcceptHeader
esté establecido en true en MvcOptions.
Exploradores y negociación de contenido
A diferencia de los clientes de API típicos, los exploradores web proporcionan encabezados Accept
. Los navegadores web especifican muchos formatos, incluidos los comodines. De forma predeterminada, cuando el marco detecta que la solicitud procede de un explorador:
- El encabezado
Accept
se omite. - El contenido se devuelve en JSON, a menos que se configure de otra manera.
Esto proporciona una experiencia más coherente entre los exploradores al consumir las API.
Para configurar una aplicación para que respete las cabeceras de aceptación del navegador, establezca la propiedad RespectBrowserAcceptHeader en true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
Configuración de formateadores
Las aplicaciones que necesitan admitir formatos adicionales pueden agregar los paquetes NuGet adecuados y configurar la compatibilidad. Hay formateadores independientes para la entrada y la salida. El enlace de modelos usa formateadores de entrada. Los formateadores de salida se usan para dar formato a las respuestas. Para obtener información sobre la creación de un formateador personalizado, vea Formateadores personalizados.
Adición de compatibilidad con el formato XML
Para configurar formateadores XML implementados mediante XmlSerializer, llame a AddXmlSerializerFormatters:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
Cuando se usa el código anterior, los métodos de controlador devuelven el formato adecuado en función del encabezado Accept
de la solicitud.
Configurar System.Text.Json
formateadores basados en
Para configurar las características de los formateadores basados en System.Text.Json
, use Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. El código resaltado siguiente configura el formato PascalCase en lugar del formato camelCase predeterminado:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
Para configurar las opciones de serialización de salida para acciones específicas, use JsonResult. Por ejemplo:
[HttpGet]
public IActionResult Get()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions { PropertyNamingPolicy = null });
Adición de compatibilidad con formato JSON basado en Newtonsoft.Json
Los formateadores JSON predeterminados usan System.Text.Json
. Para usar los Newtonsoft.Json
formateadores basados en , instale el Microsoft.AspNetCore.Mvc.NewtonsoftJson
paquete NuGet y configúrelo en Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
En el código anterior, la llamada a configura AddNewtonsoftJson
las siguientes características de API web, MVC y Razor Pages para usar Newtonsoft.Json
:
- Formateadores de entrada y salida que leen y escriben JSON
- JsonResult
- Revisión JSON
- IJsonHelper
- TempData
Es posible que algunas características no funcionen bien con formateadores basados en System.Text.Json
y requieren una referencia a los formateadores basados en Newtonsoft.Json
. Siga usando los formateadores basados en Newtonsoft.Json
si la aplicación:
- Usa atributos
Newtonsoft.Json
. Por ejemplo,[JsonProperty]
o[JsonIgnore]
. - Proporciona la configuración de la serialización.
- Se basa en las características que
Newtonsoft.Json
proporciona.
Para configurar las características de los formateadores basados en Newtonsoft.Json
, use SerializerSettings:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
Para configurar las opciones de serialización de salida para acciones específicas, use JsonResult
. Por ejemplo:
[HttpGet]
public IActionResult GetNewtonsoftJson()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });
Formato ProblemDetails
y ValidationProblemDetails
respuestas
El método de acción siguiente llama ControllerBase.Problem a para crear una ProblemDetails respuesta:
[HttpGet("Error")]
public IActionResult GetError()
=> Problem("Something went wrong.");
Una ProblemDetails
respuesta siempre es camelCase, incluso cuando la aplicación establece el formato en PascalCase. ProblemDetails
sigue a RFC 7807, que especifica minúsculas.
Cuando el [ApiController]
atributo se aplica a una clase de controlador, el controlador crea una respuesta cuando se produce un ValidationProblemDetails error en la validación del modelo. Esta respuesta incluye un diccionario que usa los nombres de propiedad del modelo como claves de error, sin cambios. Por ejemplo, el siguiente modelo incluye una sola propiedad que requiere validación:
public class SampleModel
{
[Range(1, 10)]
public int Value { get; set; }
}
De forma predeterminada, la ValidationProblemDetails
respuesta devuelta cuando la Value
propiedad no es válida usa una clave de error de Value
, como se muestra en el ejemplo siguiente:
{
"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 dar formato a los nombres de propiedad usados como claves de error, agregue una implementación de IMetadataDetailsProvider a la MvcOptions.ModelMetadataDetailsProviders colección. En el ejemplo siguiente se agrega una implementación basada en System.Text.Json
, SystemTextJsonValidationMetadataProvider
, que da formato a los nombres de propiedad como camelCase de forma predeterminada:
builder.Services.AddControllers();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new SystemTextJsonValidationMetadataProvider());
});
SystemTextJsonValidationMetadataProvider
también acepta una implementación de JsonNamingPolicy en su constructor, que especifica una directiva de nomenclatura personalizada para dar formato a los nombres de propiedad.
Para establecer un nombre personalizado para una propiedad dentro de un modelo, use el atributo [JsonPropertyName] en la propiedad:
public class SampleModel
{
[Range(1, 10)]
[JsonPropertyName("sampleValue")]
public int Value { get; set; }
}
De forma predeterminada, la ValidationProblemDetails
respuesta devuelta cuando la Value
propiedad no es válida usa una clave de error de sampleValue
, como se muestra en el ejemplo siguiente:
{
"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 dar formato a la ValidationProblemDetails
respuesta mediante Newtonsoft.Json
, use NewtonsoftJsonValidationMetadataProvider
:
builder.Services.AddControllers()
.AddNewtonsoftJson();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new NewtonsoftJsonValidationMetadataProvider());
});
De forma predeterminada, NewtonsoftJsonValidationMetadataProvider
da formato a los nombres de propiedad como camelCase. NewtonsoftJsonValidationMetadataProvider
también acepta una implementación de NamingPolicy
en su constructor, que especifica una directiva de nomenclatura personalizada para dar formato a los nombres de propiedad. Para establecer un nombre personalizado para una propiedad dentro de un modelo, use el [JsonProperty]
atributo .
Especificación de un formato
Para restringir los formatos de respuesta, aplique el filtro [Produces]
. Al igual que la mayoría de los filtros, [Produces]
puede aplicarse a la acción, el controlador o el ámbito global:
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
El filtro [Produces]
anterior:
- Obliga a todas las acciones dentro del controlador a devolver respuestas con formato JSON para POCO (objetos CLR antiguos sin formato) o ObjectResult sus tipos derivados.
- Devuelve respuestas con formato JSON incluso si se configuran otros formateadores y el cliente especifica un formato diferente.
Para más información, consulte Filtros.
Formateadores de casos especiales
Algunos casos especiales se implementan mediante formateadores integrados. De forma predeterminada, los tipos de valor devueltos string
se formatean como texto/sin formato (texto/html si se solicita a través del encabezado Accept
). Este comportamiento se puede quitar mediante la eliminación de StringOutputFormatter. Los formateadores se quitan en el método Program.cs
. Las acciones que tienen un tipo de valor devuelto de objeto de modelo devuelven 204 No Content
al devolver null
. Este comportamiento se puede quitar mediante la eliminación de HttpNoContentOutputFormatter. El código siguiente quita StringOutputFormatter
y HttpNoContentOutputFormatter
.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
Sin StringOutputFormatter
, el formateador de JSON integrado aplica formato a los tipos devueltos string
. Si se quita el formateador JSON integrado y está disponible un formateador XML, el formateador XML aplica formato a los tipos devueltos string
. De lo contrario, los tipos devueltos string
devuelven 406 Not Acceptable
.
Sin HttpNoContentOutputFormatter
, se da formato a los objetos nulos mediante el formateador configurado. Por ejemplo:
- El formateador JSON devuelve una respuesta con un cuerpo de
null
. - El formateador XML devuelve un elemento XML vacío con el atributo
xsi:nil="true"
establecido.
Asignaciones de direcciones URL de formato de respuesta
Los clientes pueden solicitar un formato determinado como parte de la dirección URL, por ejemplo:
- En la cadena de consulta o en una parte de la ruta de acceso.
- Mediante el uso de una extensión de archivo específica del formato como .xml o .json.
La asignación de la ruta de acceso de la solicitud debe especificarse en la ruta que use la API. Por ejemplo:
[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);
Esta ruta anterior permite especificar el formato solicitado como una extensión de archivo opcional. El atributo [FormatFilter]
comprueba la existencia del valor de formato en RouteData
y asigna el formato de respuesta al formateador adecuado cuando se crea la respuesta.
Ruta | Formateador |
---|---|
/api/todoitems/5 |
Formateador de salida predeterminado |
/api/todoitems/5.json |
Formateador JSON (si está configurado) |
/api/todoitems/5.xml |
Formateador XML (si está configurado) |
Deserialización polimórfica
Las características integradas proporcionan una gama limitada de serialización polimórfica, pero no admiten ningún tipo de deserialización. La deserialización requiere un convertidor personalizado. Consulte Deserialización polimórfica para obtener una muestra completa de deserialización polimórfica.