Créer des API web avec ASP.NET CoreCreate web APIs with ASP.NET Core

De Scott Addie et Tom DykstraBy Scott Addie and Tom Dykstra

ASP.NET Core prend en charge la création de services RESTful, également appelés API web, à l’aide de C#.ASP.NET Core supports creating RESTful services, also known as web APIs, using C#. Pour traiter les demandes, une API web utilise des contrôleurs.To handle requests, a web API uses controllers. Les contrôleurs dans une API web sont des classes qui dérivent de ControllerBase.Controllers in a web API are classes that derive from ControllerBase. Cet article montre comment utiliser des contrôleurs pour gérer des demandes d’API.This article shows how to use controllers for handling API requests.

Affichez ou téléchargez l’exemple de code.View or download sample code. (Guide pratique de téléchargement).(How to download).

Classe ControllerBaseControllerBase class

Une API web a une ou plusieurs classes de contrôleur qui dérivent de ControllerBase.A web API has one or more controller classes that derive from ControllerBase. Par exemple, le modèle de projet d’API web crée un contrôleur Values :For example, the web API project template creates a Values controller:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Ne créez pas de contrôleur d’API web en effectuant une dérivation de la classe Controller.Don't create a web API controller by deriving from the Controller class. Controller dérive de ControllerBase et ajoute la prise en charge pour les vues ; ainsi, il est destiné à la gestion des pages web, pas des demandes d’API web.Controller derives from ControllerBase and adds support for views, so it's for handling web pages, not web API requests. Il existe une exception à cette règle : si vous envisagez d’utiliser le même contrôleur pour les vues et les API, dérivez-le de Controller.There's an exception to this rule: if you plan to use the same controller for both views and APIs, derive it from Controller.

La classe ControllerBase fournit de nombreuses propriétés et méthodes qui sont utiles pour gérer les requêtes HTTP.The ControllerBase class provides many properties and methods that are useful for handling HTTP requests. Par exemple, ControllerBase.CreatedAtAction retourne un code d’état 201 :For example, ControllerBase.CreatedAtAction returns a 201 status code:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

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

Voici d’autres exemples de méthodes fournies par ControllerBase.Here are some more examples of methods that ControllerBase provides.

MéthodeMethod NotesNotes
BadRequest Retourne le code d’état 400.Returns 400 status code.
NotFound Retourne le code d’état 404.Returns 404 status code.
PhysicalFile Retourne un fichier.Returns a file.
TryUpdateModelAsync Appelle la liaison de modèle.Invokes model binding.
TryValidateModel Appelle la validation de modèle.Invokes model validation.

Pour obtenir la liste complète des méthodes et propriétés disponibles, consultez ControllerBase.For a list of all available methods and properties, see ControllerBase.

AttributsAttributes

L’espace de noms Microsoft.AspNetCore.Mvc fournit des attributs qui peuvent être utilisés pour configurer le comportement des contrôleurs d’API web et des méthodes d’action.The Microsoft.AspNetCore.Mvc namespace provides attributes that can be used to configure the behavior of web API controllers and action methods. L’exemple suivant utilise des attributs pour spécifier la méthode HTTP acceptée et les codes d’état retournés :The following example uses attributes to specify the HTTP method accepted and the status codes returned:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

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

Voici d’autres exemples d’attributs disponibles.Here are some more examples of attributes that are available.

AttributAttribute NotesNotes
[Route][Route] Spécifie le modèle d’URL pour un contrôleur ou une action.Specifies URL pattern for a controller or action.
[Bind][Bind] Spécifie le préfixe et les propriétés à inclure pour la liaison de modèle.Specifies prefix and properties to include for model binding.
[HttpGet][HttpGet] Identifie une action qui prend en charge la méthode HTTP GET.Identifies an action that supports the HTTP GET method.
[Consumes][Consumes] Spécifie les types de données acceptés par une action.Specifies data types that an action accepts.
[Produces][Produces] Spécifie les types de données retournés par une action.Specifies data types that an action returns.

Pour obtenir la liste des attributs disponibles, consultez l’espace de noms Microsoft.AspNetCore.Mvc.For a list that includes the available attributes, see the Microsoft.AspNetCore.Mvc namespace.

Attribut ApiControllerApiController attribute

L’attribut [ApiController] peut être appliqué à une classe de contrôleur pour activer les comportements spécifiques à une API :The [ApiController] attribute can be applied to a controller class to enable API-specific behaviors:

Ces fonctionnalités nécessitent une version de compatibilité 2.1 ou ultérieure.These features require a compatibility version of 2.1 or later.

