2014-10-11 68 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”和错误再次出现。