简单的注射器无法注入Web API控制器中的依赖项

我试图做一些基本的构造函数DI与简单的注入器,似乎无法解决Web API控制器的依赖关系。

  • 我有一个“API”文件夹,这是“控制器”文件夹之外的API控制器。
  • 我也尝试把它放在“控制器”文件夹,但似乎没有多大的区别。 我收到的堆栈跟踪与此问题中提供的相似。
  • 我正在使用“Simple Injector MVC集成快速入门”NuGet软件包(第2.1.0版)的全新安装。
  • 我从文档中获得了基本的SimpleInjectorWebApiDependencyResolver ,这与在这里find的一样。
  • 我正在使用entity framework,并已查看有关正确加载上下文的更改的讨论线程 。

这似乎不是一个问题,但我仍然收到以下错误:

types“MyProject.API.ArticleController”没有默认的构造函数

System.ArgumentException在

System.Web.Http.Internal.TypeActivator.Create [TBase](typesinstanceType)在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage请求,Type控制器types)System.Linq.Expressions.Expression.New ,Func`1&activator)在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage请求,HttpControllerDescriptor controllerDescriptor,typescontrollerType)

如果有人能提供一些build议,请问是否应该修改其当前状态/呼叫顺序。

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处理parsing控制器types的隐式方式引起的; 注册您的Web API控制器明确,你会看到问题的地方。

以下是一步一步发生的事情:

  1. System.Web.Http.DefaultHttpControllerActivator调用SimpleInjectorWebApiDependencyResolver并请求创build一个API控制器。
  2. SimpleInjectorWebApiDependencyResolver将该调用转发给SimpleInjector.Container实例。
  3. 但是, Container实例没有为该API控制器显式注册(因为您向parsing器提供了一个空容器)。
  4. 由于没有明确的注册,容器试图为该types进行最后一刻的注册。
  5. 然而,该控制器types取决于不能解决的接口,因为它们没有注册在容器(记住,你的容器是空的)。
  6. 尽pipe容器通常会抛出一个exception,但在这种情况下返回null,因为types是通过IServiceProvider.GetService方法请求的,并且types未被明确注册。
  7. SimpleInjectorWebApiDependencyResolverGetService方法也会返回null ,因为按照定义它应该返回null; 当不存在注册时(当前是这种情况)它应该返回null。
  8. 由于DependencyResolver返回null,因此DefaultHttpControllerActivator将回退到其默认行为,这意味着创build该types本身,但这需要控制器具有默认构造函数。

长话短说,这个问题是由Web API处理parsing控制器types的隐式方式引起的。

所以这里的解决scheme是:

  1. 在您的Web应用程序中只有一个Container 。 这可以防止configuration的各种麻烦和复杂性。
  2. 在容器中显式注册所有Web API控制器。 显式注册控制器将确保简单注入器将在控制器无法parsing时抛出exception。 此外,这允许您调用container.Verify() ,这将使configuration无效( 可validation的configuration很重要 )启动期间应用程序失败。 这也使您能够诊断configuration ,使您对configuration的正确性更有信心。

我的build议是将MVC和Web API放在他们自己的项目中 。 这将使事情变得更容易。

注册所有的Web API控制器可以用下面的代码完成:

 container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 

更新:

由于此错误非常常见,因此在请求控制器types时, SimpleInjectorWebApiDependencyResolver类的较新版本将不会返回null 。 相反,它会抛出一个描述性的错误。 因此,只要使用官方的SimpleInjectorWebApiDependencyResolver ,就不会再看到错误。

Interesting Posts