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

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)

Ce document explique comment créer une API web ASP.NET Core et quand il convient le plus d’utiliser chaque fonctionnalité.This document explains how to build a web API in ASP.NET Core and when it's most appropriate to use each feature.

Dériver la classe de ControllerBaseDerive class from ControllerBase

Héritez de la classe ControllerBase dans un contrôleur destiné à servir d’API web.Inherit from the ControllerBase class in a controller that's intended to serve as a web API. Par exemple :For example:

[Produces("application/json")]
[Route("api/[controller]")]
public class PetsController : ControllerBase
{
    private readonly PetsRepository _repository;

    public PetsController(PetsRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public async Task<ActionResult<List<Pet>>> GetAllAsync()
    {
        return await _repository.GetPetsAsync();
    }

    [HttpGet("{id}")]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<Pet>> GetByIdAsync(int id)
    {
        var pet = await _repository.GetPetAsync(id);

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

        return pet;
    }

    [HttpPost]
    [ProducesResponseType(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<Pet>> CreateAsync(Pet pet)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        await _repository.AddPetAsync(pet);

        return CreatedAtAction(nameof(GetByIdAsync),
            new { id = pet.Id }, pet);
    }
}
[Produces("application/json")]
[Route("api/[controller]")]
public class PetsController : ControllerBase
{
    private readonly PetsRepository _repository;

    public PetsController(PetsRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    [ProducesResponseType(typeof(IEnumerable<Pet>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetAllAsync()
    {
        var pets = await _repository.GetPetsAsync();

        return Ok(pets);
    }

    [HttpGet("{id}")]
    [ProducesResponseType(typeof(Pet), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetByIdAsync(int id)
    {
        var pet = await _repository.GetPetAsync(id);

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

        return Ok(pet);
    }

    [HttpPost]
    [ProducesResponseType(typeof(Pet), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateAsync([FromBody] Pet pet)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        await _repository.AddPetAsync(pet);

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

La classe ControllerBase fournit l’accès à de plusieurs propriétés et méthodes.The ControllerBase class provides access to several properties and methods. Dans le code précédent, les exemples incluent BadRequest(ModelStateDictionary) et CreatedAtAction(String, Object, Object).In the preceding code, examples include BadRequest(ModelStateDictionary) and CreatedAtAction(String, Object, Object). Ces méthodes sont appelées dans les méthodes d’action pour retourner les codes d’état HTTP 400 et 201, respectivement.These methods are called within action methods to return HTTP 400 and 201 status codes, respectively. La propriété ModelState, également fournie par ControllerBase, permet de gérer la validation des modèles de requêtes.The ModelState property, also provided by ControllerBase, is accessed to handle request model validation.

Annotation avec attribut ApiControllerAnnotation with ApiController attribute

ASP.NET Core 2.1 introduit l’attribut [ApiController] pour désigner une classe de contrôleur d’API web.ASP.NET Core 2.1 introduces the [ApiController] attribute to denote a web API controller class. Par exemple :For example:

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

Une version de compatibilité 2.1 ou ultérieure, définie par le biais de SetCompatibilityVersion, est obligatoire pour utiliser cet attribut au niveau du contrôleur.A compatibility version of 2.1 or later, set via SetCompatibilityVersion, is required to use this attribute at the controller level. Par exemple, le code en surbrillance dans Startup.ConfigureServices définit l’indicateur de compatibilité 2.1 :For example, the highlighted code in Startup.ConfigureServices sets the 2.1 compatibility flag:

services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Pour plus d'informations, consultez Version de compatibilité pour ASP.NET Core MVC.For more information, see Version de compatibilité pour ASP.NET Core MVC.

Dans ASP.NET Core 2.2 ou ultérieur, l’attribut [ApiController] peut être appliqué à un assembly.In ASP.NET Core 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. Notez que les contrôleurs individuels n’ont aucun moyen de refuser.Beware that there's no way to opt out for individual controllers. Il est recommandé d’appliquer des attributs de niveau assembly à la classe Startup :As a recommendation, assembly-level attributes should be applied to the Startup class:

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

Une version de compatibilité 2.2 ou ultérieure, définie par le biais de SetCompatibilityVersion, est obligatoire pour utiliser cet attribut au niveau de l’assembly.A compatibility version of 2.2 or later, set via SetCompatibilityVersion, is required to use this attribute at the assembly level.

L’attribut [ApiController] est généralement associé à ControllerBase pour donner aux contrôleurs un comportement spécifique à REST.The [ApiController] attribute is commonly coupled with ControllerBase to enable REST-specific behavior for controllers. ControllerBase permet d’accéder aux méthodes telles que NotFound et File.ControllerBase provides access to methods such as NotFound and File.

Une autre approche consiste à créer une classe de contrôleur de base personnalisée annotée avec l’attribut [ApiController] :Another approach is to create a custom base controller class annotated with the [ApiController] attribute:

[ApiController]
public class MyBaseController
{
}

Les sections suivantes décrivent les fonctionnalités pratiques ajoutées par l’attribut.The following sections describe convenience features added by the attribute.

Réponses HTTP 400 automatiquesAutomatic HTTP 400 responses

Les erreurs de validation de modèles déclenchent automatiquement une réponse HTTP 400.Model validation errors automatically trigger an HTTP 400 response. Par conséquent, le code suivant devient inutile dans vos actions :Consequently, the following code becomes unnecessary in your actions:

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

Utilisez InvalidModelStateResponseFactory pour personnaliser la sortie de la réponse résultante.Use InvalidModelStateResponseFactory to customize the output of the resulting response.

La désactivation du comportement par défaut est utile lorsque votre action peut récupérer suite à une erreur de validation de modèle.Disabling the default behavior is useful when your action can recover from a model validation error. Le comportement par défaut est désactivé quand la propriété SuppressModelStateInvalidFilter a la valeur true.The default behavior is disabled when the SuppressModelStateInvalidFilter property is set to true. Ajoutez le code suivant dans Startup.ConfigureServices après services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_<version_number>); :Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_<version_number>);:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;

        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });
services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Avec un indicateur de compatibilité 2.2 ou ultérieur, le type de réponse par défaut pour les réponses HTTP 400 est ValidationProblemDetails.With a compatibility flag 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. Définissez la propriété SuppressUseValidationProblemDetailsForInvalidModelStateResponses avec la valeur true pour retourner à la place le format d’erreur ASP.NET Core 2.1 de SerializableError.Set the SuppressUseValidationProblemDetailsForInvalidModelStateResponses property to true to instead return the ASP.NET Core 2.1 error format of SerializableError. Ajoutez le code suivant dans Startup.ConfigureServices :Add the following code in Startup.ConfigureServices:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options
          .SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
    });

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], les attributs de source de liaison sont définis explicitement.Without the [ApiController] attribute, binding source attributes are explicitly defined. Sans [ApiController] ou autres attributs de source de liaison comme [FromQuery], le runtime ASP.NET Core tente d’utiliser le classeur de modèles objet complexe.Without [ApiController] or other 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 (qui ont un ordre défini).The complex object model binder pulls data from value providers (which have a defined order). Par exemple,le « classeur de modèles body » est toujours activé.For instance, the 'body model binder' is always opt in.

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 async Task<ActionResult<List<Product>>> GetAsync(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = await _repository.GetDiscontinuedProductsAsync();
    }
    else
    {
        products = await _repository.GetProductsAsync();
    }

    return products;
}

Des règles d’inférence sont appliquées pour les sources de données par défaut des paramètres d’action.Inference rules are applied for the default data sources of action parameters. Ces règles configurent les sources de liaison que vous seriez susceptible d’appliquer manuellement aux paramètres d’action.These rules configure the binding sources you're otherwise likely to manually apply to the action parameters. Les attributs de source de liaison se comportent comme suit :The binding source attributes 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 est tout type complexe intégré ayant une signification spéciale, comme IFormCollection et CancellationToken.An exception to this 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. [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 explicitement spécifiés (par le biais de [FromBody]) ou déduits comme étant liés à partir du corps de la demande, une exception est levée.When an action has more than one parameter explicitly specified (via [FromBody]) or inferred as bound from the request body, an exception is thrown. Par exemple, les signatures d’action suivantes génèrent une exception :For example, the following action signatures cause an exception:

    // Don't do this. All of the following actions result in an exception.
    [HttpPost]
    public IActionResult Action1(Product product, 
                                 Order order) => null;
    
    [HttpPost]
    public IActionResult Action2(Product product, 
                                 [FromBody] Order order) => null;
    
    [HttpPost]
    public IActionResult Action3([FromBody] Product product, 
                                 [FromBody] Order order) => null;
    

    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]. [FromBody] doit être utilisé pour ces paramètres s’ils doivent être liés à partir du corps de la requête.[FromBody] should be used for these parameters if they are to be bound from the request body. Ce problème est résolu dans ASP.NET Core 2.2 ou version 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 fixed in ASP.NET Core 2.2 or later, where collection type parameters are inferred to be bound from the body by default.

  • [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.

Les règles d’inférence par défaut sont désactivées quand la propriété SuppressInferBindingSourcesForParameters a la valeur true.The default inference rules are disabled when the SuppressInferBindingSourcesForParameters property is set to true. Ajoutez le code suivant dans Startup.ConfigureServices après services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_<version_number>); :Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_<version_number>);:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;

        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });
