Ninject + MVC3 没有注入控制器
Posted
技术标签:
【中文标题】Ninject + MVC3 没有注入控制器【英文标题】:Ninject + MVC3 is not injecting into controller 【发布时间】:2012-12-29 21:14:47 【问题描述】:我使用了 NuGet Ninject MVC3 扩展,但无法根据请求将其注入控制器。它似乎没有绑定,因为 MVC 正在寻找无参数构造函数。这是堆栈跟踪:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +67
[InvalidOperationException: An error occurred when trying to create a controller of type 'MyApp.Presentation.Controllers.SearchController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +182
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +199
System.Web.Mvc.<>c__DisplayClass6.<BeginProcessRequest>b__2() +49
System.Web.Mvc.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a() +13
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func`1 func) +124
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862676
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
以及我尝试注入的控制器(目前它需要一个基类):
public class SearchController : MainBaseController
private readonly MyApp.Domain.Tutor.TutorSearch TutorSearch;
protected static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
[Ninject.Inject]
public SearchController(MyApp.Domain.Tutor.TutorSearch tutorSearch)
this.TutorSearch = tutorSearch;
.... (no other constructors)
还有我的 NinjectWebCommon.cs 的相关部分:
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;
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
INinjectModule[] modules = new INinjectModule[]
new Domain.DomainModule()
;
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Load(modules);
kernel.Bind<MyApp.Domain.Tutor.TutorSearch>().ToSelf();
// ***************
var t = kernel.Get<MyApp.Presentation.Controllers.SearchController>();
最后是DomainModule:
public class DomainModule : NinjectModule
public override void Load()
Bind<Data.Profile.IProfileProvider>().To<Data.Profile.XmlProfileProvider>();
Bind<Data.Subject.ISubjectProvider>().To<Data.Subject.XmlSubjectProvider>();
正如您在我的 NinjectWebCommon.cs 中标有星号的行中看到的那样,我已尝试将控制器显式构建为测试。使用正确注入的 Xml..Providers,这可以正常工作。
有什么我错过的吗?我对 NuGet MVC3 扩展的底层发生了什么了解不多,因此不知道控制器绑定在哪一点失败。
非常感谢任何有关查看内容的指针,谢谢。
【问题讨论】:
Traw,您使用具体实现而不是接口是否有特殊原因。??我添加了一个简短的草图,说明它的外观 【参考方案1】:所以经过一段时间的拼命修补,我终于找到了我的问题。 我正在引用 MVC4 (System.Web.Mvc) DLL,并且没有将旧 3.0.0.0 版本的绑定重定向到 4.0.0.0:
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="4.0.0.0" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="4.0.0.0" />
<!-- The following line was missing -->
<bindingRedirect oldVersion="3.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
至少,我希望这是一个不错的解决方案。
编辑:如下所示,以下行更简洁:
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
【讨论】:
这有助于解决我遇到的类似问题here...bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"
不会在一行中涵盖这三种情况吗?
在哪里可以找到这个文件?我也遇到了同样的问题。
没关系。我在另一个项目的 web-config 中找到了它。由于某种原因,我的配置的dependentAssembly 部分丢失了。
我真的希望这个问题能在 2053 年甚至更早之前得到解决。【参考方案2】:
使用 Visual Studio 和 Nuget 您需要运行此命令
安装包 Ninject.MVC3
(根据您运行的 MVC 版本替换 3)
这会解决你的问题
【讨论】:
这或多或少对我有用。我以为我安装了 Ninject.MVC5 (Ninject.Web.Mvc) 但事实并非如此。出于某种原因,我刚刚使用了 Ninject 和 Ninject.Web.Common。【参考方案3】:Traw,您使用具体实现而不是接口是否有特殊原因??就目前而言,您从直接 DI 类中获得零收益(我很惊讶您可以得到任何工作)我会重构并将所有内容放在接口后面,然后将接口绑定到具体实现.
以下是其外观的快速截图:
// 'imagined' ISearchType interface
public interface ISearchType
int Id get; set;
string LastName get; set;
// 'imagined' TutorSearch concrete class
public class TutorSearch : ISearchType
public int Id get; set;
public string LastName get; set;
// your revised controller code
private readonly ISearchType _tutorSearch;
public SearchController(ISearchType searchType)
_tutorSearch = searchType;
然后,在您注册服务(ninject)时,您将添加:
kernel.Bind<ISearchType>().To<TutorSearch>();
这应该让你更进一步。此外,var t = kernel.Get<...>
实际上什么也没做——以防万一你想知道“它”发生了什么。
玩得开心……
【讨论】:
嗨,吉姆。首先,感谢您的回复。我使用具体实现的原因是因为在这个阶段我还没有把它分解出来,并且有问题的类具有我希望注入的依赖项。我的印象是 Ninject 可以很好地注入一个具体的实现,或者不是这样吗? 'var t = kernel.Get<...>' 的行只是我在调试器中查看的一个测试,它运行良好 - Ninject 完美地构建了控制器。它只是没有根据网络请求。我也试过传递一个接口,得到了同样的结果! 嗨 Traw - 很高兴你的一切都按预期工作。但是,我不鼓励通过 ninject 注入具体类(即使可以)。你有什么优势??您最好在空构造函数中创建类,因为它永远不会改变实现。我的建议是从接口开始,并针对这些接口编写具体的实现。这将是最佳实践,因为您只需重构具体类中的代码。另外,对于单元测试,根据您提供的代码示例,您无法执行任何操作。 还有!!针对接口进行编码的另一个优点是,您可以将工作分包给其他开发人员,并且知道这些实现可以注入到现有功能中。如果你从这个线程中拿走任何东西,请向我保证你会重新开始并从接口开始工作 - 拜托,拜托了 :) 祝你好运.. 感谢 Jim 的热情恳求,请放心,我确实会在适当的时候从接口开始。在这种情况下,我没有,因为没有可预见的要求,我需要尽快运行的东西。我在这里注入它纯粹是因为我让 Ninject 注入它的依赖项,这些依赖项由较低层的模块提供。这允许表示层无需了解较低层的依赖关系。此外,它并不像看起来那么糟糕。我完全同意你所说的所有好处:)以上是关于Ninject + MVC3 没有注入控制器的主要内容,如果未能解决你的问题,请参考以下文章
中等信任中 MVC 控制器 + 依赖注入 (Ninject) 的问题