37

我已经设置了我的项目Ninject IoC
我的项目有常规Asp.Net MVC控制器和Web Api控制器。现在,Ninject适用于Web ApiNinject不适用于常规Asp.MVC控制器。
我的常规 MVC 控制器实现;

public class GalleryController : BaseController
{
    public GalleryController(IUow uow)
    {
        Uow = uow;
    }
    ........
}

与常规控制器一起使用时出错

An error occurred when trying to create a controller of type 'Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]

但是,当我使用Web Api尝试相同的代码时,它可以工作

public class GalleryController : BaseApiController
{
    public GalleryController(IUow uow)
    {
        Uow = uow;
    }
    ......
}

我的界面包含不同的存储库(工厂模式)

public interface IUow
{
    // Save pending changes to the data store.
    void Commit();

    //Repositoryries
    IRepository<Gallery> Gallery { get; }
    IMenuRepository Menus { get; }
}

NinjectDependencyScope班级;

public class NinjectDependencyScope : IDependencyScope
{
    private IResolutionRoot resolver;

    internal NinjectDependencyScope(IResolutionRoot resolver)
    {
        Contract.Assert(resolver != null);

        this.resolver = resolver;
    }

    public void Dispose()
    {
        var disposable = resolver as IDisposable;
        if (disposable != null)
            disposable.Dispose();

        resolver = null;
    }

    public object GetService(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");

        return resolver.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");

        return resolver.GetAll(serviceType);
    }
}

NinjectDependencyResolver班级;

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
    private IKernel kernel;

    public NinjectDependencyResolver(IKernel kernel)
        : base(kernel)
    {
        this.kernel = kernel;
    }

    public IDependencyScope BeginScope()
    {
        return new NinjectDependencyScope(kernel.BeginBlock());
    }
}

NinjectGlobal.asax 的配置;

public class IocConfig
{
    public static void RegisterIoc(HttpConfiguration config)
    {
        var kernel = new StandardKernel(); // Ninject IoC
        //kernel.Load(Assembly.GetExecutingAssembly()); //only required for asp.net mvc (not for webapi)
        // These registrations are "per instance request".
        // See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/

        kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
            .InSingletonScope();

        kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
        kernel.Bind<IUow>().To<Uow>();

        // Tell WebApi how to use our Ninject IoC
        config.DependencyResolver = new NinjectDependencyResolver(kernel);
    }
}

全球.asax

protected void Application_Start()
{

    // Tell WebApi to use our custom Ioc (Ninject)
    IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    GlobalConfig.CustomizeConfig(GlobalConfiguration.Configuration);
    AreaRegistration.RegisterAllAreas();
}
4

6 回答 6

33

我写了一些要点来帮助使用 MVC 和 Web Api 配置 Ninject。只需包含文件:

要为具体类型添加绑定,只需将它们放在Load()MainModule 的方法中。您可以创建任意数量的模块来保持绑定的组织性。但您还必须将它们添加到Modules属性中返回的数组中。

然后添加到Application_Start()方法中

  • NinjectContainer.RegisterModules(NinjectModules.Modules)(对于 MVC)
  • NinjectHttpContainer.RegisterModules(NinjectHttpModules.Modules)(对于 WebApi)

请注意,您可以将相同NinjectModules.Modules的内容用于 MVC 和 WebApi 注册。为了清楚起见,我只是将其分开

更新:记住从你的项目中删除 NinjectWebCommon.cs,因为它在运行时加载和引导一个新内核,不幸的是它只适用于 MVC。

更新:您也可以使用

  • NinjectContainer.RegisterAssembly()(对于 MVC)
  • NinjectHttpContainer.RegisterAssembly()(对于 WebApi)

这将扫描您当前的程序集以查找所有模块。这样,您可以将模块放在项目中的任何位置,并且将被注册

于 2013-06-23T02:52:57.023 回答
15

使用 MVC 5 和 Web API 2.2,我通过确保包含以下 NuGet 包解决了这个问题:

  • Ninject.MVC5
  • Ninject.Web.WebApi.WebHost用于 Web API

这安装了其他 Ninject 依赖项并允许我RegisterServices通过NinjectWebCommon.cs.

于 2015-05-29T17:15:27.220 回答
12

经过大量搜索,事实证明我们无法将 Ninject 与 web api 和常规 mvc 一起使用。我的意思是,我们必须单独配置存储库。

然后我找到了一篇很好的文章,它解释了如何将 Ninject 与 asp.net mvc 和 web api 一起使用:http: //www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc4-and- webapi-我们

现在,我没有得到错误,它正在工作:D

更新1:

还可以尝试使用 .NET Framework 4.5 在 MVC 4 Web API 中编写依赖注入的简单实现

