Las acciones del controlador de API intentan deducir parámetros de la inserción de dependencias

El mecanismo para deducir los orígenes de enlace de los parámetros de la acción del controlador de API ahora marca los parámetros que se enlazarán desde el contenedor de inserción de dependencias (DI) al registrarse el tipo en el contenedor. En casos aislados, esto puede interrumpir las aplicaciones que tienen un tipo en la DI que también se acepta en los métodos de las acciones del controlador de API.

Versión introducida

ASP.NET Core 7.0

Comportamiento anterior

Si desea enlazar un tipo registrado en el contenedor de inserción de dependencia, debe decorarse explícitamente mediante un atributo que implemente IFromServiceMetadata, como FromServicesAttribute:

Services.AddScoped<SomeCustomType>();

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

Si no se especificó el atributo, el parámetro se resolvió a partir del cuerpo de la solicitud enviado por el cliente:

Services.AddScoped<SomeCustomType>();

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

Comportamiento nuevo

Los tipos de inserción de dependencias se comprueban al iniciar la aplicación con IServiceProviderIsService a fin de determinar si un argumento de una acción del controlador de API procede de la inserción de dependencias o de otros orígenes.

En el ejemplo siguiente, que supone que usa el contenedor de inserción de dependencias predeterminado, SomeCustomType procede del contenedor de DI:

Services.AddScoped<SomeCustomType>();

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

El mecanismo para deducir los orígenes de enlace de los parámetros de la acción del controlador de API sigue estas reglas:

  1. Nunca se sobrescribe una propiedad BindingInfo.BindingSource.
  2. BindingSource.Services se asigna a un parámetro de tipo complejo, registrado en el contenedor de la inserción de dependencias.
  3. BindingSource.Body se asigna a un parámetro de tipo complejo, no registrado en el contenedor de la inserción de dependencias.
  4. BindingSource.Path se asigna a un parámetro con un nombre que aparece como un valor de ruta en cualquier plantilla de ruta.
  5. BindingSource.Query se asigna a todos los demás parámetros.

Tipo de cambio importante

Este cambio afecta a la compatibilidad de origen.

Motivo del cambio

Este mismo comportamiento ya se implementa en las API mínimas.

La probabilidad de interrumpir las aplicaciones es baja, ya que no es habitual tener un tipo en DI y como argumento en la acción del controlador de API al mismo tiempo.

Si este cambio le interrumpe, puede deshabilitar la característica estableciendo DisableImplicitFromServicesParameters en true:

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

Si el cambio se interrumpe, pero quiere enlazar desde la inserción de dependencias para parámetros de la acción del controlador de API específicos, puede deshabilitar la característica como se muestra anteriormente y usar un atributo que implemente IFromServiceMetadata, como FromServicesAttribute:

Services.AddScoped<SomeCustomType>();

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

API afectadas

Acciones del controlador de API