[英]Simple Injector unable to inject dependencies in Web API controllers
我正在嘗試使用 Simple Injector 執行一些基本的構造函數 DI,但它似乎無法解析 Web API 控制器的依賴關系。
SimpleInjectorWebApiDependencyResolver
,它也與此處找到的相同。這似乎不是問題,但我仍然收到以下錯誤:
類型“MyProject.API.ArticleController”沒有默認構造函數
System.ArgumentException 在
System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType) , Func`1& activator) 在 System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
如果有人可以向我提供一些關於是否應該從當前狀態/調用順序修改任何內容的建議,我將不勝感激。
ArticleController(基本結構):
public class ArticleController : ApiController
{
private readonly IArticleRepository articleRepository;
private readonly IUserRepository userRepository;
private readonly IReleaseRepository releaseRepository;
public ArticleController(IArticleRepository articleRepository, IUserRepository userRepository, IReleaseRepository releaseRepository)
{
this.articleRepository = articleRepository;
this.userRepository = userRepository;
this.releaseRepository = releaseRepository;
}
// GET api/Article
public IEnumerable<Article> GetArticles(){ // code }
// GET api/Article/5
public Article GetArticle(int id){ // code }
// PUT api/Article/5
public HttpResponseMessage PutArticle(int id, Article article){ // code }
// POST api/Article
public HttpResponseMessage PostArticle(ArticleModel article){ // code }
// DELETE api/Article/5
public HttpResponseMessage DeleteArticle(int id){ // code }
}
SimpleInjectorInitializer:
public static class SimpleInjectorInitializer
{
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcAttributeFilterProvider();
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
container.Register<IArticleRepository, ArticleRepository>();
container.Register<IUserRepository, UserRepository>();
container.Register<IReleaseRepository, ReleaseRepository>();
}
}
Global.asax.cs:
public class WebApiApplication : System.Web.HttpApplication
{
private void ConfigureApi()
{
// Create the container as usual.
var container = new Container();
// Verify the container configuration
// container.Verify();
// Register the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ConfigureApi();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
TLTR:問題是由 Web API 處理解析控制器類型的隱式方式引起的; 顯式注冊您的 Web API 控制器,您將看到問題出在哪里。
以下是幕后發生的事情的分步說明:
System.Web.Http.DefaultHttpControllerActivator
調用SimpleInjectorWebApiDependencyResolver
並請求創建 API 控制器。SimpleInjectorWebApiDependencyResolver
將該調用轉發到SimpleInjector.Container
實例。Container
實例沒有該 API 控制器的任何顯式注冊(因為您向解析器提供了一個空容器)。IServiceProvider.GetService
方法請求的,並且該類型並未顯式注冊。SimpleInjectorWebApiDependencyResolver
的GetService
方法也將返回null
,因為根據定義它應該返回 null; 當不存在注冊時,它應該返回 null(目前是這種情況)。DependencyResolver
返回 null, DefaultHttpControllerActivator
將回退到其默認行為,這意味着自己創建該類型,但這需要控制器具有默認構造函數。長話短說,問題是由 Web API 處理解析控制器類型的隱式方式引起的。
所以這里的解決方案是:
Container
。 這可以防止您的配置出現各種麻煩和復雜化。container.Verify()
當配置無效時,這將使應用程序在啟動期間失敗( 可驗證的配置很重要)。 這還允許您診斷配置,從而使您對配置的正確性更有信心。我的建議是將 MVC 和 Web API 放在他們自己的項目中。 這將使事情變得容易得多。
可以使用以下代碼注冊所有 Web API 控制器:
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
更新:
由於此錯誤非常常見,因此在請求控制器類型時, SimpleInjectorWebApiDependencyResolver
類的較新版本將永遠不會返回null
。 相反,它會拋出一個描述性錯誤。 因此,只要您使用官方SimpleInjectorWebApiDependencyResolver
,您就不會再看到錯誤了。
以下設置對我有用:
1)包括從Unity.WebAPI https://www.nuget.org/packages/Unity.WebAPI/ 2)在UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// **** Important note -----
// register all your components with the container here
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
3) 在Global.asax文件中
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
首先,只需在 Global.asax.cs 的 Application_Start 方法中添加對 UnityConfig.RegisterComponents() 的調用,然后 Web API 框架將使用 Unity.WebAPI DependencyResolver 來解析您的組件。
例如
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents(); // <----- Add this line
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
在 UnityConfig 類的 RegisterComponents 方法中添加您的 Unity 注冊。 所有實現 IDisposable 的組件都應該向 HierarchicalLifetimeManager 注冊,以確保它們在請求結束時被正確處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.