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 вы сейчас используете.