I'm developing an ASP.NET Web Api 2.2 with C#, .NET Framework 4.5.1.
After updating my Web.Api to Ninject 3.2.0 I get this error:
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.
I get the exception in 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
class:
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
class:
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.
}
The strange thing is it compiles and works perfectly, but after update it doesn't work.
I have changed this public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver
but it still doesn't work.
Any idea?
UPDATE
Debugging I see that the exception is thrown in NinjectDependencyResolver
here:
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAll(serviceType);
}
It runs twice. First serviceType
is IFilterProvider
and second time serviceType
is ModelValidatorProvider
, and after that I get the exception.
These are the Ninject packages that I'm using:
<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" />
The previous version for these assemblies were:
<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" />
SECOND UPDATE
I have found that the problem is in this class:
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>();
}
}
I set Dependency Resolver
here:
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;
}
And I use WebContainerManager
in a class that inherits from ExceptionFilterAttribute
:
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);
}
}
So, if I remove WebContainerManager
I don't get that cycle.
I was having all sorts of grief with the WebApi2 and Ninject initialization after upgrading the Ninject packages (even uninstalling and deleting the old ones).
Specifically in your case I would remove these lines of code:
// Use the container and our NinjectDependencyResolver as
// application's resolver
var resolver = new NinjectDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
as they are probably the cause of the error (the NinjectWebCommon.cs and Ninject libraries deal with initializing the dependency resolver now).
For others out there who followed a similar upgrade path to me. What worked for me was the following:
Remove the old DependencyResolver initialization code (for me this was causing the specific error you mention as in earlier versions of Ninject/WebApi2, putting these lines in the WebApiConfig.cs Register() method was how you initialized the DependencyResolver...this no longer is the case):
var kernel = new StandardKernel(); config.DependencyResolver = new NinjectDependencyResolver(kernel);
Install the Ninject.Web.WebApi.WebHost package. This installed the NinjectWebCommon.cs file. For me, just having the Ninject.Web.WebApi and it's dependencies didn't create this file.
My installed and working Ninject Packages for reference:
<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" />
Be sure that any old Ninject
or Ninject.Web.Common.*
dlls aren't present in your bin folder.
I had the same issue in my solution after I had uninstalled Ninject.Web.Common
, Ninject.Web.Common.WebHost
, Ninject.Web.WebApi
, and Ninject.MVC5
from Nuget and installed WebApiContrib.IoC.Ninject
in order to use GlobalConfiguration.Configuration.DependencyResolver
as in your example. I kept the version of Ninject
that I already had installed (which was indeed 3.2.2).
The error did not appear when I first made my changes. However, after moving around from a few git branches and back to my current work, I saw the error. The code that had run fine last week was now throwing the same exact error.
It seems that my bin folder had references to the old Ninject.*
packages I had removed. Upon deleting those files, my project worked as expected.
The cyclic dependency is between the classes "NinjectDefaultModelValidatorProvider" and "DefaultModelValidatorProviders".Simply add a binding for "DefaultModelValidatorProviders" on your startup like below:
_kernel.Bind<DefaultModelValidatorProviders>().ToConstant(new DefaultModelValidatorProviders(config.Services.GetServices(typeof (ModelValidatorProvider)).Cast<ModelValidatorProvider>()));
In my case it was working just fine in Owin Selfhost context, but not when hosted in IIS. My solution was to remove all Ninject related assemblies from nuget packages except Ninject itself.
Then I wrote my own DependencyResolver class, feel free to leave improvements in the comments.
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);
}
}
And then in your Owin Configuration method:
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);
This is what worked for me.
uninstall-package Ninject.Web.WebApi.WebHost
The above command uninstalled the version 'Ninject.Web.WebApi.WebHost 3.2.4.0' and the error is gone!!
Just reconfirm, I have installed the same package using the command
install-package Ninject.Web.WebApi.WebHost
and the command installed the package 'Ninject.Web.WebApi.WebHost 3.2.4.0' and the error reappeared.
var _surveyBusiness = _kernel.Get<ISurveyBusiness>();
_surveyBusiness.SomeFunc(user.CompanyId, user.UserId);
This is working also.
I fixed this by adding the following line in Global.asax
(where my StandardKernel
was being initialized):
kernel.Bind<DefaultModelValidatorProviders>().ToConstant(new DefaultModelValidatorProviders(GlobalConfiguration.Configuration.Services.GetModelValidatorProviders()));
来源:https://stackoverflow.com/questions/26312231/ninjectdependencyresolver-fails-binding-modelvalidatorprovider