使用Ninject.Web.Mvc 2.0和ASP.NET MVC 1.0时出现"多个匹配的绑定可用"错误

Den*_*nko 30 asp.net-mvc ninject

最近我切换到Ninject 2.0版本并开始收到以下错误:

Error occured: Error activating SomeController
More than one matching bindings are available.
Activation path:
  1) Request for SomeController

Suggestions:
  1) Ensure that you have defined a binding for SomeController only once.

但是,我无法找到某种复制路径.有时它会发生,有时它不会发生.我正在使用NinjectHttpApplication自动控制器注入.控制器在单独的程序集中定义:

public class App : NinjectHttpApplication
{
    protected override IKernel CreateKernel()
    {
        INinjectModule[] modules = new INinjectModule[] {
            new MiscModule(),
            new ProvidersModule(),
            new RepositoryModule(),
            new ServiceModule()
        };

        return new StandardKernel(modules);
    }

    protected override void OnApplicationStarted()
    {
        RegisterRoutes(RouteTable.Routes);
        RegisterAllControllersIn("Sample.Mvc");
        base.OnApplicationStarted();
    }

    /* ............. */

}
Run Code Online (Sandbox Code Playgroud)

也许有人熟悉这个错误.

有什么建议?

小智 23

我终于最近想出了这个问题.显然,NinjectHttpApplication.RegisterAllControllersIn()函数不会执行所需的所有正确绑定.它将您的具体控制器实现绑定到IController请求.例如,如果您有一个名为SampleMvcController的控制器类,它继承自System.Web.Mvc.Controller.它将在应用程序启动期间执行以下命名绑定:

kernel.Bind<IController>().To(SampleMvcController).InTransientScope().Named("SampleMvc");
Run Code Online (Sandbox Code Playgroud)

但调试NinjectControllerFactory的时候,我发现,要求正在作出的Ninject内核返回一个对象类"SampleMvcController",而不是一个具体实现一个IController,采用了名为"SampleMvc"的结合.

因此,当涉及SampleMvcController的第一个Web请求生成时,它会创建SampleMvcController与其自身的绑定.但这不是线程安全的.因此,如果您同时发出多个Web请求,则绑定可能会多次发生,现在您因为SampleMvcController具有多个绑定而留下此错误.

您可以在使Web应用程序重新启动后立即通过快速刷新MVC URL来验证这一点.

修复:

解决此问题的最简单方法是为控制器绑定创建新的NinjectModule,并在应用程序启动期间加载此模块.在此模块中,您将自动绑定每个已定义的控制器,如下所示:

class ControllerModule : StandardModule {
      public override Load() {
        Bind<SampleMvcController>().ToSelf();
        Bind<AnotherMvcController>().ToSelf();
      }
    }
Run Code Online (Sandbox Code Playgroud)

但是如果您不介意更改Ninject源代码,可以修改RegisterAllControllersIn()函数以自动绑定它遇到的每个控制器.


Ste*_*ook 16

几个月来我一直在处理这个问题.我尝试了很多选择,但无法找到解决方案.我知道这是一个线程问题,因为只有当我的网站负载很重时才会发生.最近,在ninject源代码中报告并修复了一个错误,解决了这个问题.

以下是对该问题的参考.它在Ninject源的2.1.0.70版中得到修复.通过删除行,关键更改在KernelBase.cs中

context.Plan = planner.GetPlan(service);
Run Code Online (Sandbox Code Playgroud)

并替换它

lock (planner)
{
    context.Plan = planner.GetPlan(service);
}
Run Code Online (Sandbox Code Playgroud)

要在MVC中使用这个新版本,您需要获取Ninject的最新版本,然后获取ninject.web.mvc的最新版本.使用新的Ninject构建构建ninject.web.mvc.

我已经使用这个新版本大约一个星期,负载很重,没有问题.它是最长的没有问题所以我认为这是一个解决方案.