Types de retour des actions du contrôleur dans l’API web ASP.NET CoreController action return types in ASP.NET Core Web API

Par Scott AddieBy Scott Addie

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)View or download sample code (how to download)

ASP.NET Core offre les options suivantes pour les types de retour des actions du contrôleur dans l’API web :ASP.NET Core offers the following options for Web API controller action return types:

Ce document décrit quel type de retour est le plus adapté en fonction de chaque cas.This document explains when it's most appropriate to use each return type.

Type spécifiqueSpecific type

L’action la plus simple retourne un type de données primitif ou complexe (par exemple, string ou un type d’objet personnalisé).The simplest action returns a primitive or complex data type (for example, string or a custom object type). Considérez l’action suivante, qui retourne une collection d’objets Product personnalisés :Consider the following action, which returns a collection of custom Product objects:

[HttpGet]
public IEnumerable<Product> Get()
{
    return _repository.GetProducts();
}

Sans conditions connues contre lesquelles une protection est nécessaire pendant l’exécution de l’action, le retour d’un type spécifique peut suffire.Without known conditions to safeguard against during action execution, returning a specific type could suffice. L’action précédente n’acceptant aucun paramètre, la validation des contraintes de paramètre n’est pas nécessaire.The preceding action accepts no parameters, so parameter constraints validation isn't needed.

Quand des conditions connues doivent être prises en compte dans une action, plusieurs chemins de retour sont introduits.When known conditions need to be accounted for in an action, multiple return paths are introduced. Dans ce cas, il est courant de combiner un type de retour ActionResult avec le type de retour primitif ou complexe.In such a case, it's common to mix an ActionResult return type with the primitive or complex return type. IActionResult ou ActionResult<T> sont nécessaires pour prendre en charge ce type d’action.Either IActionResult or ActionResult<T> are necessary to accommodate this type of action.

Type IActionResultIActionResult type

Le type de retour IActionResult est adapté quand plusieurs types de retour ActionResult sont possibles dans une action.The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. Les types ActionResult représentent différents codes d’état HTTP.The ActionResult types represent various HTTP status codes. Certains types de retour courants relevant de cette catégorie sont BadRequestResult (400), NotFoundResult (404) et OkObjectResult (200).Some common return types falling into this category are BadRequestResult (400), NotFoundResult (404), and OkObjectResult (200).

Comme il existe plusieurs types de retour et chemins dans l’action, une utilisation répandue de l’attribut [ProducesResponseType] est nécessaire.Because there are multiple return types and paths in the action, liberal use of the [ProducesResponseType] attribute is necessary. Cet attribut génère des détails plus descriptifs de la réponse pour les pages d’aide de l’API créées par des outils tels que Swagger.This attribute produces more descriptive response details for API help pages generated by tools like Swagger. [ProducesResponseType] indique les types connus et les codes d’état HTTP que l’action doit retourner.[ProducesResponseType] indicates the known types and HTTP status codes to be returned by the action.

Action synchroneSynchronous action

Considérez l’action synchrone suivante pour laquelle il existe deux types de retour possibles :Consider the following synchronous action in which there are two possible return types:

[HttpGet("{id}")]
[ProducesResponseType(typeof(Product), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return Ok(product);
}

Dans l’action précédente, un code d’état 404 est retourné quand le produit représenté par id n’existe pas dans le magasin de données sous-jacent.In the preceding action, a 404 status code is returned when the product represented by id doesn't exist in the underlying data store. La méthode d’assistance NotFound est appelée comme raccourci de return new NotFoundResult();.The NotFound helper method is invoked as a shortcut to return new NotFoundResult();. Si le produit existe, un objet Product représentant la charge utile est retourné avec un code d’état 200.If the product does exist, a Product object representing the payload is returned with a 200 status code. La méthode d’assistance Ok est appelée comme forme abrégée de return new OkObjectResult(product);.The Ok helper method is invoked as the shorthand form of return new OkObjectResult(product);.

Action asynchroneAsynchronous action

Considérez l’action asynchrone suivante pour laquelle il existe deux types de retour possibles :Consider the following asynchronous action in which there are two possible return types:

[HttpPost]
[ProducesResponseType(typeof(Product), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync([FromBody] Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

Dans le code précédent :In the preceding code:

  • Un code d’état 400 (BadRequest) est retourné par le runtime ASP.NET Core lorsque la description de produit contient « XYZ Widget ».A 400 status code (BadRequest) is returned by the ASP.NET Core runtime when the product description contains "XYZ Widget".
  • Un code d’état 201 est généré par la méthode CreatedAtAction lors de la création d’un produit.A 201 status code is generated by the CreatedAtAction method when a product is created. Dans ce chemin de code, l’objet Product est retourné.In this code path, the Product object is returned.

Par exemple, le modèle suivant indique que les requêtes doivent inclure les propriétés Name et Description.For example, the following model indicates that requests must include the Name and Description properties. Par conséquent, si vous n’indiquez pas Name et Description dans la requête, la validation du modèle échoue.Therefore, failure to provide Name and Description in the request causes model validation to fail.

public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Description { get; set; }
}

Si l’attribut [ApiController] dans ASP.NET Core 2.1 ou une version ultérieure est appliqué, les erreurs de validation de modèle entraînent un code d’état 400.If the [ApiController] attribute in ASP.NET Core 2.1 or later is applied, model validation errors result in a 400 status code. Pour plus d’informations, consultez Réponses HTTP 400 automatiques.For more information, see Automatic HTTP 400 responses.

Type ActionResult<T>ActionResult<T> type

ASP.NET Core 2.1 introduit le type de retour ActionResult<T> pour les actions du contrôleur dans l’API web.ASP.NET Core 2.1 introduces the ActionResult<T> return type for Web API controller actions. Il vous permet de retourner un type dérivant d’ActionResult ou de retourner un type spécifique.It enables you to return a type deriving from ActionResult or return a specific type. ActionResult<T> offre les avantages suivants par rapport au type IActionResult :ActionResult<T> offers the following benefits over the IActionResult type:

  • La propriété Type de l’attribut [ProducesResponseType] peut être exclue.The [ProducesResponseType] attribute's Type property can be excluded. Par exemple, [ProducesResponseType(200, Type = typeof(Product))] est simplifié en [ProducesResponseType(200)].For example, [ProducesResponseType(200, Type = typeof(Product))] is simplified to [ProducesResponseType(200)]. Le type de retour attendu pour l’action est déduit de T dans ActionResult<T>.The action's expected return type is instead inferred from the T in ActionResult<T>.
  • Des opérateurs de cast implicite prennent en charge la conversion de T et ActionResult en ActionResult<T>.Implicit cast operators support the conversion of both T and ActionResult to ActionResult<T>. T est converti en ObjectResult, ce qui signifie que return new ObjectResult(T); est simplifié en return T;.T converts to ObjectResult, which means return new ObjectResult(T); is simplified to return T;.

C# ne prend pas en charge les opérateurs de cast implicite sur les interfaces.C# doesn't support implicit cast operators on interfaces. Par conséquent, ActionResult<T> nécessite une conversion de l’interface en un type concret.Consequently, conversion of the interface to a concrete type is necessary to use ActionResult<T>. Par exemple, l’utilisation de IEnumerable dans l’exemple suivant ne fonctionne pas :For example, use of IEnumerable in the following example doesn't work:

[HttpGet]
public ActionResult<IEnumerable<Product>> Get()
{
    return _repository.GetProducts();
}

Pour corriger le code précédent, vous pouvez retourner _repository.GetProducts().ToList();.One option to fix the preceding code is to return _repository.GetProducts().ToList();.

La plupart des actions ont un type de retour spécifique.Most actions have a specific return type. Des conditions inattendues peuvent se produire pendant l’exécution d’une action, auquel cas le type spécifique n’est pas retourné.Unexpected conditions can occur during action execution, in which case the specific type isn't returned. Par exemple, le paramètre d’entrée d’une action peut entraîner l’échec de la validation du modèle.For example, an action's input parameter may fail model validation. Dans ce cas, il est courant de retourner le type ActionResult approprié à la place du type spécifique.In such a case, it's common to return the appropriate ActionResult type instead of the specific type.

Action synchroneSynchronous action

Considérez une action synchrone pour laquelle il existe deux types de retour possibles :Consider a synchronous action in which there are two possible return types:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return product;
}

Dans le code précédent, un code d’état 404 est retourné quand le produit n’existe pas dans la base de données.In the preceding code, a 404 status code is returned when the product doesn't exist in the database. Si le produit existe, l’objet Product correspondant est retourné.If the product does exist, the corresponding Product object is returned. Avant ASP.NET Core 2.1, la ligne return product; aurait indiqué return Ok(product);.Before ASP.NET Core 2.1, the return product; line would have been return Ok(product);.

Conseil

Depuis ASP.NET Core 2.1, l’inférence de la source de liaison de paramètre d’action est activée quand une classe de contrôleur est décorée avec l’attribut [ApiController].As of ASP.NET Core 2.1, action parameter binding source inference is enabled when a controller class is decorated with the [ApiController] attribute. Un nom de paramètre correspondant à un nom dans le modèle de routage est automatiquement lié à l’aide des données de l’itinéraire de demande.A parameter name matching a name in the route template is automatically bound using the request route data. Par conséquent, le paramètre id de l’action précédente n’est pas explicitement annoté avec l’attribut [FromRoute].Consequently, the preceding action's id parameter isn't explicitly annotated with the [FromRoute] attribute.

Action asynchroneAsynchronous action

Considérez une action asynchrone pour laquelle il existe deux types de retour possibles :Consider an asynchronous action in which there are two possible return types:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

Dans le code précédent :In the preceding code:

  • Un code d’état 400 (BadRequest) est retourné par le runtime ASP.NET Core dans les cas suivants :A 400 status code (BadRequest) is returned by the ASP.NET Core runtime when:
    • L’attribut [ApiController] a été appliqué et la validation du modèle échoue.The [ApiController] attribute has been applied and model validation fails.
    • La description de produit contient « XYZ Widget ».The product description contains "XYZ Widget".
  • Un code d’état 201 est généré par la méthode CreatedAtAction lors de la création d’un produit.A 201 status code is generated by the CreatedAtAction method when a product is created. Dans ce chemin de code, l’objet Product est retourné.In this code path, the Product object is returned.

Conseil

Depuis ASP.NET Core 2.1, l’inférence de la source de liaison de paramètre d’action est activée quand une classe de contrôleur est décorée avec l’attribut [ApiController].As of ASP.NET Core 2.1, action parameter binding source inference is enabled when a controller class is decorated with the [ApiController] attribute. Les paramètres de type complexe sont automatiquement liés à l’aide du corps de la demande.Complex type parameters are automatically bound using the request body. Par conséquent, le paramètre product de l’action précédente n’est pas explicitement annoté avec l’attribut [FromBody].Consequently, the preceding action's product parameter isn't explicitly annotated with the [FromBody] attribute.

Ressources supplémentairesAdditional resources