2014-10-11 88 views
23

我正在用C#,.NET Framework 4.5.1開發ASP.NET Web Api 2.2。NinjectDependencyResolver失敗綁定ModelValidatorProvider

更新我Web.Api到Ninject 3.2.0後,我得到這個錯誤:

Error activating ModelValidatorProvider using binding from ModelValidatorProvider to NinjectDefaultModelValidatorProvider 
A cyclical dependency was detected between the constructors of two services. 

Activation path: 
    3) Injection of dependency ModelValidatorProvider into parameter defaultModelValidatorProviders of constructor of type DefaultModelValidatorProviders 
    2) Injection of dependency DefaultModelValidatorProviders into parameter defaultModelValidatorProviders of constructor of type NinjectDefaultModelValidatorProvider 
    1) Request for ModelValidatorProvider 

Suggestions: 
    1) Ensure that you have not declared a dependency for ModelValidatorProvider on any implementations of the service. 
    2) Consider combining the services into a single one to remove the cycle. 
    3) Use property injection instead of constructor injection, and implement IInitializable 
    if you need initialization logic to be run after property values have been injected. 

我得到的例外NinjectWebCommon

public static class NinjectWebCommon 
{ 
    private static readonly Bootstrapper bootstrapper = new Bootstrapper(); 

    /// <summary> 
    /// Starts the application 
    /// </summary> 
    public static void Start() 
    { 
     DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); 
     DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); 
     bootstrapper.Initialize(CreateKernel); 
    } 

    /// <summary> 
    /// Stops the application. 
    /// </summary> 
    public static void Stop() 
    { 
     bootstrapper.ShutDown(); 
    } 

    /// <summary> 
    /// Creates the kernel that will manage your application. 
    /// </summary> 
    /// <returns>The created kernel.</returns> 
    private static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 
     try 
     { 
      kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
      kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 

      RegisterServices(kernel); 
      return kernel; 
     } 
     catch 
     { 
      kernel.Dispose(); 
      throw; 
     } 
    } 

    /// <summary> 
    /// Load your modules or register your services here! 
    /// </summary> 
    /// <param name="kernel">The kernel.</param> 
    private static void RegisterServices(IKernel kernel) 
    { 
     var containerConfigurator = new NinjectConfigurator(); 
     containerConfigurator.Configure(kernel); 
    }   
} 

NinjectDependencyResolver類:

using Ninject; 
using System; 
using System.Collections.Generic; 
using System.Web.Http.Dependencies; 

namespace Matt.SocialNetwork.Web.Common 
{ 
    public class NinjectDependencyResolver : IDependencyResolver 
    { 
     private readonly IKernel _container; 

     public IKernel Container 
     { 
      get { return _container; } 
     } 

     public NinjectDependencyResolver(IKernel container) 
     { 
      _container = container; 
     } 

     public object GetService(Type serviceType) 
     { 
      return _container.TryGet(serviceType); 
     } 

     public IEnumerable<object> GetServices(Type serviceType) 
     { 
      return _container.GetAll(serviceType); 
     } 

     public IDependencyScope BeginScope() 
     { 
      return this; 
     } 

     public void Dispose() 
     { 
      // noop 
     } 
    } 
} 

NinjectConfigurator等級:

public class NinjectConfigurator 
{ 
    public void Configure(IKernel container) 
    { 
     // Add all bindings/dependencies 
     AddBindings(container); 

     // Use the container and our NinjectDependencyResolver as 
     // application's resolver 
     var resolver = new NinjectDependencyResolver(container); 
     GlobalConfiguration.Configuration.DependencyResolver = resolver; 
    } 

    // Omitted for brevity. 
} 

奇怪的是它編譯和工作完美,但更新後它不起作用。

我改變了這個public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver,但它仍然不起作用。

有什麼想法?

UPDATE

調試我看到異常在NinjectDependencyResolver這裏拋出:

public IEnumerable<object> GetServices(Type serviceType) 
{ 
    return _container.GetAll(serviceType); 
} 

它運行兩次。第一個serviceTypeIFilterProvider,第二個時間serviceTypeModelValidatorProvider,之後我得到了異常。

這些都是Ninject包,我使用:

我發現

<package id="Ninject" version="3.2.2.0" targetFramework="net45" /> 
<package id="Ninject.MVC5" version="3.2.1.0" targetFramework="net45" /> 
<package id="Ninject.Web.Common" version="3.2.2.0" targetFramework="net451" /> 
<package id="Ninject.Web.Common.WebHost" version="3.2.0.0" targetFramework="net45" /> 
<package id="Ninject.Web.WebApi" version="3.2.0.0" targetFramework="net451" /> 

