C# ASP.NET MVC4 中的 Ninject
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11470243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ninject in ASP.NET MVC4
提问by VulgarBinary
So after much screwing around I finally got Ninject wired in and compiling in my MVC4 application. The problem I was running into is the IDependencyScope interface no longer exists from what I can tell and the System.Web.Http.Dependencies namespace was done away with.
因此,经过一番折腾之后,我终于将 Ninject 连接起来并在我的 MVC4 应用程序中进行编译。我遇到的问题是,据我所知,IDependencyScope 接口不再存在,并且 System.Web.Http.Dependencies 命名空间已被取消。
So, my problem now is I have everything wired in and upon running the application I get:
所以,我现在的问题是我已经连接好所有东西,并且在运行应用程序时我得到:
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
Which I haven't been able to track down or even begin to fathom where it is coming from.
我一直无法追踪甚至开始理解它的来源。
My standard Ninject methods inside the Global.asax.cs look as follows:
我在 Global.asax.cs 中的标准 Ninject 方法如下所示:
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();
}
And my custom resolver:
还有我的自定义解析器:
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.
}
}
Any insight here would be greatly appreciated. I've spent far too much time already trying to get any DI framework wired into the latest MVC4 RC running on .NET 4.5 and have now just reached my tolerance level for things just not working at all..
这里的任何见解将不胜感激。我已经花了太多时间试图将任何 DI 框架连接到在 .NET 4.5 上运行的最新 MVC4 RC 中,现在刚刚达到我对根本无法工作的事情的容忍度..
Edit #1A little further research digging around in github the ExtensionsForIEnumerableOfT.cs doesn't help much:
编辑 #1进一步研究在 github 中挖掘 ExtensionsForIEnumerableOfT.cs 并没有多大帮助:
And possibly if I had wrote it myself I would begin to understand this but Bootstrapper.cs doesn't help too much either.
如果我自己写的话,我可能会开始理解这一点,但 Bootstrapper.cs 也没有太大帮助。
https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs
https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs
Hoping these details will make it easier for any of you who might have more experience with Ninject.
希望这些细节能让您对 Ninject 有更多经验的人更容易。
Edit #2The error encountered is specifically in NinjectMvcHttpApplicationPlugin.cs:
编辑 #2遇到的错误特别是在 NinjectMvcHttpApplicationPlugin.cs 中:
The offending line is:
违规行是:
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
Which lives in the following method:
其中存在以下方法:
public void Start()
{
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
DependencyResolver.SetResolver(this.CreateDependencyResolver());
RemoveDefaultAttributeFilterProvider();
}
The ModelValidatorProviders collection contains 2 elements: {System.Web.Mvc.DataErrorInfoModelValidatorProvider} {System.Web.Mvc.ClientDataTypeModelValidatorProvider}
ModelValidatorProviders 集合包含 2 个元素:{System.Web.Mvc.DataErrorInfoModelValidatorProvider} {System.Web.Mvc.ClientDataTypeModelValidatorProvider}
And it's trying to remove a single instance of:
它试图删除单个实例:
System.Web.Mvc.DataAnnotationsModelValidatorProvider
System.Web.Mvc.DataAnnotationsModelValidatorProvider
Which apparently isn't loaded up in the ModelValidationProviders.Providers collection. Any ideas from here?
这显然没有在 ModelValidationProviders.Providers 集合中加载。来自这里的任何想法?
Resolution to Above Exception And Onto The Next
解决上述异常和下一个
To resolve the issue in the ModelValidatorProviders I had to manually add an object it was expecting. So now my CreateKernel method looks like:
为了解决 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;
}
Now it runs and gets into the actual guts of Ninject but still has an issue, one that makes no sense yet again:
现在它运行并进入了 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.
采纳答案by VulgarBinary
Ok after beating my head against the wall for far too long I figured out what was going on. The default project type for MVC4 running on .NET 4.5 had a reference to the original RC version of System.Web.Http instead of the updated version.
好吧,在将我的头撞在墙上太久之后,我弄清楚发生了什么。在 .NET 4.5 上运行的 MVC4 的默认项目类型引用了 System.Web.Http 的原始 RC 版本,而不是更新版本。
Namespaces were missing, objects didn't exist, life was not good.
命名空间丢失,对象不存在,生活不好。
Steps for resolution:
解决步骤:
- Remove your reference to System.Web.Http in your MVC4 project
- Add Reference -> System.Web.Http
- Delete all work arounds you put in to get the old garbage version of System.Web.Http to work
Reapply standard process to wire in Ninject.
HOWEVER, the error of:
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.
- 在 MVC4 项目中删除对 System.Web.Http 的引用
- 添加参考 -> System.Web.Http
- 删除您投入的所有变通方法,以使 System.Web.Http 的旧垃圾版本正常工作
在 Ninject 中重新应用标准流程进行接线。
但是,错误如下:
异常详细信息:Ninject.ActivationException:激活 IntPtr 时出错 没有可用的匹配绑定,并且类型不可自绑定。激活路径: 3)将依赖IntPtr注入到Func{IKernel}类型的构造函数的参数方法中 2)将依赖Func{IKernel}注入到HttpApplicationInitializationHttpModule类型的构造函数的参数lazyKernel中 1)请求IHttpModule
建议: 1) 确保您已经为 IntPtr 定义了一个绑定。2) 如果绑定是在模块中定义的,请确保该模块已加载到内核中。3) 确保您没有意外创建多个内核。4) 如果您使用构造函数参数,请确保参数名称与构造函数参数名称匹配。5) 如果您使用自动模块加载,请确保搜索路径和过滤器正确。
UpdateThis was solved by updating MVC from MVC4 Beta to MVC4 RC.
更新这是通过将 MVC 从 MVC4 Beta 更新到 MVC4 RC 来解决的。
回答by anAgent
Check out the Pro ASP.NET MVC 3 book. I just ported this code over from MVC3 to MVC4 last night and works correctly. Page 322 to be exact.
查看Pro ASP.NET MVC 3 书籍。我昨晚刚刚将这段代码从 MVC3 移植到 MVC4 并且工作正常。准确地说是第 322 页。
What I don't see is where you are mapping your Interface to your concrete items.
我没有看到您将界面映射到具体项目的位置。
Bind<ISomething>().To<Something>();
Add another constructor and add the method that calls your mapping;
添加另一个构造函数并添加调用您的映射的方法;
public NinjectDependencyResolver() {
_kernal = new StandardKernel();
RegisterServices(_kernel);
}
public static void RegisterServices(IKernel kernel) {
kernel.Bind<ISomething>().To<Something>();
}
Here's what a resolver could/should look like;
这是解析器可以/应该是什么样子;
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 -
Global.Asx -
Application_Start()
Application_Start()
method
方法
DependencyResolver.SetResolver(new NinjectDependencyResolver());
That's it.
就是这样。
UPDATED 11/14/2012
2012 年 11 月 14 日更新
On a side note, if you're working with MVC WebAPI, you will want to use WebApiContrib.IoC.Ninjectfrom nuget. Also, check out the "Contact Manager" in their samples asp.net.com. This helped to cleanup the implementation of Ninject
在一个侧面说明,如果你使用MVC的WebAPI的工作,你会希望使用WebApiContrib.IoC.Ninject从的NuGet。另外,请查看他们的示例asp.net.com 中的“Contact Manager” 。这有助于清理 Ninject 的实现
回答by user2035720
When you will install latest Ninject.MVC3 from NuGet package we find following code on top of the NinjectWebCommon.csfile:
当您从 NuGet 包安装最新的 Ninject.MVC3 时,我们会在NinjectWebCommon.cs文件顶部找到以下代码:
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]
in this case we dont need to register ninject explicitly in global.asax
在这种情况下,我们不需要在 global.asax 中显式注册 ninject
I found a good content on using Ninject with MVC 4 here
我在这里找到了关于在 MVC 4 中使用 Ninject 的好内容
回答by Frederik Struck-Sch?ning
I tend to keep my Ninject bootstrapping in a separate project. In order to use the .InRequestScope()extension method of IBindingInSyntax<T>, I had added via Nuget the Ninject.Web.Commonlibrary. Alas, this library includes the app_start bootstrapper, resulting in duplicate NinjectWebCommon classes and attachment via WebActivator (1 in said project and 1 in the MVC project itself).
我倾向于在一个单独的项目中保持我的 Ninject 引导。为了使用 的.InRequestScope()扩展方法IBindingInSyntax<T>,我通过 Nuget 添加了Ninject.Web.Common库。唉,这个库包含 app_start 引导程序,导致重复的 NinjectWebCommon 类和通过 WebActivator 的附件(所述项目中的 1 个,MVC 项目本身中的 1 个)。
I deleted the duplicate App_Start folder from my bootstrap project, and this solved it.
我从我的引导项目中删除了重复的 App_Start 文件夹,这解决了它。
回答by Naga
I have come across the same issue not quite sure what has fixed after below changes
我遇到了同样的问题,不太确定以下更改后修复了什么
added Ninject.MVC4 to project
将 Ninject.MVC4 添加到项目中
deleted NinjectWebCommon.cs (the generated file, as the integration already exists in global.ascx.cs file)
删除了 NinjectWebCommon.cs(生成的文件,因为集成已经存在于 global.ascx.cs 文件中)
回答by Saurabh Mehndiratta
I am using DD4T, and encountered same error.
我正在使用 DD4T,但遇到了同样的错误。
After confirming that all packages are installed by nuget package manager, I found that some of the DLLs/references were missing (newtonsoft etc):
在确认所有包都由 nuget 包管理器安装后,我发现缺少一些 DLL/引用(newtonsoft 等):
Then, after re-installing Newtonsoft.Json (to re-install package use following command in Nuget Package Manager:Update-Package –reinstall Newtonsoft.Json), and putting netrtsn.dll from Tridion Deployer bin, I got this error - "Sequence contains no elements" with exactly same stack trace as given in this question.
然后,在重新安装 Newtonsoft.Json(在 Nuget 包管理器中使用以下命令重新安装包:Update-Package –reinstall Newtonsoft.Json)并将 netrtsn.dll 从 Tridion Deployer bin 放入后,我收到此错误 - “Sequence不包含任何元素”,堆栈跟踪与此问题中给出的完全相同。
Thanks to Naga, for providing this resolution deleted NinjectWebCommon.cs (the generated file, as the integration already exists in global.ascx.cs file), and wohooooo!!!! all errors resolved, Tridion + MVC4 = DD4T is running fine now.
感谢 Naga,提供这个解决方案删除了 NinjectWebCommon.cs(生成的文件,因为集成已经存在于 global.ascx.cs 文件中),和 woohooooo!!!!所有错误都解决了,Tridion + MVC4 = DD4T 现在运行良好。
回答by fordareh
I have also had this problem when I used nuget to install Ninject.MVC4 in a project referenced by my actual MVC website project.
当我在我的实际 MVC 网站项目引用的项目中使用 nuget 安装 Ninject.MVC4 时,我也遇到了这个问题。
The trouble is that the NinjectWebCommon.cs file automatically installed in the App_Start directory of the referenced project conflicts with the (actual, useful) one installed in my website project. Removing the NinjectWebCommon.cs file from the referenced project resolves the error.
问题是引用项目的App_Start目录下自动安装的NinjectWebCommon.cs文件与我网站项目中安装的(实际的,有用的)冲突了。从引用的项目中删除 NinjectWebCommon.cs 文件可解决错误。
回答by 1_bug
Just delete NinjectWebCommon.csfile from your project (it is in App_Startfolder). and everything should be working.
只需NinjectWebCommon.cs从您的项目中删除文件(它在App_Start文件夹中)。一切都应该正常工作。
Source: http://mlindev.blogspot.com.au/2012/09/how-to-implement-dependency-injection.html
来源:http: //mlindev.blogspot.com.au/2012/09/how-to-implement-dependency-injection.html

