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 控制器動作參數繫結來源的機制會遵循下列規則:
- 先前指定的 BindingInfo.BindingSource 永遠不會被覆寫。
- 在 DI 容器中註冊的複雜類型參數會被指派 BindingSource.Services。
- 未在 DI 容器中註冊的複雜類型參數會被指派 BindingSource.Body。
- 在任何路由範本中名稱呈現為路由值的參數會被指派 BindingSource.Path。
- 所有其他參數都是指派的 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 控制器動作