API 控制器動作嘗試從 DI 推斷參數

推斷 API 控制器動作參數繫結來源的機制現在會在容器中註冊類型時,標記要從相依性插入 (DI) 容器繫結的參數。 在少數的情況下,這可能中斷應用程式,其在 DI 中有 API 控制器動作方法中也接受的類型。

導入的版本

ASP.NET Core 7.0

先前的行為

如果您想要繫結在 DI 容器中註冊的類型,則必須使用實作 IFromServiceMetadata 的屬性加以明確裝飾,例如 FromServicesAttribute

Services.AddScoped<SomeCustomType>();

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

如果未指定此屬性,則會從用戶端所傳送的要求本文解析參數:

Services.AddScoped<SomeCustomType>();

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

新的行為

使用 IServiceProviderIsService 在應用程式啟動時檢查 DI 中的類型,以判斷 API 控制器動作中的引數是否來自 DI 或其他來源。

在下列假設您使用預設 DI 容器的範例中,SomeCustomType 來自 DI 容器:

Services.AddScoped<SomeCustomType>();

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

推斷 API 控制器動作參數繫結來源的機制會遵循下列規則:

  1. 先前指定的 BindingInfo.BindingSource 永遠不會被覆寫。
  2. 在 DI 容器中註冊的複雜類型參數會被指派 BindingSource.Services
  3. 未在 DI 容器中註冊的複雜類型參數會被指派 BindingSource.Body
  4. 任何路由範本中名稱呈現為路由值的參數會被指派 BindingSource.Path
  5. 所有其他參數都是指派的 BindingSource.Query

中斷性變更的類型

這項變更會影響來源相容性

變更原因

此相同行為已在最少的 API 中實作。

應用程式中斷的可能性不高,因為少有同時在 DI 中具備類型,且該類型在 API 控制器動作中作為引數的狀況。

如果這項變更害您中斷,請將 DisableImplicitFromServicesParameters 設定為 true,藉此停用功能:

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

如果您因變更而中斷,但想要針對特定 API 控制器動作參數從 DI 繫結,您可停用上述功能並使用實作 IFromServiceMetadata 的屬性,例如 FromServicesAttribute

Services.AddScoped<SomeCustomType>();

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

受影響的 API

API 控制器動作