如何在带有OWIN的ASP.NET MVC应用程序中添加Ninject控制器工厂?

3
我正在使用Visual Studio 2012 Premium、.NET Framework 4.5.1和C#开发一个ASP.NET Web Api 2.2项目。
我创建了一个空的ASP.NET MVC 5项目。我删除了Global.asax文件并创建了这个Startup.cs类:
using Microsoft.Owin;
using Ninject;
using Ninject.Web.Common.OwinHost;
using Ninject.Web.WebApi.OwinHost;
using Owin;
using System.Reflection;
using System.Web.Http;
using System.Web.Routing;
using MyProject.Web.API.App_Start;

[assembly: OwinStartup(typeof(MyProject.Web.API.Startup))]
namespace MyProject.Web.API
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            var webApiConfiguration = new HttpConfiguration();
            webApiConfiguration.Routes.MapHttpRoute(
                name: "Default",
                routeTemplate: "{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });

            webApiConfiguration.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            webApiConfiguration.Routes.MapHttpRoute(
                name: "ProductionOrderActionApi",
                routeTemplate: "api/MyProductionOrders/{orderNumber}/{action}",
                defaults: new { controller = "MyProductionOrders" });

            app.UseNinjectMiddleware(CreateKernel);
            app.UseNinjectWebApi(webApiConfiguration);
        }

        private static StandardKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());

            RegisterServices(kernel);

            return kernel;
        }

        private static void RegisterServices(IKernel kernel)
        {
            var containerConfigurator = new NinjectConfigurator();
            containerConfigurator.Configure(kernel);
        }
    }
}

该项目与 ApiController 类一起工作正常,但是当我尝试访问 Controller 时,出现以下错误:No Parameterless constructor defined for this object.
这是我的一个Controller之一:
public class MyController : Controller
{
    private readonly IExceptionLogHelper m_ExceptionLoggerHelper;
    private readonly IGenericRepository<MyModel> _myRepo;

    public MyController(
        IExceptionLogHelper exceptionLoggerHelper,
        IGenericRepository<MyModel> myModelRepo)
    {
        _exceptionLoggerHelper = exceptionLoggerHelper;
        _myRepo = myModelRepo;
    }

    //
    // GET: /UploadChinaCodes/
    public ActionResult Index()
    {
        return View();
    }
}

还有 NinjectConfigurator 类:

public class NinjectConfigurator
{
    public void Configure(IKernel container)
    {
        AddBindings(container);
    }

    private void AddBindings(IKernel container)
    {

        // Exception logger.
        container.Bind<IExceptionLogHelper>().To<ExceptionLogHelper>();

        // Repositories.
        container.Bind<IGenericRepository<MyModel>>().To<GenericRepository<MyModel>>();
    }
}

这些是安装的NuGet包:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="EntityFramework" version="6.1.2" targetFramework="net45" />
  <package id="log4net" version="2.0.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client.es" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core.es" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost.es" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net451" />
  <package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net451" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net451" />
  <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
  <package id="Ninject" version="3.2.2.0" targetFramework="net45" />
  <package id="Ninject.Extensions.ContextPreservation" version="3.2.0.0" targetFramework="net45" />
  <package id="Ninject.Extensions.NamedScope" version="3.2.0.0" targetFramework="net45" />
  <package id="Ninject.Web.Common" version="3.2.3.0" targetFramework="net45" />
  <package id="Ninject.Web.Common.OwinHost" version="3.2.3.0" targetFramework="net45" />
  <package id="Ninject.Web.WebApi" version="3.2.4.0" targetFramework="net45" />
  <package id="Ninject.Web.WebApi.OwinHost" version="3.2.4.0" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
</packages>

顺便说一下,我正在使用 Owin。我该如何解决这个问题?

你尝试过添加一个无参数的构造函数吗? - Alberto
@Alberto,OP不想要一个无参数的构造函数,只需要一个带参数的构造函数来注入依赖项。看起来Ninject没有被用作MVC控制器工厂。 - danludwig
事实上,我编写了“add”函数:无参数版本将被MVC内部或需要它的任何内容使用,而实际构造函数由Ninject或OWIN使用。 - Alberto
我已经添加了一个NinjectControllerFactory,但现在我又遇到了另一个问题:http://stackoverflow.com/questions/28827566/the-icontrollerfactory-ninjectcontrollerfactory-did-not-return-a-controller-for。我不知道是否需要删除这个问题。 - VansFannel
1个回答

3
你需要为Ninject创建一个自定义的DefaultControllerFactory:
using Ninject;
using System;
using System.Web.Mvc;

namespace MyProject.Web.API.Factories
{
    public class NinjectControllerFactory : DefaultControllerFactory
    {
        public IKernel Kernel { get; private set; }

        public NinjectControllerFactory(IKernel kernel)
        {
            this.Kernel = kernel;
        }

        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            IController controller = null;

            if (controllerType != null)
                controller = (IController)Kernel.Get(controllerType);

            return controller; 
        }
    }
}

并在Startup类上注册它:
using Microsoft.Owin;
using Ninject;
using Ninject.Web.Common.OwinHost;
using Ninject.Web.WebApi.OwinHost;
using Owin;
using System.Reflection;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using MyProject.Web.API.Factories;

[assembly: OwinStartup(typeof(MyProject.Web.API.Startup))]
namespace MyProject.Web.API
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            var webApiConfiguration = new HttpConfiguration();

            webApiConfiguration.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            webApiConfiguration.Routes.MapHttpRoute(
                name: "ProductionOrderActionApi",
                routeTemplate: "api/ProductionOrders/{orderNumber}/{action}",
                defaults: new { controller = "ProductionOrders" });

            app.UseNinjectMiddleware(CreateKernel);
            app.UseNinjectWebApi(webApiConfiguration);
        }

        private static StandardKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());

            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));
            RegisterServices(kernel);

            return kernel;
        }

        private static void RegisterServices(IKernel kernel)
        {
            var containerConfigurator = new NinjectConfigurator();
            containerConfigurator.Configure(kernel);
        }
    }
}

我已经在CreateKernel方法中添加了这一行代码:ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接