ApiController sur des contrôleurs spécifiquesApiController on specific controllers

L’attribut [ApiController] peut être appliqué à des contrôleurs spécifiques, comme dans l’exemple suivant à partir du modèle de projet :The [ApiController] attribute can be applied to specific controllers, as in the following example from the project template:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

ApiController sur plusieurs contrôleursApiController on multiple controllers

Une façon d’utiliser l’attribut sur plusieurs contrôleurs consiste à créer une classe de contrôleur de base personnalisée annotée avec l’attribut [ApiController].One approach to using the attribute on more than one controller is to create a custom base controller class annotated with the [ApiController] attribute. Voici un exemple illustrant une classe de base personnalisée et un contrôleur qui dérive de celle-ci :Here's an example showing a custom base class and a controller that derives from it:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces("application/json")]
[Route("api/[controller]")]
public class PetsController : MyControllerBase

ApiController sur un assemblyApiController on an assembly

Si la version de compatibilité est définie sur 2.2 ou une version ultérieure, l’attribut [ApiController] peut être appliqué à un assembly.If compatibility version is set to 2.2 or later, the [ApiController] attribute can be applied to an assembly. De cette manière, l’annotation applique le comportement de l’API web à tous les contrôleurs de l’assembly.Annotation in this manner applies web API behavior to all controllers in the assembly. Les contrôleurs individuels n’ont aucun moyen de refuser.There's no way to opt out for individual controllers. Appliquez l’attribut de niveau assembly à la classe Startup, comme indiqué dans l’exemple suivant :Apply the assembly-level attribute to the Startup class as shown in the following example:

[assembly: ApiController]
namespace WebApiSample
{
    public class Startup
    {
        ...
    }
}

Exigence du routage d’attributAttribute routing requirement

L’attribut ApiController rend nécessaire le routage d’attributs.The ApiController attribute makes attribute routing a requirement. Par exemple :For example:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Les actions sont inaccessibles par le biais de routes conventionnelles définies par UseMvc ou UseMvcWithDefaultRoute dans Startup.Configure.Actions are inaccessible via conventional routes defined by UseMvc or UseMvcWithDefaultRoute in Startup.Configure.

Réponses HTTP 400 automatiquesAutomatic HTTP 400 responses

Grâce à l’attribut ApiController, les erreurs de validation de modèles déclenchent automatiquement une réponse HTTP 400.The ApiController attribute makes model validation errors automatically trigger an HTTP 400 response. Ainsi, le code suivant est inutile dans une méthode d’action :Consequently, the following code is unnecessary in an action method:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

Réponse BadRequest par défautDefault BadRequest response

Avec une version de compatibilité 2.2 ou ultérieure, le type de réponse par défaut pour les réponses HTTP 400 est ValidationProblemDetails.With a compatibility version of 2.2 or later, the default response type for HTTP 400 responses is ValidationProblemDetails. Le type ValidationProblemDetails est conforme à la spécification RFC 7807.The ValidationProblemDetails type complies with the RFC 7807 specification.

Pour remplacer la réponse par défaut par SerializableError, définissez la propriété SuppressUseValidationProblemDetailsForInvalidModelStateResponses sur true dans Startup.ConfigureServices, comme illustré dans l’exemple suivant :To change the default response to SerializableError, set the SuppressUseValidationProblemDetailsForInvalidModelStateResponses property to true in Startup.ConfigureServices, as shown in the following example:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Personnaliser la réponse BadRequestCustomize BadRequest response

Pour personnaliser la réponse qui résulte d’une erreur de validation, utilisez InvalidModelStateResponseFactory.To customize the response that results from a validation error, use InvalidModelStateResponseFactory. Ajoutez le code en surbrillance suivant après services.AddMvc().SetCompatibilityVersion :Add the following highlighted code after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.InvalidModelStateResponseFactory = context =>
        {
            var problemDetails = new ValidationProblemDetails(context.ModelState)
            {
                Type = "https://contoso.com/probs/modelvalidation",
                Title = "One or more model validation errors occurred.",
                Status = StatusCodes.Status400BadRequest,
                Detail = "See the errors property for details.",
                Instance = context.HttpContext.Request.Path
            };

            return new BadRequestObjectResult(problemDetails)
            {
                ContentTypes = { "application/problem+json" }
            };
        };
    });

Consigner automatiquement 400 réponsesLog automatic 400 responses

