Mettre en forme les données des réponses dans l’API web ASP.NET Core
ASP.NET Core MVC prend en charge la mise en forme des données de réponse, à l’aide de formats spécifiés ou en réponse à la demande d’un client.
Résultats d’une action spécifique à un format
Certains types de résultats d’action sont spécifiques à un format particulier, comme JsonResult et ContentResult. Les actions peuvent retourner des résultats qui utilisent toujours un format spécifié, ignorant la demande d’un client pour un autre format. Par exemple, le renvoi de JsonResult
renvoie des données au format JSON et le renvoi de ContentResult
renvoie des données sous forme de chaîne de caractères au format texte brut.
Une action n’est pas nécessaire pour retourner un type spécifique. ASP.NET Core prend en charge toute valeur de retour d’objet. Les résultats des actions qui renvoient des objets qui ne sont pas des typesIActionResult sont sérialisés en utilisant l'implémentation IOutputFormatter appropriée. Pour plus d’informations, consultez Types de retour d’action de contrôleur dans ASP.NET Core API web.
Par défaut, la méthode d’assistance intégrée ControllerBase.Ok retourne des données au format JSON :
[HttpGet]
public IActionResult Get() =>
Ok(_todoItemStore.GetList());
L’exemple de code retourne une liste d’éléments todo. L’utilisation des outils de développement du navigateur F12 ou http-repl avec le code précédent affiche :
- En-tête de réponse contenant content-type:
application/json; charset=utf-8
. - En-têtes de la requête. Par exemple, l’en-tête
Accept
. L’en-têteAccept
est ignoré par le code précédent.
Pour retourner des données mises en forme en texte brut, utilisez ContentResult et le helper Content :
[HttpGet("Version")]
public ContentResult GetVersion() =>
Content("v1.0.0");
Dans le code précédent, le Content-Type
retourné est text/plain
.
Pour les actions avec plusieurs types de retour, retournez IActionResult
. Par exemple, lorsque vous retournez différents codes d’état HTTP en fonction du résultat de l’opération.
Négociation de contenu
La négociation du contenu a lieu lorsque le client spécifie un en-tête Accepter. Le format par défaut utilisé par ASP.NET Core est JSON. La négociation de contenu est la suivante :
- Implémenté par ObjectResult.
- Intégré aux résultats d’action d’état spécifiques au code retournés par les méthodes d’assistance. Les méthodes d’assistance des résultats de l’action sont basées sur
ObjectResult
.
Lorsqu’un type de modèle est retourné, le type de retour est ObjectResult
.
La méthode d’action suivante utilise les méthodes helper Ok
et NotFound
:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
Par défaut, ASP.NET Core prend en charge les types de médias suivants :
application/json
text/json
text/plain
Des outils tels que Fiddler ou curl peuvent définir l’en-tête de requête Accept
pour spécifier le format de retour. Lorsque l’en-tête Accept
contient un type que le serveur prend en charge, ce type est retourné. La section suivante montre comment ajouter des formateurs supplémentaires.
Les actions du contrôleur peuvent retourner des POCO (objets CLR anciens bruts). Lorsqu’un POCO est retourné, le runtime crée automatiquement un ObjectResult
qui encapsule l’objet. Le client obtient l’objet sérialisé mis en forme. Si l’objet retourné est null
, une 204 No Content
réponse est retournée.
L’exemple suivant retourne un type d’objet :
[HttpGet("{id:long}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
Dans le code précédent, une demande d’élément todo valide retourne une réponse 200 OK
. Une demande d’élément todo non valide retourne une réponse 204 No Content
.
En-tête Accepter.
La négociation de contenu intervient lorsqu’un en-tête Accept
apparaît dans la requête. Lorsqu’une demande contient un en-tête d’acceptation, ASP.NET Core :
- Énumère les types de médias dans l’en-tête d’acceptation dans l’ordre de préférence.
- Tente de trouver un formateur capable de produire une réponse dans l’un des formats spécifiés.
Si aucun formateur ne peut répondre à la demande du client, ASP.NET Core :
- Retourne
406 Not Acceptable
si MvcOptions.ReturnHttpNotAcceptable est défini surtrue
, ou - - Tente de trouver le premier formateur qui peut produire une réponse.
Si aucun formateur n'est configuré pour le format demandé, le premier formateur capable de formater l'objet est utilisé. Si aucun en-tête Accept
n’apparaît dans la demande :
- Le premier formateur capable de gérer l’objet est utilisé pour sérialiser la réponse.
- Il n’y a pas de négociation en cours. Le serveur détermine le format à retourner.
Si l'en-tête Accepter contient */*
, l'en-tête est ignoré à moins que RespectBrowserAcceptHeader
ne soit réglé sur true sur MvcOptions.
Navigateurs et négociation de contenu
Contrairement aux clients API classiques, les navigateurs web fournissent des en-têtes Accept
. Les navigateurs web spécifient de nombreux formats, y compris des caractères génériques. Par défaut, lorsque l’infrastructure détecte que la demande provient d’un navigateur :
- L’en-tête
Accept
est ignoré. - Le contenu est retourné dans JSON, sauf configuration contraire.
Cette approche offre une expérience plus cohérente entre les navigateurs lors de la consommation d’API.
Pour configurer une application afin de respecter les en-têtes d’acceptation du navigateur, définissez la propriété RespectBrowserAcceptHeader sur true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
Configurer les formateurs
Les applications qui doivent prendre en charge des formats supplémentaires peuvent ajouter les packages NuGet appropriés et configurer la prise en charge. Il existe des formateurs distincts pour les entrées et pour les sorties. Les formateurs d’entrée sont utilisés par la liaison de modèle. Les formateurs de sortie sont utilisés pour mettre en forme les réponses. Pour plus d’informations sur la création d’un formateur personnalisé, consultez Formateurs personnalisés.
Ajouter la prise en charge du format XML
Pour configurer des formateurs XML implémentés à l’aide de XmlSerializer, appelez AddXmlSerializerFormatters :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
Lors de l’utilisation du code précédent, les méthodes de contrôleur retournent le format approprié en fonction de l’en-tête de la demande Accept
.
Configurer des formateurs basés sur System.Text.Json
Pour configurer des fonctionnalités pour les System.Text.Json
formateurs basés sur la base, utilisez Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. Le code en surbrillance suivant configure la mise en forme PascalCase au lieu de la mise en forme camelCase par défaut :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
La méthode d’action suivante appelle ControllerBase.Problem pour créer une réponse ProblemDetails :
[HttpGet("Error")]
public IActionResult GetError() =>
Problem("Something went wrong.");
Une réponse ProblemDetails
est toujours camelCase, même lorsque l’application définit le format sur PascalCase. ProblemDetails
suit la RFC 7807, qui spécifie des minuscules.
Pour configurer les options de sérialisation de sortie pour des actions spécifiques, utilisez JsonResult
. Par exemple :
[HttpGet]
public IActionResult Get() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions
{
PropertyNamingPolicy = null
});
Ajout de la prise en charge du format JSON basé sur Newtonsoft.Json
Les formateurs JSON par défaut utilisent System.Text.Json
. Pour utiliser les Newtonsoft.Json
formateurs basés sur les données, installez le package NuGet et configurez-le Microsoft.AspNetCore.Mvc.NewtonsoftJson
dans Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
Dans le code précédent, l’appel à AddNewtonsoftJson
configure les fonctionnalités d’API Web, MVC et Razor Pages suivantes pour utiliser Newtonsoft.Json
:
- Formateurs d’entrée et de sortie qui lisent et écrivent JSON
- JsonResult
- Patch JSON
- IJsonHelper
- TempData
Certaines fonctionnalités peuvent ne pas fonctionnent correctement avec des formateurs basés sur System.Text.Json
et requièrent une référence aux formateurs basés sur Newtonsoft.Json
. Continuez à utiliser les Newtonsoft.Json
formateurs basés sur les données lorsque l’application :
- Utilise des attributs
Newtonsoft.Json
. Par exemple,[JsonProperty]
ou[JsonIgnore]
. - Personnalise les paramètres de sérialisation.
- S’appuie sur les fonctionnalités qui fournissent
Newtonsoft.Json
.
Pour configurer des fonctionnalités pour les Newtonsoft.Json
formateurs basés sur la base, utilisez SerializerSettings :
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
Pour configurer les options de sérialisation de sortie pour des actions spécifiques, utilisez JsonResult
. Par exemple :
[HttpGet]
public IActionResult GetNewtonsoftJson() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver()
});
Spécifier un format
Pour restreindre les formats de réponse, appliquez le filtre [Produces]
. Comme la plupart des filtres, [Produces]
peut être appliqué à l’action, au contrôleur ou à l’étendue globale :
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
Le filtre précédent [Produces]
:
- Force toutes les actions au sein du contrôleur à retourner des réponses au format JSON pour les POCOs (objets CLR anciens bruts) ou ObjectResult et ses types dérivés.
- Retourne des réponses au format JSON même si d’autres formateurs sont configurés et que le client spécifie un autre format.
Pour plus d’informations, consultez Filtres.
Formateurs pour des cas spéciaux
Certains cas spéciaux sont implémentés avec des formateurs intégrés. Par défaut, les types de retour string
sont formatés en text/plain (text/html si c’est demandé via l’en-tête Accept
). Vous pouvez éviter ce comportement en supprimant StringOutputFormatter. Les formateurs sont supprimés dans Program.cs
. Les actions dont le type de retour est un objet de modèle renvoient 204 No Content
lorsqu'elles renvoient null
. Vous pouvez éviter ce comportement en supprimant HttpNoContentOutputFormatter. Le code suivant supprime StringOutputFormatter
et HttpNoContentOutputFormatter
.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
Sans StringOutputFormatter
, les formats de formateur JSON intégrés string
retournent des types. Si le formateur JSON intégré est supprimé et qu’un formateur XML est disponible, le formateur XML met en forme les types de retour string
. Sinon, les types de retour string
retournent 406 Not Acceptable
.
Sans HttpNoContentOutputFormatter
, les objets null sont mis en forme avec le formateur configuré. Par exemple :
- Le formateur JSON retourne une réponse avec un corps
null
. - Le formateur XML retourne un élément XML vide avec l’ensemble d’attributs
xsi:nil="true"
.
Mappages d’URL de format de réponse
Les clients peuvent demander un format particulier dans le cadre de l’URL, par exemple :
- Dans la chaîne de requête ou une partie du chemin d’accès.
- En utilisant une extension de fichier spécifique au format, telle que .xml ou .json.
Le mappage du chemin de la requête doit être spécifié dans la route utilisée par l’API. Par exemple :
[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);
L’itinéraire précédent permet de spécifier le format demandé à l’aide d’une extension de fichier facultative. L’attribut [FormatFilter]
vérifie l’existence de la valeur du format dans RouteData
et mappe le format de la réponse au formateur approprié lors de la création de la réponse.
Route | Formateur |
---|---|
/api/todoitems/5 |
Le formateur de sortie par défaut |
/api/todoitems/5.json |
Le formateur JSON (s’il est configuré) |
/api/todoitems/5.xml |
Le formateur XML (s’il est configuré) |
Désérialisation polymorphe
Les fonctionnalités intégrées fournissent une gamme limitée de sérialisation polymorphe, mais aucune prise en charge de la désérialisation. La désérialisation nécessite un convertisseur personnalisé. Pour obtenir un exemple complet de désérialisation polymorphe, consultez Désérialisation polymorphe .
Ressources supplémentaires
ASP.NET Core MVC prend en charge la mise en forme des données de réponse. Les données de réponse peuvent être mises en forme à l’aide de formats spécifiques ou en réponse au format demandé par le client.
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Résultats d’une action spécifique à un format
Certains types de résultats d’action sont spécifiques à un format particulier, comme JsonResult et ContentResult. Les actions peuvent retourner des résultats mis en forme dans un format particulier, quelles que soient les préférences du client. Par exemple, le retour JsonResult
renvoie des données au format JSON. Retourne ContentResult
ou une chaîne retourne des données de chaîne au format texte brut.
Une action n’est pas nécessaire pour retourner un type spécifique. ASP.NET Core prend en charge toute valeur de retour d’objet. Les résultats des actions qui renvoient des objets qui ne sont pas des typesIActionResult sont sérialisés en utilisant l'implémentation IOutputFormatter appropriée. Pour plus d’informations, consultez Types de retour d’action de contrôleur dans ASP.NET Core API web.
La méthode d’assistance intégrée Ok retourne des données au format JSON :
// GET: api/authors
[HttpGet]
public ActionResult Get()
{
return Ok(_authors.List());
}
L’exemple de téléchargement retourne la liste des auteurs. L’utilisation des outils de développement du navigateur F12 ou http-repl avec le code précédent :
- L’en-tête de réponse contenant content-type:
application/json; charset=utf-8
est affiché. - Les en-têtes de requête sont affichés. Par exemple, l’en-tête
Accept
. L’en-têteAccept
est ignoré par le code précédent.
Pour retourner des données mises en forme en texte brut, utilisez ContentResult et le helper Content :
// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
return Content("An API listing authors of docs.asp.net.");
}
Dans le code précédent, le Content-Type
retourné est text/plain
. Le retour d’une chaîne fournit Content-Type
:text/plain
// GET api/authors/version
[HttpGet("version")]
public string Version()
{
return "Version 1.0.0";
}
Pour les actions avec plusieurs types de retour, retournez IActionResult
. Par exemple, le retour de différents codes de status HTTP en fonction du résultat des opérations effectuées.
Négociation de contenu
La négociation du contenu a lieu lorsque le client spécifie un en-tête Accepter. Le format par défaut utilisé par ASP.NET Core est JSON. La négociation de contenu est la suivante :
- Implémenté par ObjectResult.
- Intégré aux résultats d’action d’état spécifiques au code retournés par les méthodes d’assistance. Les méthodes d’assistance des résultats de l’action sont basées sur
ObjectResult
.
Lorsqu’un type de modèle est retourné, le type de retour est ObjectResult
.
La méthode d’action suivante utilise les méthodes helper Ok
et 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);
}
Par défaut, ASP.NET Core prend en charge application/json
les types multimédias , text/json
et text/plain
. Des outils comme Fiddler ou http-repl peuvent définir l’en-tête de requête Accept
pour spécifier le format de retour. Lorsque l’en-tête Accept
contient un type que le serveur prend en charge, ce type est retourné. La section suivante montre comment ajouter des formateurs supplémentaires.
Les actions du contrôleur peuvent retourner des POCO (objets CLR anciens bruts). Lorsqu’un POCO est retourné, le runtime crée automatiquement un ObjectResult
qui encapsule l’objet. Le client obtient l’objet sérialisé mis en forme. Si l’objet retourné est null
, une 204 No Content
réponse est retournée.
Retour d’un type d’objet :
// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
return _authors.GetByAlias(alias);
}
Dans le code précédent, une demande d'alias d'auteur valide renvoie une réponse 200 OK
contenant les données de l'auteur. Une demande d’alias non valide retourne une réponse 204 No Content
.
En-tête Accepter.
La négociation de contenu intervient lorsqu’un en-tête Accept
apparaît dans la requête. Lorsqu’une demande contient un en-tête d’acceptation, ASP.NET Core :
- Énumère les types de médias dans l’en-tête d’acceptation dans l’ordre de préférence.
- Tente de trouver un formateur capable de produire une réponse dans l’un des formats spécifiés.
Si aucun formateur ne peut répondre à la demande du client, ASP.NET Core :
- Retourne
406 Not Acceptable
si MvcOptions.ReturnHttpNotAcceptable est défini surtrue
, ou - - Tente de trouver le premier formateur qui peut produire une réponse.
Si aucun formateur n'est configuré pour le format demandé, le premier formateur capable de formater l'objet est utilisé. Si aucun en-tête Accept
n’apparaît dans la demande :
- Le premier formateur capable de gérer l’objet est utilisé pour sérialiser la réponse.
- Il n’y a pas de négociation en cours. Le serveur détermine le format à retourner.
Si l'en-tête Accepter contient */*
, l'en-tête est ignoré à moins que RespectBrowserAcceptHeader
ne soit réglé sur true sur MvcOptions.
Navigateurs et négociation de contenu
Contrairement aux clients API classiques, les navigateurs web fournissent des en-têtes Accept
. Les navigateurs web spécifient de nombreux formats, y compris des caractères génériques. Par défaut, lorsque l’infrastructure détecte que la demande provient d’un navigateur :
- L’en-tête
Accept
est ignoré. - Le contenu est retourné dans JSON, sauf configuration contraire.
Cette approche offre une expérience plus cohérente entre les navigateurs lors de la consommation d’API.
Pour configurer une application de manière à respecter les en-têtes d’acceptation du navigateur, définissez RespectBrowserAcceptHeader sur true
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
});
}
Configurer les formateurs
Les applications qui doivent prendre en charge des formats supplémentaires peuvent ajouter les packages NuGet appropriés et configurer la prise en charge. Il existe des formateurs distincts pour les entrées et pour les sorties. Les formateurs d’entrée sont utilisés par la liaison de modèle. Les formateurs de sortie sont utilisés pour mettre en forme les réponses. Pour plus d’informations sur la création d’un formateur personnalisé, consultez Formateurs personnalisés.
Ajouter la prise en charge du format XML
Les formateurs XML implémentés avec XmlSerializer peuvent être configurés en appelant AddXmlSerializerFormatters :
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddXmlSerializerFormatters();
}
Le code précédent sérialise les résultats à l’aide de XmlSerializer
.
Lors de l’utilisation du code précédent, les méthodes de contrôleur retournent le format approprié en fonction de l’en-tête de la demande Accept
.
Configurer des formateurs basés sur System.Text.Json
Les fonctionnalités pour les formateurs basés sur System.Text.Json
peuvent être configurées avec Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. La mise en forme par défaut est camelCase. Le code mis en surbrillance suivant définit la mise en forme PascalCase :
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null);
}
La méthode d’action suivante appelle ControllerBase.Problem pour créer une réponse ProblemDetails :
[HttpGet("error")]
public IActionResult GetError()
{
return Problem("Something went wrong!");
}
Dans le code précédent :
https://localhost:5001/WeatherForecast/temperature
retourne PascalCase.https://localhost:5001/WeatherForecast/error
retourne camelCase. La réponse d’erreur est toujours camelCase, même lorsque l’application définit le format sur PascalCase.ProblemDetails
suit la RFC 7807, qui spécifie la minuscule
Le code suivant définit PascalCase et ajoute un convertisseur personnalisé :
services.AddControllers().AddJsonOptions(options =>
{
// Use the default property (Pascal) casing.
options.JsonSerializerOptions.PropertyNamingPolicy = null;
// Configure a custom converter.
options.JsonSerializerOptions.Converters.Add(new MyCustomJsonConverter());
});
Les options de sérialisation de sortie, par action, peuvent être configurées à l’aide de JsonResult
. Par exemple :
public IActionResult Get()
{
return Json(model, new JsonSerializerOptions
{
WriteIndented = true,
});
}
Ajouter la prise en charge du format JSON basé sur Newtonsoft.Json
Les formateurs JSON par défaut sont basés sur System.Text.Json
. Une prise en charge des fonctionnalités et des formateurs basés sur Newtonsoft.Json
est disponible en installant le package NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson
et en le configurant dans Startup.ConfigureServices
.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
}
Dans le code précédent, l’appel à AddNewtonsoftJson
configure les fonctionnalités d’API Web, MVC et Razor Pages suivantes pour utiliser Newtonsoft.Json
:
- Formateurs d’entrée et de sortie qui lisent et écrivent JSON
- JsonResult
- Patch JSON
- IJsonHelper
- TempData
Certaines fonctionnalités peuvent ne pas fonctionnent correctement avec des formateurs basés sur System.Text.Json
et requièrent une référence aux formateurs basés sur Newtonsoft.Json
. Continuez à utiliser les Newtonsoft.Json
formateurs basés sur les données lorsque l’application :
- Utilise des attributs
Newtonsoft.Json
. Par exemple,[JsonProperty]
ou[JsonIgnore]
. - Personnalise les paramètres de sérialisation.
- S’appuie sur les fonctionnalités qui fournissent
Newtonsoft.Json
.
Les fonctionnalités pour les formateurs basés sur Newtonsoft.Json
peuvent être configurées avec 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());
});
Les options de sérialisation de sortie, par action, peuvent être configurées à l’aide de JsonResult
. Par exemple :
public IActionResult Get()
{
return Json(model, new JsonSerializerSettings
{
Formatting = Formatting.Indented,
});
}
Spécifier un format
Pour restreindre les formats de réponse, appliquez le filtre [Produces]
. Comme la plupart des filtres, [Produces]
peut être appliqué à l’action, au contrôleur ou à l’étendue globale :
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{
Le filtre précédent [Produces]
:
- Force toutes les actions au sein du contrôleur à retourner des réponses au format JSON pour les POCOs (objets CLR anciens bruts) ou ObjectResult et ses types dérivés.
- Si d’autres formateurs sont configurés et que le client spécifie un autre format, JSON est retourné.
Pour plus d’informations, consultez Filtres.
Formateurs pour des cas spéciaux
Certains cas spéciaux sont implémentés avec des formateurs intégrés. Par défaut, les types de retour string
sont formatés en text/plain (text/html si c’est demandé via l’en-tête Accept
). Vous pouvez éviter ce comportement en supprimant StringOutputFormatter. Les formateurs sont supprimés dans la méthode ConfigureServices
. Les actions dont le type de retour est un objet de modèle renvoient 204 No Content
lorsqu'elles renvoient null
. Vous pouvez éviter ce comportement en supprimant HttpNoContentOutputFormatter. Le code suivant supprime StringOutputFormatter
et HttpNoContentOutputFormatter
.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
// requires using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
}
Sans StringOutputFormatter
, les formats de formateur JSON intégrés string
retournent des types. Si le formateur JSON intégré est supprimé et qu’un formateur XML est disponible, le formateur XML met en forme les types de retour string
. Sinon, les types de retour string
retournent 406 Not Acceptable
.
Sans HttpNoContentOutputFormatter
, les objets null sont mis en forme avec le formateur configuré. Par exemple :
- Le formateur JSON retourne une réponse avec un corps
null
. - Le formateur XML retourne un élément XML vide avec l’ensemble d’attributs
xsi:nil="true"
.
Mappages d’URL de format de réponse
Les clients peuvent demander un format particulier dans le cadre de l’URL, par exemple :
- Dans la chaîne de requête ou une partie du chemin d’accès.
- En utilisant une extension de fichier spécifique au format, telle que .xml ou .json.
Le mappage du chemin de la requête doit être spécifié dans la route utilisée par l’API. Par exemple :
[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
[HttpGet("{id}.{format?}")]
public Product Get(int id)
{
L’itinéraire précédent permet de spécifier le format demandé comme d’une extension de fichier facultative. L’attribut [FormatFilter]
vérifie l’existence de la valeur du format dans RouteData
et mappe le format de la réponse au formateur approprié lors de la création de la réponse.
Route | Formateur |
---|---|
/api/products/5 |
Le formateur de sortie par défaut |
/api/products/5.json |
Le formateur JSON (s’il est configuré) |
/api/products/5.xml |
Le formateur XML (s’il est configuré) |
ASP.NET Core MVC prend en charge la mise en forme des données de réponse, à l’aide de formats spécifiés ou en réponse à la demande d’un client.
Résultats d’une action spécifique à un format
Certains types de résultats d’action sont spécifiques à un format particulier, comme JsonResult et ContentResult. Les actions peuvent retourner des résultats qui utilisent toujours un format spécifié, ignorant la demande d’un client pour un autre format. Par exemple, le renvoi de JsonResult
renvoie des données au format JSON et le renvoi de ContentResult
renvoie des données sous forme de chaîne de caractères au format texte brut.
Une action n’est pas nécessaire pour retourner un type spécifique. ASP.NET Core prend en charge toute valeur de retour d’objet. Les résultats des actions qui renvoient des objets qui ne sont pas des typesIActionResult sont sérialisés en utilisant l'implémentation IOutputFormatter appropriée. Pour plus d’informations, consultez Types de retour d’action de contrôleur dans ASP.NET Core API web.
Par défaut, la méthode d’assistance intégrée ControllerBase.Ok retourne des données au format JSON :
[HttpGet]
public IActionResult Get()
=> Ok(_todoItemStore.GetList());
L’exemple de code retourne une liste d’éléments todo. L’utilisation des outils de développement du navigateur F12 ou http-repl avec le code précédent affiche :
- En-tête de réponse contenant content-type:
application/json; charset=utf-8
. - En-têtes de la requête. Par exemple, l’en-tête
Accept
. L’en-têteAccept
est ignoré par le code précédent.
Pour retourner des données mises en forme en texte brut, utilisez ContentResult et le helper Content :
[HttpGet("Version")]
public ContentResult GetVersion()
=> Content("v1.0.0");
Dans le code précédent, le Content-Type
retourné est text/plain
.
Pour les actions avec plusieurs types de retour, retournez IActionResult
. Par exemple, lorsque vous retournez différents codes d’état HTTP en fonction du résultat de l’opération.
Négociation de contenu
La négociation du contenu a lieu lorsque le client spécifie un en-tête Accepter. Le format par défaut utilisé par ASP.NET Core est JSON. La négociation de contenu est la suivante :
- Implémenté par ObjectResult.
- Intégré aux résultats d’action d’état spécifiques au code retournés par les méthodes d’assistance. Les méthodes d’assistance des résultats de l’action sont basées sur
ObjectResult
.
Lorsqu’un type de modèle est retourné, le type de retour est ObjectResult
.
La méthode d’action suivante utilise les méthodes helper Ok
et NotFound
:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
Par défaut, ASP.NET Core prend en charge les types de médias suivants :
application/json
text/json
text/plain
Des outils comme Fiddler ou http-repl peuvent définir l’en-tête de requête Accept
pour spécifier le format du retour. Lorsque l’en-tête Accept
contient un type que le serveur prend en charge, ce type est retourné. La section suivante montre comment ajouter des formateurs supplémentaires.
Les actions du contrôleur peuvent retourner des POCO (objets CLR anciens bruts). Lorsqu’un POCO est retourné, le runtime crée automatiquement un ObjectResult
qui encapsule l’objet. Le client obtient l’objet sérialisé mis en forme. Si l’objet retourné est null
, une 204 No Content
réponse est retournée.
L’exemple suivant retourne un type d’objet :
[HttpGet("{id:long}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
Dans le code précédent, une demande d’élément todo valide retourne une réponse 200 OK
. Une demande d’élément todo non valide retourne une réponse 204 No Content
.
En-tête Accepter.
La négociation de contenu intervient lorsqu’un en-tête Accept
apparaît dans la requête. Lorsqu’une demande contient un en-tête d’acceptation, ASP.NET Core :
- Énumère les types de médias dans l’en-tête d’acceptation dans l’ordre de préférence.
- Tente de trouver un formateur capable de produire une réponse dans l’un des formats spécifiés.
Si aucun formateur ne peut répondre à la demande du client, ASP.NET Core :
- Retourne
406 Not Acceptable
si MvcOptions.ReturnHttpNotAcceptable est défini surtrue
, ou - - Tente de trouver le premier formateur qui peut produire une réponse.
Si aucun formateur n'est configuré pour le format demandé, le premier formateur capable de formater l'objet est utilisé. Si aucun en-tête Accept
n’apparaît dans la demande :
- Le premier formateur capable de gérer l’objet est utilisé pour sérialiser la réponse.
- Il n’y a pas de négociation en cours. Le serveur détermine le format à retourner.
Si l'en-tête Accepter contient */*
, l'en-tête est ignoré à moins que RespectBrowserAcceptHeader
ne soit réglé sur true sur MvcOptions.
Navigateurs et négociation de contenu
Contrairement aux clients API classiques, les navigateurs web fournissent des en-têtes Accept
. Les navigateurs web spécifient de nombreux formats, y compris des caractères génériques. Par défaut, lorsque l’infrastructure détecte que la demande provient d’un navigateur :
- L’en-tête
Accept
est ignoré. - Le contenu est retourné dans JSON, sauf configuration contraire.
Cette approche offre une expérience plus cohérente entre les navigateurs lors de la consommation d’API.
Pour configurer une application afin de respecter les en-têtes d’acceptation du navigateur, définissez la propriété RespectBrowserAcceptHeader sur true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
Configurer les formateurs
Les applications qui doivent prendre en charge des formats supplémentaires peuvent ajouter les packages NuGet appropriés et configurer la prise en charge. Il existe des formateurs distincts pour les entrées et pour les sorties. Les formateurs d’entrée sont utilisés par la liaison de modèle. Les formateurs de sortie sont utilisés pour mettre en forme les réponses. Pour plus d’informations sur la création d’un formateur personnalisé, consultez Formateurs personnalisés.
Ajouter la prise en charge du format XML
Pour configurer des formateurs XML implémentés à l’aide de XmlSerializer, appelez AddXmlSerializerFormatters :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
Lors de l’utilisation du code précédent, les méthodes de contrôleur retournent le format approprié en fonction de l’en-tête de la demande Accept
.
Configurer des formateurs basés sur System.Text.Json
Pour configurer des fonctionnalités pour les System.Text.Json
formateurs basés sur la base, utilisez Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. Le code en surbrillance suivant configure la mise en forme PascalCase au lieu de la mise en forme camelCase par défaut :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
Pour configurer les options de sérialisation de sortie pour des actions spécifiques, utilisez JsonResult. Par exemple :
[HttpGet]
public IActionResult Get()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions { PropertyNamingPolicy = null });
Ajout de la prise en charge du format JSON basé sur Newtonsoft.Json
Les formateurs JSON par défaut utilisent System.Text.Json
. Pour utiliser les Newtonsoft.Json
formateurs basés sur les données, installez le package NuGet et configurez-le Microsoft.AspNetCore.Mvc.NewtonsoftJson
dans Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
Dans le code précédent, l’appel à AddNewtonsoftJson
configure les fonctionnalités d’API Web, MVC et Razor Pages suivantes pour utiliser Newtonsoft.Json
:
- Formateurs d’entrée et de sortie qui lisent et écrivent JSON
- JsonResult
- Patch JSON
- IJsonHelper
- TempData
Certaines fonctionnalités peuvent ne pas fonctionnent correctement avec des formateurs basés sur System.Text.Json
et requièrent une référence aux formateurs basés sur Newtonsoft.Json
. Continuez à utiliser les Newtonsoft.Json
formateurs basés sur les données lorsque l’application :
- Utilise des attributs
Newtonsoft.Json
. Par exemple,[JsonProperty]
ou[JsonIgnore]
. - Personnalise les paramètres de sérialisation.
- S’appuie sur les fonctionnalités qui fournissent
Newtonsoft.Json
.
Pour configurer des fonctionnalités pour les Newtonsoft.Json
formateurs basés sur la base, utilisez SerializerSettings :
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
Pour configurer les options de sérialisation de sortie pour des actions spécifiques, utilisez JsonResult
. Par exemple :
[HttpGet]
public IActionResult GetNewtonsoftJson()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });
Format ProblemDetails
et réponses ValidationProblemDetails
La méthode d’action suivante appelle ControllerBase.Problem pour créer une réponse ProblemDetails :
[HttpGet("Error")]
public IActionResult GetError()
=> Problem("Something went wrong.");
Une réponse ProblemDetails
est toujours camelCase, même lorsque l’application définit le format sur PascalCase. ProblemDetails
suit la RFC 7807, qui spécifie des minuscules.
Lorsque l’attribut [ApiController]
est appliqué à une classe de contrôleur, le contrôleur crée une réponse ValidationProblemDetails en cas d’échec de la validation du modèle. Cette réponse inclut un dictionnaire qui utilise les noms de propriétés du modèle comme clés d’erreur, sans modification. Par exemple, le modèle suivant inclut une propriété unique qui nécessite une validation :
public class SampleModel
{
[Range(1, 10)]
public int Value { get; set; }
}
Par défaut, la réponse ValidationProblemDetails
retournée lorsque la propriété Value
n’est pas valide utilise une clé d’erreur de Value
, comme illustré dans l’exemple suivant :
{
"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."
]
}
}
Pour mettre en forme les noms de propriétés utilisés comme clés d’erreur, ajoutez une implémentation de IMetadataDetailsProvider à la collection MvcOptions.ModelMetadataDetailsProviders. L’exemple suivant ajoute une System.Text.Json
implémentation basée sur SystemTextJsonValidationMetadataProvider
, qui met en forme les noms de propriétés en tant que camelCase par défaut :
builder.Services.AddControllers();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new SystemTextJsonValidationMetadataProvider());
});
SystemTextJsonValidationMetadataProvider
accepte également une implémentation de JsonNamingPolicy dans son constructeur, qui spécifie une stratégie de nommage personnalisée pour la mise en forme des noms de propriétés.
Pour définir un nom personnalisé pour une propriété dans un modèle, utilisez l’attribut [JsonPropertyName] sur la propriété :
public class SampleModel
{
[Range(1, 10)]
[JsonPropertyName("sampleValue")]
public int Value { get; set; }
}
La réponse ValidationProblemDetails
retournée pour le modèle précédent lorsque la propriété Value
n’est pas valide utilise une clé d’erreur de sampleValue
, comme illustré dans l’exemple suivant :
{
"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."
]
}
}
Pour mettre en forme la ValidationProblemDetails
réponse à l’aide de Newtonsoft.Json
, utilisez NewtonsoftJsonValidationMetadataProvider
:
builder.Services.AddControllers()
.AddNewtonsoftJson();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new NewtonsoftJsonValidationMetadataProvider());
});
Par défaut, NewtonsoftJsonValidationMetadataProvider
met en forme les noms de propriétés comme camelCase. NewtonsoftJsonValidationMetadataProvider
accepte également une implémentation de NamingPolicy
dans son constructeur, qui spécifie une stratégie de nommage personnalisée pour la mise en forme des noms de propriétés. Pour définir un nom personnalisé pour une propriété dans un modèle, utilisez l’attribut [JsonProperty]
.
Spécifier un format
Pour restreindre les formats de réponse, appliquez le filtre [Produces]
. Comme la plupart des filtres, [Produces]
peut être appliqué à l’action, au contrôleur ou à l’étendue globale :
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
Le filtre précédent [Produces]
:
- Force toutes les actions au sein du contrôleur à retourner des réponses au format JSON pour les POCOs (objets CLR anciens bruts) ou ObjectResult et ses types dérivés.
- Retourne des réponses au format JSON même si d’autres formateurs sont configurés et que le client spécifie un autre format.
Pour plus d’informations, consultez Filtres.
Formateurs pour des cas spéciaux
Certains cas spéciaux sont implémentés avec des formateurs intégrés. Par défaut, les types de retour string
sont formatés en text/plain (text/html si c’est demandé via l’en-tête Accept
). Vous pouvez éviter ce comportement en supprimant StringOutputFormatter. Les formateurs sont supprimés dans Program.cs
. Les actions dont le type de retour est un objet de modèle renvoient 204 No Content
lorsqu'elles renvoient null
. Vous pouvez éviter ce comportement en supprimant HttpNoContentOutputFormatter. Le code suivant supprime StringOutputFormatter
et HttpNoContentOutputFormatter
.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
Sans StringOutputFormatter
, les formats de formateur JSON intégrés string
retournent des types. Si le formateur JSON intégré est supprimé et qu’un formateur XML est disponible, le formateur XML met en forme les types de retour string
. Sinon, les types de retour string
retournent 406 Not Acceptable
.
Sans HttpNoContentOutputFormatter
, les objets null sont mis en forme avec le formateur configuré. Par exemple :
- Le formateur JSON retourne une réponse avec un corps
null
. - Le formateur XML retourne un élément XML vide avec l’ensemble d’attributs
xsi:nil="true"
.
Mappages d’URL de format de réponse
Les clients peuvent demander un format particulier dans le cadre de l’URL, par exemple :
- Dans la chaîne de requête ou une partie du chemin d’accès.
- En utilisant une extension de fichier spécifique au format, telle que .xml ou .json.
Le mappage du chemin de la requête doit être spécifié dans la route utilisée par l’API. Par exemple :
[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);
L’itinéraire précédent permet de spécifier le format demandé à l’aide d’une extension de fichier facultative. L’attribut [FormatFilter]
vérifie l’existence de la valeur du format dans RouteData
et mappe le format de la réponse au formateur approprié lors de la création de la réponse.
Route | Formateur |
---|---|
/api/todoitems/5 |
Le formateur de sortie par défaut |
/api/todoitems/5.json |
Le formateur JSON (s’il est configuré) |
/api/todoitems/5.xml |
Le formateur XML (s’il est configuré) |
Désérialisation polymorphe
Les fonctionnalités intégrées fournissent une gamme limitée de sérialisation polymorphe, mais aucune prise en charge de la désérialisation. La désérialisation nécessite un convertisseur personnalisé. Pour obtenir un exemple complet de désérialisation polymorphe, consultez Désérialisation polymorphe .