Les actions du contrôleur d’API tentent de déduire des paramètres à partir de l’injection de dépendances

Le mécanisme permettant de déduire les sources de liaison des paramètres d’action du contrôleur d’API marque désormais les paramètres comme étant liés au conteneur d’injection de dépendances quand le type est inscrit dans le conteneur. Dans de rares cas, ce comportement peut arrêter les applications qui ont un type dans l’injection de dépendances qui est également accepté dans les méthodes d’action du contrôleur d’API.

Version introduite

ASP.NET Core 7.0

Comportement précédent

Si vous vouliez lier un type inscrit dans le conteneur d’injection de dépendances, il devait être explicitement décoré avec un attribut qui implémente IFromServiceMetadata, comme FromServicesAttribute :

Services.AddScoped<SomeCustomType>();

[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    public ActionResult Get([FromServices]SomeCustomType service) => Ok();
}

Si l’attribut n’était pas spécifié, le paramètre était résolu à partir du corps de la demande envoyé par le client :

Services.AddScoped<SomeCustomType>();

[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    // Bind from the request body
    [HttpPost]
    public ActionResult Post(SomeCustomType service) => Ok();
}

Nouveau comportement

Les types dans l’injection de dépendances sont vérifiés au démarrage de l’application avec IServiceProviderIsService pour déterminer si un argument dans une action de contrôleur d’API provient de l’injection de dépendances ou d’autres sources.

Dans l’exemple suivant, qui suppose que vous utilisez le conteneur d’injection de dépendances par défaut, SomeCustomType provient du conteneur d’injection de dépendances :

Services.AddScoped<SomeCustomType>();

[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    // Bind from DI
    [HttpPost]
    public ActionResult Post(SomeCustomType service) => Ok();
}

Le mécanisme permettant de déduire les sources de liaison des paramètres d’action du contrôleur d’API utilise les règles suivantes :

  1. Un BindingInfo.BindingSource spécifié précédemment n’est jamais remplacé.
  2. Un paramètre de type complexe inscrit dans le conteneur d’injection de dépendances reçoit BindingSource.Services.
  3. Un paramètre de type complexe qui n’est pas inscrit dans le conteneur d’injection de dépendances reçoit BindingSource.Body.
  4. BindingSource.Path est affecté à un paramètre avec un nom qui apparaît en tant que valeur de routage dans n’importe quel modèle de routage.
  5. Tous les autres paramètres reçoivent BindingSource.Query.

Type de changement cassant

Ce changement affecte la compatibilité de la source.

Raison du changement

Ce même comportement est déjà implémenté dans les API minimales.

La probabilité d’arrêt des applications est faible, car il n’est pas courant d’avoir un type dans l’injection de dépendances qui soit en même temps un argument dans l’action de votre contrôleur d’API.

Si votre application est arrêtée par ce changement, vous pouvez désactiver la fonctionnalité en définissant DisableImplicitFromServicesParameters sur true :

Services.Configure<ApiBehaviorOptions>(options =>
{
     options.DisableImplicitFromServicesParameters = true;
});

Si votre application est arrêtée par ce changement, mais que vous voulez lier certains paramètres d’action du contrôleur d’API à l’injection de dépendances, vous pouvez désactiver la fonctionnalité comme indiqué ci-dessus et utiliser un attribut qui implémente IFromServiceMetadata, comme FromServicesAttribute :

Services.AddScoped<SomeCustomType>();

[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    // Bind from DI
    [HttpPost]
    public ActionResult Post([FromServices]SomeCustomType service) => Ok();
}

API affectées

Actions du contrôleur d’API