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 JsonResult renvoie des JSdonnées au format ON et le retour ContentResult renvoie 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.

Par défaut, la méthode ControllerBase.Ok d’assistance intégrée retourne JSdes données au format ON :

[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ête Accept 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 MVC 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 Postman 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 :

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.Jsonformateurs 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 ON basé Newtonsoft.Jsonsur l’ajout JS

Les formateurs ON par défaut JSutilisent System.Text.Json. Pour utiliser les Newtonsoft.Jsonformateurs 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 :

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.Jsonformateurs 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.Jsonformateurs 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 JSdes réponses au format ON pour les POCOs (objets CLR anciens bruts) ou et ObjectResult ses types dérivés.
  • Retourne JSdes réponses au format ON 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 JS de formateur ON intégrés stringretournent des types. Si le formateur JSON intégré est supprimé et qu’un formateur XML est disponible, le formateur XML met en forme string des types de retour. 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 JSformateur ON retourne une réponse avec un corps de 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 Ok d’assistance intégrée 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 s’affiche.
  • Les en-têtes de requête sont affichés. Par exemple, l’en-tête Accept. L’en-tête Accept 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 MVC 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/jsonles types multimédias , text/jsonet 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 :

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 ON par défaut JSsont 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 :

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.Jsonformateurs 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 JSdes réponses au format ON pour les POCOs (objets CLR anciens bruts) ou et ObjectResult 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 JS de formateur ON intégrés stringretournent des types. Si le formateur JSON intégré est supprimé et qu’un formateur XML est disponible, le formateur XML met en forme string des types de retour. 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 JSformateur ON retourne une réponse avec un corps de 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 JsonResult renvoie des JSdonnées au format ON et le retour ContentResult renvoie 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.

Par défaut, la méthode ControllerBase.Ok d’assistance intégrée retourne JSdes données au format ON :

[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ête Accept 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 MVC 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 :

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.Jsonformateurs 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 ON basé Newtonsoft.Jsonsur l’ajout JS

Les formateurs ON par défaut JSutilisent System.Text.Json. Pour utiliser les Newtonsoft.Jsonformateurs 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 :

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.Jsonformateurs 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.Jsonformateurs 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.Jsonimplé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 ValidationProblemDetailsretourné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 JSdes réponses au format ON pour les POCOs (objets CLR anciens bruts) ou et ObjectResult ses types dérivés.
  • Retourne JSdes réponses au format ON 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 JS de formateur ON intégrés stringretournent des types. Si le formateur JSON intégré est supprimé et qu’un formateur XML est disponible, le formateur XML met en forme string des types de retour. 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 JSformateur ON retourne une réponse avec un corps de 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