于 2013-05-06T14:06:38.500 回答
6

这是对我来说很好的简单解决方案:

  1. 在 Visual Studio 中,创建名为 DemoApp 的新 Web 应用程序项目,并确保您已选择 Empty template with MVC and Web API references: 在此处输入图像描述
  2. 在包管理器控制台中一一执行:

    安装包 Ninject

    安装包 Ninject.MVC5

  3. 将 NinjectDependencyResolver.cs 添加到 IoC 文件夹:

    using Ninject;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http.Dependencies;
    
    namespace DemoApp.IoC
    {
        public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver
        {
            private readonly IKernel kernel;
    
            public NinjectDependencyResolver(IKernel kernel)
            {
                this.kernel = kernel;
            }
    
            public IDependencyScope BeginScope()
            {
                return this;
            }
    
            public object GetService(Type serviceType)
            {
                return kernel.TryGet(serviceType);
            }
    
            public IEnumerable<object> GetServices(Type serviceType)
            {
                return kernel.GetAll(serviceType);
            }
    
            public void Dispose() { } //it is not necessary to implement any dispose logic here
        }
    }
    
  4. 在 App_Start/NinjectWebCommon.cs 中进行以下更改:

    • 在 CreateKernel 方法中添加这些行:

      NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel); DependencyResolver.SetResolver(ninjectResolver); //MVC GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //网络接口

    • 在 RegisterServices 方法中添加您的绑定,例如:

      kernel.Bind<IHelloService>().To<HelloService>();

现在 NinjectWebCommon.cs 应该如下所示:

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DemoApp.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(DemoApp.App_Start.NinjectWebCommon), "Stop")]

namespace DemoApp.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;
    using DemoApp.IoC;
    using System.Web.Mvc;
    using System.Web.Http;
    using DemoApp.Config;

    public static class NinjectWebCommon 
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start() 
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

                RegisterServices(kernel);

                NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
                DependencyResolver.SetResolver(ninjectResolver); //MVC
                GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API

                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IHelloService>().To<HelloService>();
        }        
    }
}
  1. 只是为了示例的完整性,添加一些 Mvc 和 Api 控制器,以及 IHelloService、HelloService 的代码:

家庭控制器.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DemoApp.Config;
namespace DemoApp.Controllers
{
    public class HomeController : Controller
    {
        private IHelloService helloService;

        public HomeController(IHelloService helloService)
        {
            this.helloService = helloService;
        }

        // GET: /Home/
        public string Index()
        {
            return "home/index: " + helloService.GetMessage();
        }
    }
}

用户控制器.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using DemoApp.Config;
namespace DemoApp.Controllers
{
    public class UserController : ApiController
    {
        private IHelloService helloService;

        public UserController(IHelloService helloService)
        {
            this.helloService = helloService;
        }

        [HttpGet]
        public string Data()
        {
            return "api/user/data: " + helloService.GetMessage();
        }
    }
}

IHelloService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
    public interface IHelloService
    {
       string GetMessage();
    }
}

HelloService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
    public class HelloService : IHelloService
    {
        public string GetMessage()
        {
            return "Hi";
        }
    }
}
  1. 最终结构应如下所示: 在此处输入图像描述

    现在在浏览器中进行一些测试。对我来说是:

    http://localhost:51156/home/index

    http://localhost:51156/api/user/data

就是这样。

于 2016-12-27T03:04:01.597 回答
0

我认为问题在于您没有注册一个使用 Ninject 构建控制器(并解决它们的依赖关系)的 ControllerFactory,您是否尝试过实现自己的 ControllerFactory?另请参阅此处http://bubblogging.wordpress.com/2012/06/04/mvc-controller-factory-ninject/

于 2013-05-05T09:25:53.930 回答
0

Nenad 有一个更优雅的解决方案 - 我花了 3 个额外的小时,因为我首先尝试在这里实施与我现有的基础设施相冲突的解决方案。这是对另一个堆栈溢出问题的答复。我在这里复制这个答案,以防它帮助其他人节省我失去的时间。


有一种方法可以在 MVC 和 ASP.NET Web API 之间共享相同的容器。您只需要实现这两个接口。

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
   {
       private readonly IKernel kernel;

       public NinjectDependencyResolver(IKernel kernel)
           : base(kernel)
       {
           this.kernel = kernel;
       }

       public IDependencyScope BeginScope()
       {
           return new NinjectDependencyScope(this.kernel.BeginBlock());
       }
   }

查看这篇文章以获取解决方案: 在 MVC 和 Web API 之间共享依赖解析器的简单方法

于 2016-10-21T11:31:39.340 回答