services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

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

Quand un paramètre d’action est annoté avec l’attribut [FromForm], le type de contenu de demande multipart/form-data est déduit.When an action parameter is annotated with the [FromForm] attribute, the multipart/form-data request content type is inferred.

Le comportement par défaut est désactivé quand la propriété SuppressConsumesConstraintForFormFileParameters a la valeur true.The default behavior is disabled when the SuppressConsumesConstraintForFormFileParameters 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.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Ajoutez le code suivant dans Startup.ConfigureServices après services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); :Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Exigence du routage d’attributAttribute routing requirement

Le routage d’attribut devient une exigence.Attribute routing becomes a requirement. Par exemple :For example:

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

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

Réponses de la fonctionnalité Détails du problème pour les codes d’état erreurProblem details responses for error status codes

Dans ASP.NET Core 2.2 ou ultérieur, MVC transforme un résultat d’erreur (résultat avec un code d’état égal ou supérieur à 400) en résultat avec ProblemDetails.In ASP.NET Core 2.2 or later, MVC transforms an error result (a result with status code 400 or higher) to a result with ProblemDetails. ProblemDetails est :ProblemDetails is:

  • Un type basé sur la spécification RFC 7807.A type based on the RFC 7807 specification.
  • Un format standardisé pour spécifier les détails des erreurs lisibles par machine dans une réponse HTTP.A standardized format for specifying 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 (product == 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"
}

La fonctionnalité Détails du problème nécessite un indicateur de compatibilité de 2.2 ou ultérieur.The problem details feature requires a compatibility flag of 2.2 or later. Le comportement par défaut est désactivé quand la propriété SuppressMapClientErrors a la valeur true.The default behavior 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.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

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.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Ressources supplémentairesAdditional resources