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

Ninject в ASP.NET MVC4

Итак, после многократного прикручивания я наконец получил Ninject, подключенный и компилирующийся в моем приложении MVC4. Проблема, с которой я столкнулся, - это интерфейс IDependencyScope, который больше не существует из того, что я могу сказать, и пространство имен System.Web.Http.Dependencies было устранено.

Итак, теперь моя проблема заключается в том, что у меня все подключено и после запуска приложения я получаю:

    Sequence contains no elements

    [InvalidOperationException: Sequence contains no elements]
   System.Linq.Enumerable.Single(IEnumerable`1 source) +379
   Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:53
   Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:52
   Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:31
   Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:53
   Ninject.Web.Common.NinjectHttpApplication.Application_Start() in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\NinjectHttpApplication.cs:81

Который я не смог отследить или даже начать понимать, откуда он.

Мои стандартные методы Ninject внутри Global.asax.cs выглядят следующим образом:

        protected override IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());
            kernel.Bind<IRenderHelper>().To<RenderHelper>();

            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
            return kernel;
        }

        protected override void OnApplicationStarted()
        {
            base.OnApplicationStarted();
            AreaRegistration.RegisterAllAreas();
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            BundleTable.Bundles.RegisterTemplateBundles();
        }

И мой пользовательский резольвер:

public class NinjectDependencyResolver : IDependencyResolver
{
    private readonly IKernel _kernel;

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

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

     public IEnumerable<object> GetServices(Type serviceType)
     {
         try
         {
             return _kernel.GetAll(serviceType);
         }
         catch (Exception)
         {
             return new List<object>();
         }
     }

     public void Dispose()
     {
         // When BeginScope returns 'this', the Dispose method must be a no-op.
     }
}

Любое понимание здесь было бы весьма признательным. Я потратил слишком много времени, пытаясь заставить любую инфраструктуру DI подключиться к последнему MVC4 RC, работающему на .NET 4.5, и теперь только что достиг уровня допуска, поскольку вещи просто не работают вообще.

Изменить # 1 Немного дальнейших исследований, копающихся в github, ExtensionsForIEnumerableOfT.cs не очень помогает:

https://github.com/ninject/ninject/blob/master/src/Ninject/Infrastructure/Language/ExtensionsForIEnumerableOfT.cs

И, возможно, если бы я сам написал это, я бы начал понимать это, но Bootstrapper.cs тоже не слишком помогает.

https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs

Надеясь, что эти подробности облегчат вам любого из вас, у кого может быть больше опыта с Ninject.

Изменить # 2 Произошла ошибка, особенно в NinjectMvcHttpApplicationPlugin.cs:

Строка нарушения:

ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());

Что живет в следующем методе:

public void Start()
{
    ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
    DependencyResolver.SetResolver(this.CreateDependencyResolver());
    RemoveDefaultAttributeFilterProvider();
}

Коллекция ModelValidatorProviders содержит 2 элемента: {} System.Web.Mvc.DataErrorInfoModelValidatorProvider {System.Web.Mvc.ClientDataTypeModelValidatorProvider}

И он пытается удалить один экземпляр:

System.Web.Mvc.DataAnnotationsModelValidatorProvider

Который, по-видимому, не загружен в коллекцию ModelValidationProviders.Providers. Любые идеи отсюда?

Разрешение выше исключения и на следующий

Чтобы решить проблему в ModelValidatorProviders, мне пришлось вручную добавить объект, который он ожидал. Итак, теперь мой метод CreateKernel выглядит так:

protected override IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());

    kernel.Bind<IRenderHelper>().To<RenderHelper>();
    kernel.Unbind<IDocumentViewerAdapter>();

    GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
    ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
    FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
    return kernel;
}

Теперь он запускается и попадает в настоящие кишки Ninject, но все еще имеет проблему, которая еще не имеет смысла:

Exception Details: Ninject.ActivationException: Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
 3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
 2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
 1) Request for IHttpModule

Suggestions:
 1) Ensure that you have defined a binding for IntPtr.
 2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
 3) Ensure you have not accidentally created more than one kernel.
 4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
 5) If you are using automatic module loading, ensure the search path and filters are correct.
4b9b3361

Ответ 1

Хорошо, когда я слишком долго бился головой о стену, я понял, что происходит. Тип проекта по умолчанию для MVC4, работающего на .NET 4.5, имел ссылку на исходную версию RC System.Web.Http вместо обновленной версии.

Пространства имен отсутствовали, объектов не было, жизнь не была хорошей.

Шаги для разрешения:

  • Удалите свою ссылку на System.Web.Http в проекте MVC4.
  • Добавить ссылку → System.Web.Http
  • Удалите все работы, которые вы вложили, чтобы получить старую мусорную версию System.Web.Http для работы
  • Повторите стандартный процесс для проводки в Ninject.

    ОДНАКО, ошибка:

    Сведения об исключении: Ninject.ActivationException: ошибка активации IntPtr Нет соответствующих привязок, и тип не является самопереключаемым. Путь активации:  3) Инъекция зависимости IntPtr в параметр-метод конструктора типа Func {IKernel}  2) Инъекция зависимости Func {IKernel} в параметр lazyKernel конструктора типа HttpApplicationInitializationHttpModule  1) Запрос для IHttpModule

    Предложения:  1) Убедитесь, что вы определили привязку для IntPtr.  2) Если привязка была определена в модуле, убедитесь, что модуль загружен в ядро.  3) Убедитесь, что вы случайно не создали более одного ядра.  4) Если вы используете аргументы конструктора, убедитесь, что имя параметра соответствует имени параметра конструктора.  5) Если вы используете автоматическую загрузку модуля, убедитесь, что путь поиска и фильтры правильные.

Обновление. Это было решено путем обновления MVC от бета-версии MVC4 до MVC4 RC.

Ответ 2

Просмотрите Pro ASP.NET MVC 3 книгу. Я просто портировал этот код с MVC3 на MVC4 прошлой ночью и работает правильно. А точнее.

То, что я не вижу, это то, где вы привязываете свой интерфейс к вашим конкретным элементам.

Bind<ISomething>().To<Something>();

Добавьте еще один конструктор и добавьте метод, который вызывает ваше сопоставление;

public NinjectDependencyResolver() {
    _kernal = new StandardKernel();
    RegisterServices(_kernel);
}

public static void RegisterServices(IKernel kernel) {
    kernel.Bind<ISomething>().To<Something>();
}

Здесь может/должен выглядеть должен быть распознаватель;

   public class NinjectDependencyResolver : IDependencyResolver {
    private IKernal _kernel;

    public NinjectDependencyResolver(){
        _kernal = StandardKernal();
        AddBindings();
    }

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

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

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

    public IBindingToSyntax<T> Bind<T>() {
      return _kernal.Bind<T>();
    }

     public static void RegisterServices(IKernel kernel){
      //Add your bindings here. 
      //This is static as you can use it for WebApi by passing it the IKernel
     }
}

Global.Asx -

Application_Start()

Метод

DependencyResolver.SetResolver(new NinjectDependencyResolver());

Что это.


ОБНОВЛЕНО 11/14/2012

На стороне примечания, если вы работаете с MVC WebAPI, вы захотите использовать WebApiContrib.IoC.Ninject из nuget. Кроме того, ознакомьтесь с "Диспетчером контактов" в своих образцах asp.net.com. Это помогло очистить реализацию Ninject

Ответ 4

Когда вы установите последнюю версию Ninject.MVC3 из пакета NuGet, мы найдем следующий код поверх файла NinjectWebCommon.cs:

[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]

[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]

в этом случае нам не нужно явно регистрировать ninject в global.asax

Я нашел хорошее содержание при использовании Ninject с MVC 4 здесь

Ответ 5

Я, как правило, сохраняю загрузку Ninject в отдельном проекте. Чтобы использовать метод расширения .InRequestScope() IBindingInSyntax<T>, я добавил через Nuget библиотеку Ninject.Web.Common. Увы, эта библиотека включает в себя загрузчик app_start, в результате чего дублируются классы и вложение NinjectWebCommon через WebActivator (1 в указанном проекте и 1 в самом проекте MVC).

Я удалил дублируемую папку App_Start из моего проекта начальной загрузки, и это решило его.

Ответ 6

Я столкнулся с одной и той же проблемой, не совсем уверенной, что зафиксировано после изменений ниже.

добавлен проект Ninject.MVC4 для проекта

удален NinjectWebCommon.cs(сгенерированный файл, поскольку интеграция уже существует в файле global.ascx.cs)

Ответ 7

Я использую DD4T и столкнулся с такой же ошибкой.

После подтверждения того, что все пакеты установлены менеджером пакетов nuget, Я обнаружил, что некоторые библиотеки DLL/ссылки отсутствовали (newtonsoft и т.д.):

Затем, после повторной установки Newtonsoft.Json(для повторной установки пакета используйте следующую команду в диспетчере пакетов Nuget: Update-Package -reinstall Newtonsoft.Json), и, поместив netrtsn.dll из bin Tridion Deployer, я получил эту ошибку - "Последовательность не содержит элементов" с точно такой же трассировкой стека, как указано в этом вопросе.

Благодаря Наге за предоставление этой резолюции удаленный NinjectWebCommon.cs(сгенерированный файл, поскольку интеграция уже существует в файле global.ascx.cs), и wohooooo!!!! все ошибки решены, Tridion + MVC4 = DD4T работает нормально сейчас.

Ответ 8

У меня также была эта проблема, когда я использовал nuget для установки Ninject.MVC4 в проекте, на который ссылается мой фактический проект веб-сайта MVC.

Проблема заключается в том, что файл NinjectWebCommon.cs, автоматически установленный в каталоге App_Start указанного проекта, конфликтует с (фактическим, полезным), установленным в моем проекте веб-сайта. Удаление файла NinjectWebCommon.cs из указанного проекта устраняет ошибку.