【问题标题】:Ninject and ASP.NET Web APINinject 和 ASP.NET Web API
【发布时间】:2012-07-25 15:08:29
【问题描述】:

在我提出问题之前,您应该知道我从这个页面获得了我当前的代码: http://www.strathweb.com/2012/05/using-ninject-with-the-latest-asp-net-web-api-source/

我正在尝试通过使用上述网站上的 IDependencyResolver 适配器在我的应用程序中使用 ASP.NET Web API 和 Ninject。

我创建了所有代码,就像它在网站上显示的那样,它可以工作,但是当我加载我的应用程序时,我的常规控制器失败并显示此错误:

[MissingMethodException: No parameterless constructor defined for this object.]
[InvalidOperationException: An error occurred when trying to create a controller of type 'AccountManager.Controllers.HomeController'...

所以,我似乎可以将 Ninject 与常规控制器或 Web API 控制器一起使用,但不能同时使用两者。 :(

这是我的代码:

NinjectResolver.cs

public class NinjectResolver : NinjectScope, IDependencyResolver
{
    private IKernel _kernel;

    public NinjectResolver(IKernel kernel)
        : base(kernel)
    {
        _kernel = kernel;
    }

    public IDependencyScope BeginScope()
    {
        return new NinjectScope(_kernel.BeginBlock());
    }
}

NinjectScope.cs

public class NinjectScope : IDependencyScope
{
    protected IResolutionRoot resolutionRoot;

    public NinjectScope(IResolutionRoot kernel)
    {
        resolutionRoot = kernel;
    }

    public object GetService(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).SingleOrDefault();
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).ToList();
    }

    public void Dispose()
    {
        IDisposable disposable = (IDisposable)resolutionRoot;
        if (disposable != null) disposable.Dispose();
        resolutionRoot = null;
    }
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    private void SetupDependencyInjection()
    {
        //create Ninject DI Kernel
        IKernel kernel = new StandardKernel();

        //register services with Ninject DI container
        RegisterServices(kernel);

        //tell asp.net mvc to use our Ninject DI Container
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
    }
}

AccountingController.cs

public class AccountingController : ApiController
{
    private ICustomerService _customerService;

    public AccountingController(ICustomerService service)
    {
        _customerService = service;
    }

    // GET /api/<controller>/5
    public string Get(int id)
    {
        return "value";
    }
}

【问题讨论】:

  • 之前没用过 Ninject,但是有什么原因你不能在 Ninject 试图注入的类型上添加无参数构造函数?
  • @Charleh:这将违背 IoC 容器的目的。

标签: c# asp.net-mvc ninject


【解决方案1】:

在调用 RegisterServices(kernel); 之前,将以下代码行插入到 CreateKernel() 方法中。

GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);

您还需要使用下面的代码,我更喜欢在同一个类中定义它。

public class NinjectResolver : NinjectScope, IDependencyResolver
{
    private IKernel _kernel;
    public NinjectResolver(IKernel kernel)  : base(kernel)
    {
        _kernel = kernel;
    }
    public IDependencyScope BeginScope()
    {
        return new NinjectScope(_kernel.BeginBlock());
    }
}

public class NinjectScope : IDependencyScope
{
    protected IResolutionRoot resolutionRoot;
    public NinjectScope(IResolutionRoot kernel)
    {
        resolutionRoot = kernel;
    }
    public object GetService(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).SingleOrDefault();
    }
    public IEnumerable<object> GetServices(Type serviceType)
    {
        IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
        return resolutionRoot.Resolve(request).ToList();
    }
    public void Dispose()
    {
        IDisposable disposable = (IDisposable)resolutionRoot;
        if (disposable != null) disposable.Dispose();
        resolutionRoot = null;
    }
}

运行它,它应该可以工作。这对我有用,我希望它也对你有用。

进一步阅读:

Using Ninject – Dependency Injection with ASP.NET Web API controllers

【讨论】:

    【解决方案2】:

    我有一个 Web API 项目,它使用与你在 strathweb 中完全相同的解决方案工作,所以我只是在项目中添加了一个普通控制器,它确实可以工作。它本身对你没有很大的帮助,所以我将详细说明我的设置:

    我安装了以下软件包(在 IOC 方面):

    • Ninject 3.0.1.10
    • Ninject MVC 3.0.0.6
    • Ninject.Web.Common 3.0.0.7
    • WebActivator 1.5.1

    我的 Global.asax.cs 文件中完全没有关于 Ninject 的内容,而是使用安装 Ninject 时在 App_Start 中自动创建的 NinjectWebCommon.cs 文件。我不知道你的全局文件中有代码是否意味着 Ninject 没有在你的项目中正确设置自己?

    这是 NinjectWebCommon.cs 中的代码:

        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();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
    
            RegisterServices(kernel);
    
            GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(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)
        {
            kernel.Bind<IUserRepository>().To<UserRepository>().InSingletonScope();
            kernel.Bind<IUserManager>().To<UserManager>();
        }        
    }
    

    我可以看到我们的代码之间的另一个区别,我在其中创建内核,我的代码声明了两个到内核的绑定。

    这是我的测试控制器的代码,我可以在构造函数中设置一个断点并得到它:

    public class TestController : Controller
    {
        IUserManager _userManager;
    
        public TestController(IUserManager userManager)
        {
            _userManager = userManager;
        }
    
        //
        // GET: /Test/
        public ActionResult Index()
        {
            return View();
        }
    }
    

    这适用于我的 Controller 和我的 APIControllers。

    【讨论】:

      猜你喜欢
      • 2016-04-12
      • 2012-06-06
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-14
      • 2012-12-10
      相关资源
      最近更新 更多