ASP.NET MVC 4 + Ninject MVC 3 = Нет конструктора без параметров, определенного для этого объекта

ОБНОВЛЕНИЕ. Пожалуйста, посмотрите мой ответ на ссылку и объяснение решения этой проблемы.

Прежде чем начать, я знаю, что это очень распространенный вопрос, и я использовал Ninject для многих лун без проблем, но теперь он появился, и я не могу понять, исправить. Кроме того, нет, ни один из результатов в Google и SO пока не помог мне.

Итак, рассмотрим следующий бит кода, запущенный очень, очень, очень простой прототип проекта ASP.NET MVC 4 из Visual Studio 2012 на Windows Server 2008 R2:

public class DefaultController : Controller {
    private IGroupPrincipalRepository GroupPrincipalRepository { get; set; }

    [Inject]
    public DefaultController(
        IGroupPrincipalRepository groupPrincipalRepository) {
        this.GroupPrincipalRepository = groupPrincipalRepository;
    }
}

И здесь метод NinjectWebCommon.cs RegisterServices:

kernel.Bind(typeof(IGroupPrincipalRepository)).ToConstructor(
    c =>
        new GroupPrincipalRepository(new PrincipalContext(ContextType.Domain, "?", "?", "?", "?"))).InSingletonScope();

Теперь так работают мои другие проекты, которые используют Ninject (но ASP.NET MVC 3 на .NET 4), и насколько я знаю, это то, что необходимо для того, чтобы все работало. Итак, почему я вдруг получаю No parameterless constructor, определенный для этого объекта. исключения?

UPDATE

Здесь полный файл NinjectWebCommon.cs:

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

namespace App_Start {
    using System;
    using System.DirectoryServices.AccountManagement;
    using System.Repositories.ActiveDirectory;
    using System.Web;
    using Microsoft.Web.Infrastructure.DynamicModuleHelper;
    using Ninject;
    using Ninject.Web.Common;

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

        public static void Start() {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop() {
            bootstrapper.ShutDown();
        }

        private static IKernel CreateKernel() {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }

        private static void RegisterServices(
            IKernel kernel) {
            kernel.Bind(typeof(IGroupPrincipalRepository)).ToConstructor(
                c =>
                    new GroupPrincipalRepository(new PrincipalContext(ContextType.Domain, "", "", "", ""))).InSingletonScope();
        }
    }
}

ОБНОВЛЕНИЕ. Пожалуйста, посмотрите мой ответ на ссылку и объяснение решения этой проблемы.

Ответ 1

Ну, у меня нет точного ответа, почему ошибка возникает, но я знаю, кто ее вызывает, и это Visual Studio 2012. Я установил Visual Studio 2010 на том же компьютере, что и в 2012 году, установленном ASP.NET MVC 4 за 2010 год, и я воссоздал проект 2012 года в 2010 году дословно, письмо для письма. Конечным результатом является то, что когда 2010 отлаживает проект, все работает отлично, а Ninject вводит зависимости так, как должно.

Когда 2012 отлаживает свой проект, он просто придумывает исключение No parameterless constructor defined for this object. Повторное таргетирование между .NET 4.0 и .NET 4.5 в 2012 году ничего не делает. Повторная установка Ninject из NuGet также не делает ничего. Я даже настроил проекты на 2010 и 2012 годы, чтобы использовать локальный сервер IIS, чтобы быть абсолютно уверенным, и конечный результат тот же.

Я собираюсь предположить, что есть ошибка с Visual Studio 2012 или с Ninject. Единственное различие между двумя проектами заключается в том, с какой IDE они работают, и проект 2012 года - это тот, который разбивается, поэтому я указываю пальцем на Visual Studio 2012.

UPDATE

Ребята. РЕБЯТА! Я столкнулся с этой проблемой AGAIN и нашел решение в другом вопросе SO: Ninject + MVC3 не вводит в контроллер.