Voir Guide pratique pour consigner automatiquement 400 réponses en cas d’erreurs de validation de modèle (aspnet/AspNetCore.Docs no 12157).See How to log automatic 400 responses on model validation errors (aspnet/AspNetCore.Docs #12157).

Désactiver le comportement 400 automatiqueDisable automatic 400

Pour désactiver le comportement 400 automatique, définissez la propriété SuppressModelStateInvalidFilter sur true.To disable the automatic 400 behavior, set the SuppressModelStateInvalidFilter property to true. Ajoutez le code en surbrillance suivant dans Startup.ConfigureServices après services.AddMvc().SetCompatibilityVersion :Add the following highlighted code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Inférence de paramètre de source de liaisonBinding source parameter inference

Un attribut de source de liaison définit l’emplacement auquel se trouve la valeur d’un paramètre d’action.A binding source attribute defines the location at which an action parameter's value is found. Les attributs de source de liaison suivants existent :The following binding source attributes exist:

AttributAttribute Source de liaisonBinding source
[FromBody][FromBody] Corps de la requêteRequest body
[FromForm][FromForm] Données de formulaire dans le corps de la demandeForm data in the request body
[FromHeader][FromHeader] En-tête de demandeRequest header
[FromQuery][FromQuery] Paramètre de la chaîne de requête de la demandeRequest query string parameter
[FromRoute][FromRoute] Données d’itinéraire à partir de la demande actuelleRoute data from the current request
[FromServices][FromServices] Service de demande injecté comme paramètre d’actionThe request service injected as an action parameter

Avertissement

N’utilisez pas [FromRoute] lorsque les valeurs risquent de contenir %2f (c’est-à-dire /).Don't use [FromRoute] when values might contain %2f (that is /). %2f ne sera pas sans la séquence d’échappement /.%2f won't be unescaped to /. Utilisez [FromQuery] si la valeur peut contenir %2f.Use [FromQuery] if the value might contain %2f.

Sans l’attribut [ApiController] ou des attributs de source de liaison comme [FromQuery], le runtime ASP.NET Core tente d’utiliser le classeur de modèles objet complexe.Without the [ApiController] attribute or binding source attributes like [FromQuery], the ASP.NET Core runtime attempts to use the complex object model binder. Le classeur de modèles objet complexe extrait des données à partir de fournisseurs de valeurs dans un ordre défini.The complex object model binder pulls data from value providers in a defined order.

Dans l’exemple suivant, l’attribut [FromQuery] indique que la valeur du paramètre discontinuedOnly est fournie dans la chaîne de requête de l’URL de demande :In the following example, the [FromQuery] attribute indicates that the discontinuedOnly parameter value is provided in the request URL's query string:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

L’attribut [ApiController] applique des règles d’inférence pour les sources de données par défaut des paramètres d’action.The [ApiController] attribute applies inference rules for the default data sources of action parameters. Ces règles vous évitent d’avoir à identifier les sources de liaison manuellement en appliquant des attributs aux paramètres d’action.These rules save you from having to identify binding sources manually by applying attributes to the action parameters. Les règles d’inférence de source de liaison se comportent comme suit :The binding source inference rules behave as follows:

  • [FromBody] est déduit des paramètres de type complexe.[FromBody] is inferred for complex type parameters. Une exception à cette règle d’inférence [FromBody] est tout type complexe intégré ayant une signification spéciale, comme IFormCollection et CancellationToken.An exception to the [FromBody] inference rule is any complex, built-in type with a special meaning, such as IFormCollection and CancellationToken. Le code de l’inférence de la source de liaison ignore ces types spéciaux.The binding source inference code ignores those special types.
  • [FromForm] est déduit pour les paramètres d’action de type IFormFile et IFormFileCollection.[FromForm] is inferred for action parameters of type IFormFile and IFormFileCollection. Il n’est pas déduit pour les types simples ou définis par l’utilisateur.It's not inferred for any simple or user-defined types.
  • [FromRoute] est déduit pour tout nom de paramètre d’action correspondant à un paramètre dans le modèle d’itinéraire.[FromRoute] is inferred for any action parameter name matching a parameter in the route template. Quand plus d’un itinéraire correspond à un paramètre d’action, toute valeur d’itinéraire est considérée comme [FromRoute].When more than one route matches an action parameter, any route value is considered [FromRoute].
  • [FromQuery] est déduit pour tous les autres paramètres d’action.[FromQuery] is inferred for any other action parameters.

Notes sur l’inférence FromBodyFromBody inference notes

[FromBody] n’est pas déduit pour les types simples tels que string ou int.[FromBody] isn't inferred for simple types such as string or int. Vous devez donc utiliser l’attribut [FromBody] pour les types simples quand cette fonctionnalité est nécessaire.Therefore, the [FromBody] attribute should be used for simple types when that functionality is needed.

Quand une action a plusieurs paramètres liés à partir du corps de la demande, une exception est levée.When an action has more than one parameter bound from the request body, an exception is thrown. Par exemple, toutes les signatures de méthode d’action suivantes génèrent une exception :For example, all of the following action method signatures cause an exception:

  • [FromBody] est déduit sur les deux paramètres, car ce sont des types complexes.[FromBody] inferred on both because they're complex types.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Attribut [FromBody] sur un paramètre, déduit sur l’autre, car c’est un type complexe.[FromBody] attribute on one, inferred on the other because it's a complex type.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Attribut [FromBody] sur les deux paramètres.[FromBody] attribute on both.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Notes

Dans ASP.NET Core 2.1, les paramètres de type collection comme les listes et les tableaux sont déduits de manière incorrecte en tant que [FromQuery].In ASP.NET Core 2.1, collection type parameters such as lists and arrays are incorrectly inferred as [FromQuery]. L’attribut [FromBody] doit être utilisé pour ces paramètres s’ils doivent être liés à partir du corps de la demande.The [FromBody] attribute should be used for these parameters if they are to be bound from the request body. Ce problème est corrigé dans ASP.NET Core version 2.2 ou ultérieure, où les paramètres de type collection sont déduits pour être liés à partir du corps par défaut.This behavior is corrected in ASP.NET Core 2.2 or later, where collection type parameters are inferred to be bound from the body by default.

Désactiver les règles d’inférenceDisable inference rules

Pour désactiver l’inférence de la source de liaison, définissez SuppressInferBindingSourcesForParameters sur true.To disable binding source inference, set SuppressInferBindingSourcesForParameters to true. Ajoutez le code suivant dans Startup.ConfigureServices après services.AddMvc().SetCompatibilityVersion :Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Inférence de demande multipart/form-dataMultipart/form-data request inference

L’attribut [ApiController] applique une règle d’inférence quand un paramètre d’action est annoté avec l’attribut [FromForm] : le type de contenu de demande multipart/form-data est déduit.The [ApiController] attribute applies an inference rule when an action parameter is annotated with the [FromForm] attribute: the multipart/form-data request content type is inferred.

Pour désactiver le comportement par défaut, définissez SuppressConsumesConstraintForFormFileParameters sur true dans Startup.ConfigureServices, comme illustré dans l’exemple suivant :To disable the default behavior, set SuppressConsumesConstraintForFormFileParameters to true in Startup.ConfigureServices, as shown in the following example:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Fonctionnalité Détails du problème pour les codes d’état erreurProblem details for error status codes

Quand la version de compatibilité est 2.2 ou ultérieure, MVC transforme un résultat d’erreur (résultat avec un code d’état égal ou supérieur à 400) en résultat avec ProblemDetails.When the compatibility version is 2.2 or later, MVC transforms an error result (a result with status code 400 or higher) to a result with ProblemDetails. Le type ProblemDetails est basé sur la spécification RFC 7807 pour fournir des détails de l’erreur lisibles par machine dans une réponse HTTP.The ProblemDetails type is based on the RFC 7807 specification for providing machine-readable error details in an HTTP response.

Prenons le code suivant dans une action de contrôleur :Consider the following code in a controller action:

if (pet == null)
{
    return NotFound();
}

La réponse HTTP pour NotFound a le code d’état 404 avec le corps ProblemDetails.The HTTP response for NotFound has a 404 status code with a ProblemDetails body. Par exemple :For example:

{
    type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
    title: "Not Found",
    status: 404,
    traceId: "0HLHLV31KRN83:00000001"
}

Personnaliser la réponse ProblemDetailsCustomize ProblemDetails response

Utilisez la propriété ClientErrorMapping pour configurer le contenu de la réponse ProblemDetails.Use the ClientErrorMapping property to configure the contents of the ProblemDetails response. Par exemple, le code suivant met à jour la propriété type pour les réponses 404 :For example, the following code updates the type property for 404 responses:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Désactiver la réponse ProblemDetailsDisable ProblemDetails response

La création automatique de ProblemDetails est désactivée quand la propriété SuppressMapClientErrors est définie sur true.The automatic creation of ProblemDetails is disabled when the SuppressMapClientErrors property is set to true. Ajoutez le code suivant dans Startup.ConfigureServices :Add the following code in Startup.ConfigureServices:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Ressources supplémentairesAdditional resources