第二次更新:

<package id="Ninject" version="3.2.2.0" targetFramework="net451" /> 
<package id="Ninject.MVC5" version="3.2.1.0" targetFramework="net45" /> 
<package id="Ninject.Web.Common" version="3.2.3.0" targetFramework="net451" /> 
<package id="Ninject.Web.Common.WebHost" version="3.2.3.0" targetFramework="net451" /> 
<package id="Ninject.Web.WebApi" version="3.2.2.0" targetFramework="net451" /> 

以前的版本,這些組件是問題在於此類:

public static class WebContainerManager 
{ 
    public static IKernel GetContainer() 
    { 
     var resolver = GlobalConfiguration.Configuration.DependencyResolver as NinjectDependencyResolver; 
     if (resolver != null) 
     { 
      return resolver.Container; 
     } 

     throw new InvalidOperationException("NinjectDependencyResolver not being used as the MVC dependency resolver"); 
    } 

    public static T Get<T>() 
    { 
     return GetContainer().Get<T>(); 
    } 
} 

我設置Dependency Resolver這裏:

public class NinjectConfigurator 
{ 
    /// <summary> 
    /// Entry method used by caller to configure the given 
    /// container with all of this application's 
    /// dependencies. Also configures the container as this 
    /// application's dependency resolver. 
    /// </summary> 
    public void Configure(IKernel container) 
    { 
     // Add all bindings/dependencies 
     AddBindings(container); 

     // Use the container and our NinjectDependencyResolver as 
     // application's resolver 
     var resolver = new NinjectDependencyResolver(container); 
     GlobalConfiguration.Configuration.DependencyResolver = resolver; 
    } 

而且我從ExceptionFilterAttribute繼承的類使用WebContainerManager

public class UnhandledExceptionFilter : ExceptionFilterAttribute 
{ 
    private readonly IExceptionLogHelper excepLogHelper; 

    public UnhandledExceptionFilter() 
     : this(WebContainerManager.Get<IExceptionLogHelper>()) {} 

    public UnhandledExceptionFilter(IExceptionLogHelper exceptionLogHelper) 
    { 
     this.excepLogHelper = exceptionLogHelper; 
    } 