В основном, это то, что отсутствует в Web.config, который заставляет его работать:

<dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

Я предполагаю, что это заставляет фреймворк быть в курсе контейнеров IoC, что позволяет Ninject, наконец, иметь возможность связывать. Хотя, я не могу не думать, что пакет Ninject NuGet должен искать существование переадресации связывания в Web.config и автоматически добавлять его. Это наверняка помогло бы с большим количеством волос, тянущимися по этой проблеме.

P.S. Проголосуйте сопли из этой должности, которую я связал, потому что она этого заслуживает!

Ответ 2

Я знаю, что это старый вопрос, но, похоже, нет реальных ответов, и я работал над проблемой, поэтому вот мое решение:

Создать пользовательский контроллер factory:

public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel ninjectKernel;
    public NinjectControllerFactory(IKernel kernel)
    {
        ninjectKernel = kernel;
    }
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        return (controllerType == null) ? null : (IController) ninjectKernel.Get(controllerType);
    }
}

Затем, если вы используете NinjectHttpApplication, добавьте следующую строку в OnApplicationStarted:

ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(Kernel));

Если вы не используете NinjectHttpApplication, добавьте эту строку где-нибудь после создания вашего ядра и передайте ссылку на свое только что созданное ядро.

Что это.

Ответ 3

Не изобретайте велосипед и просто попробуйте Install-Package Ninject.MVC3

Ответ 4

Я получил такое же сообщение об ошибке после получения MVC3 от NuGet.
Я не знаю, была ли у вас настройка вашего проекта так же, как и у меня, но мой web.config автоматически создается в зависимости от среды. MVC из NuGet добавляет rows (<runtime>) к web.config, и эти строки были удалены, так как мои конфигурационные файлы слияния не были настроены правильно.

Привет,

Ким

Ответ 5

Вот грязное решение! Поместите это

var type = typeof(Ninject.Web.Mvc.MvcModule);

в начале события AppStart (или где-либо еще)

Теперь позвольте мне объяснить, что это значит, если кто-то еще не обманул. Вещь - наш класс приложений http может находиться где угодно в решении. Не только в веб-приложении. И это очень важно потому что процедура компиляции asp.net отличается от обычных библиотечных приложений. Он охотно загружает ВСЕ ссылки на библиотеки через помощник BuildManager, в то время как обычно clr не загружает типы с начала, если они не используются напрямую.

Теперь вернемся к нашей ситуации: Ninject.Web.Mvc работает как динамический плагин, который не требует упоминания в коде. И, таким образом, он не загружается, если он был указан внутри библиотеки классов, что приводит к нарушенной инициализации Mvc.Dependancy.

Ответ 6

Проблема возникает, когда вы используете Visual Studio 2012/2013 с ASP.NET 4.0/4.5. Версия System.Web.Mvc была установлена ​​в 4.0.0.0 в файле Web.config. Это не работает.

Мое решение состояло в

  • удалить NinjectWebCommon.cs
  • скопируйте класс Dere Jone NinjectControllerFactory в проект:

    public class NinjectControllerFactory : DefaultControllerFactory
    {
       private IKernel ninjectKernel;
       public NinjectControllerFactory(IKernel kernel)
       {
          ninjectKernel = kernel;
       }
    
       protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
       {
          return (controllerType == null) ? null : (IController) ninjectKernel.Get(controllerType);
       }
    }
    
  • измените содержимое Global.asax на:

    public class MvcApplication : NinjectHttpApplication
    {
       protected override IKernel CreateKernel()
       {
           IKernel kernel = new StandardKernel();
    
           // kernel.Load(Assembly.GetExecutingAssembly());
    
           // kernel.Bind<ISomeClass>().To<SomeClass>();
    
           return kernel;
       }
    
       protected override void OnApplicationStarted()
       {
           AreaRegistration.RegisterAllAreas();
    
           WebApiConfig.Register(GlobalConfiguration.Configuration);
           FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
           RouteConfig.RegisterRoutes(RouteTable.Routes);
           BundleConfig.RegisterBundles(BundleTable.Bundles);
    
           ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(Kernel));
       }
    }
    

    после этого ваши инъекции должны работать.

