Подтвердить что ты не робот

NinjectDependencyResolver не удается привязать ModelValidatorProvider

Я разрабатываю ASP.NET Web Api 2.2 с С#,.NET Framework 4.5.1.

После обновления моего 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 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);
}

Он работает дважды. Первый serviceType - IFilterProvider, а второй раз serviceType - ModelValidatorProvider, и после этого я получаю исключение.

Это пакеты Ninject, которые я использую:

<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" />

Предыдущая версия для этих сборок:

<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" />

ВТОРОЕ ОБНОВЛЕНИЕ

Я обнаружил, что проблема в этом классе:

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 
    /// dependencies. Also configures the container as this
    /// application dependency resolver.
    /// </summary>
    public void Configure(IKernel container)
    {
        // Add all bindings/dependencies
        AddBindings(container);

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

И я использую WebContainerManager в классе, который наследует от 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);
    }
}

Итак, если я удалю WebContainerManager, я не получаю этот цикл.

4b9b3361

Ответ 1

У меня возникали все виды печали с инициализацией WebApi2 и Ninject после обновления пакетов Ninject (даже удаление и удаление старых).

В частности, в вашем случае я бы удалил эти строки кода:

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

поскольку они, вероятно, являются причиной ошибки (библиотеки NinjectWebCommon.cs и Ninject работают с инициализацией преобразователя зависимостей сейчас).


Для других, которые следовали аналогичному пути обновления ко мне. Что для меня работало:

  • Удалите старый код инициализации DependencyResolver (для меня это вызвало конкретную ошибку, которую вы упомянули, как в более ранних версиях Ninject/WebApi2, поместив эти строки в метод WebApiConfig.cs Register(), было то, как вы инициализировали 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" />

Ответ 2

Убедитесь, что в вашей папке bin нет старых Ninject или Ninject.Web.Common.* dll.

У меня была такая же проблема в моем решении после того, как я удалил Ninject.Web.Common, Ninject.Web.Common.WebHost, Ninject.Web.WebApi и Ninject.MVC5 из Nuget и установил WebApiContrib.IoC.Ninject, чтобы использовать GlobalConfiguration.Configuration.DependencyResolver, как в вашем примере. Я сохранил версию Ninject, которую я уже установил (что действительно было 3.2.2).

Ошибка, когда я впервые внес свои изменения. Однако, переместившись из нескольких ветвей git и вернувшись к моей текущей работе, я увидел ошибку. Код, который отлично работал на прошлой неделе, теперь бросает ту же самую точную ошибку.

Кажется, что моя папка bin имела ссылки на старые пакеты Ninject.*, которые я удалил. При удалении этих файлов мой проект работал как ожидалось.

Ответ 3

Циклическая зависимость между классами "NinjectDefaultModelValidatorProvider" и "DefaultModelValidatorProviders". Просто добавьте привязку для "DefaultModelValidatorProviders" при запуске, как показано ниже:

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

Ответ 4

В моем случае он отлично работал в контексте Owin Selfhost, но не при размещении в IIS. Мое решение состояло в том, чтобы удалить все связанные с Ninject сборки из пакетов nuget, кроме самого 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);

Ответ 5

Это то, что сработало для меня.

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" и возникла ошибка.

Ответ 6

var _surveyBusiness = _kernel.Get<ISurveyBusiness>();
_surveyBusiness.SomeFunc(user.CompanyId, user.UserId);

Это работает также.

Ответ 7

Я исправил это, добавив следующую строку в Global.asax (где инициализировался мой StandardKernel):

kernel.Bind<DefaultModelValidatorProviders>().ToConstant(new DefaultModelValidatorProviders(GlobalConfiguration.Configuration.Services.GetModelValidatorProviders()));