    public override void OnException(HttpActionExecutedContext actionExecutedContext) 
    { 
     this.excepLogHelper.LogException(actionExecutedContext); 
    } 
} 

所以,如果我刪除WebContainerManager我沒有得到循環。

+0

你試過卸載所有的ninject軟件包並重新安裝它們嗎?確保你真的有最新版本? – BatteryBackupUnit 2014-10-17 09:16:34

+0

是的,我這樣做,我得到了同樣的錯誤。 – VansFannel 2014-10-17 09:18:42

+0

你可以上傳[mcve](http://stackoverflow.com/help/mcve)作爲視覺工作室項目在gist/github回購或類似的東西?我想刺穿它。 – BatteryBackupUnit 2014-11-10 07:18:25

回答

10

升級Ninject軟件包(甚至是卸載和刪除舊的軟件包)後,我對於WebApi2和Ninject的初始化感到各種各樣的悲傷。

特別是在你的情況我會刪除這些代碼:

// Use the container and our NinjectDependencyResolver as 
// application's resolver 
var resolver = new NinjectDependencyResolver(container); 
GlobalConfiguration.Configuration.DependencyResolver = resolver; 

,因爲他們很可能(在NinjectWebCommon.cs和Ninject庫處理現在初始化依賴解析器)錯誤的原因。


對於其他那些誰跟隨類似的升級路徑給我。什麼工作對我來說是如下:

  • 取出舊DependencyResolver初始化代碼(對我來說這是造成你提到在早期版本Ninject/WebApi2的特定錯誤,把這些線路中的WebApiConfig.cs註冊()方法是你如何初始化DependencyResolver ......這不再是這種情況):

    var kernel = new StandardKernel(); 
    config.DependencyResolver = new NinjectDependencyResolver(kernel); 
    
  • 安裝Ninject.Web.WebApi.WebHost包。這安裝了 NinjectWebCommon.cs文件。對我來說,只有Ninject.Web.WebApi和它的 依賴關係並沒有創建這個文件。

我安裝並正常工作Ninject套餐以供參考:

<package id="Ninject" version="3.2.2.0" targetFramework="net452" /> 
<package id="Ninject.Web.Common" version="3.2.3.0" targetFramework="net452" /> 
<package id="Ninject.Web.Common.WebHost" version="3.2.0.0" targetFramework="net452" /> 
<package id="Ninject.Web.WebApi" version="3.2.3.0" targetFramework="net452" /> 
<package id="Ninject.Web.WebApi.WebHost" version="3.2.3.0" targetFramework="net452" /> 
+0

其中config中的'config'在哪裏。 DependencyResolver從哪裏來? – bigerock 2015-04-01 19:15:22

+0

@bigerock WebApiConfig.cs將有一個方法public static void Register(HttpConfiguration config),這是上面兩行代碼應該去的地方。 – mips 2015-04-06 10:22:22

2

的循環依賴是類「NinjectDefaultModelValidatorProvider」和「DefaultModelValidatorProviders」之間.Simply增加對「DefaultModelValidatorProviders」綁定在你的啓動像如下:

 
_kernel.Bind<DefaultModelValidatorProviders>().ToConstant(new DefaultModelValidatorProviders(config.Services.GetServices(typeof (ModelValidatorProvider)).Cast<ModelValidatorProvider>())); 
+4

配置從哪裏來? – 2016-01-17 10:26:35

6

確保任何舊NinjectNinject.Web.Common.* dll不在您的bin文件夾中。

我有同樣的問題在我的解決方案我已經從卸載的NuGet Ninject.Web.CommonNinject.Web.Common.WebHostNinject.Web.WebApiNinject.MVC5,爲了使用GlobalConfiguration.Configuration.DependencyResolver作爲你的榜樣安裝WebApiContrib.IoC.Ninject後。我保留了我已經安裝的Ninject版本(確實是3.2.2)。

當我第一次進行更改時,沒有出現該錯誤。但是,從幾個git分支轉移到我目前的工作後,我看到了錯誤。上週運行良好的代碼現在拋出了相同的確切錯誤。

看來我的bin文件夾引用了我刪除的舊的Ninject.*包。刪除這些文件後,我的項目按預期工作。

+1

哇,我一直回到這個,直到我意識到在發佈到Azure的時候,我並沒有刪除舊的dll!在發佈 - >設置 - >文件發佈選項下,您必須選中「在目的地刪除其他文件」。否則,你會發現一切都在localhost中運行,但不在Azure上,因爲Ninject.Web。*仍然存在。 – tofutim 2016-10-26 07:49:32

1

在我的情況下,它在Owin Selfhost上下文中工作得很好,但在IIS中託管時沒有。我的解決方案是從nuget包中除Ninject本身之外的所有Ninject相關的程序集。

然後我寫了我自己的DependencyResolver類,隨時留下改進的意見。

public class NinjectDepsolver : IDependencyResolver 
{ 
    private IKernel _kernel; 

    public NinjectDepsolver(IKernel kernel) 
    { 
     _kernel = kernel; 
    } 

    public void Dispose() 
    { 
     _kernel = null; 
    } 

    public object GetService(Type serviceType) => _kernel.TryGet(serviceType); 

    public IEnumerable<object> GetServices(Type serviceType) => _kernel.GetAll(serviceType).ToArray(); 

    public IDependencyScope BeginScope() => new DepScope(this); 

    class DepScope : IDependencyScope 
    { 
     private NinjectDepsolver _depsolver; 

     public DepScope(NinjectDepsolver depsolver) 
     { 
      _depsolver = depsolver; 
     } 

     public void Dispose() 
     { 
      _depsolver = null; 
     } 

     public object GetService(Type serviceType) => _depsolver.GetService(serviceType); 

     public IEnumerable<object> GetServices(Type serviceType) => _depsolver.GetServices(serviceType); 
    } 
} 

,然後在Owin配置方法:

var kernel = new StandardKernel(); 
kernel.Load(<your module classes>); 
var httpConfig = new HttpConfiguration(); 
var httpConfig.DependencyResolver = new NinjectDepsolver(kernel); 
var httpConfig.MapHttpAttributeRoutes(); 

app.UseWebApi(httpConfig); 
0

這是對我工作。

uninstall-package Ninject.Web.WebApi.WebHost

上述命令卸載了版本「Ninject.Web.WebApi.WebHost 3.2.4.0」和錯誤消失!

只是重申,我一直在使用該命令

install-package Ninject.Web.WebApi.WebHost

安裝在同一封裝和命令安裝包「Ninject.Web.WebApi.WebHost 3.2.4.0」和錯誤再次出現。