Ответ 7

Все просто смешно, я переключился на Autofac, устал от того, что никогда не смог успешно добавить Ninject в проект. Веб-API, MVC4, MVC5 все проблемы.

Для людей MVC5, используя Ninject MVC3, добавьте следующее к уровню приложения web.config:

 <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-5.1.0.0" newVersion="5.1.0.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>

Ответ 8

Я вытягивал свои волосы на этом несколько часов в недавнем проекте, который я перешел из MVC 3 в MVC 4. Из-за отсутствия ответов на вопросы я решил, что это должно быть то, что я сделал, поскольку кажется, что Ninject.MVC3 пакет nuget будет работать отлично с MVC 4 - и действительно, он делает.

В моем случае я не полностью обновлял проект MVC3. После выполнения этого руководства У меня все получилось так, как ожидалось. Я предполагал, что мне не хватает переадресации связывания сборки.

Итак, если вы обновляете проект MVC 3 до MVC 4, используя Ninject и получая конструкцию без конструктора без параметров, надейтесь, что это поможет.

Ответ 9

Как и все предыдущие плакаты, это вызвало у меня седые волосы. В моем случае я слишком оптимизировал свои ссылки. Ninject. * Там был материал, но он искалечен. Я удалил все ссылки и очистил package.conf manualli и снова добавил пакеты - победа!

Ответ 10

У меня такая же проблема, и единственное, что работает для меня, - это изменить "Локальный веб-сервер IIS" в свойствах веб-проекта на "Использовать сервер разработки Visual Studio".

enter image description here

Я не знаю, почему, но когда я это делаю, мой пункт разрыва в NinjectWebCommon запущен. Как @Alex сказал, что-то с Visual Studio 2012 недостаточно ярким, чтобы выполнять код в NinjectWebCommon каждый раз, когда вы создаете приложение. Это также возможно, что это мне недостаточно, чтобы понять, как это работает под капотом.

Мне не нравится мое решение, потому что я бы предпочел использовать свой локальный веб-сервер IIS, но на данный момент у меня есть приложение для создания и много времени с этим $%?!!/bug..feature. Не уверен.

Ответ 11

Это было решено для меня, добавив ссылку через Nuget в Ninject.Web.MVC.

Ответ 12

Я пробовал все эти решения, но никто не работал.

Вот как я это решил: Удалены все файлы temp asp.net temp. После того, как я это сделал, у меня появились новые ошибки конфигурации. Я исправил их. Появилась последняя и настоящая ошибка: новый Bootstrapper() пытался загрузить более старую версию dll ninject. Удалены все пакеты ninject. Установленные пакеты ninject nuget по очереди, убедитесь, что установлена ​​правильная версия.

Ответ 13

Я попытался настроить Ninject с MVC 5. Наконец, мне пришлось сначала использовать решение с контроллером factory, а затем решение с привязкой переадресации. После этого все работает так, как ожидалось. Используется локальный сервер IIS.

Ответ 14

Мне удалось решить эту проблему в веб-проекте MVC5, удалив директиву #if #endif из моего конструктора контроллеров.

Ответ 15

Ярлык для всего этого: Загрузите один из следующих Nuget Pacakges:

  • Ninject.MVC3
  • Ninject.MVC5

Это позаботится о необходимости привязки.

Ответ 16

Я исправил мой, удалив Ninject MVC5 и установив Ninject MVC3 из Nuget.

MVC5 == Ninject.MVC5
MVC4 == Ninject.MVC3
MVC3 == Ninject.MVC3

Проверьте версию System.Web.MVC в ссылках, чтобы убедиться, какую версию MVC вы сейчас используете.