无法使用Ninject将依赖项注入到由Angular Service调用的ASP.NET Web API控制器中。

3

我正在使用Ninject和ASP.NET MVC 4,使用存储库并希望进行构造函数注入以将存储库传递给其中一个控制器。

这是我的上下文对象(EntityFramework),它实现了我的StatTracker接口:

public class StatTrackerRepository : IStatTrackerRepository
{
    private GolfStatTrackerEntities _ctx;

    public StatTrackerRepository(GolfStatTrackerEntities ctx)
    {
        _ctx = ctx;
    }

    public IQueryable<Facility> GetFacilites()
    {
        return _ctx.Facilities;
    }
}

这是我的仓库接口:
public interface IStatTrackerRepository
{ 
    IQueryable<Facility> GetFacilites();
}

然后调用我的主页控制器:

public class HomeController : Controller
{
    public IStatTrackerRepository _repo { get; set; }

    public HomeController(IStatTrackerRepository repo)
    {
        _repo = repo;
    }

    public ActionResult Index()
    {
        var facilities = _repo.GetFacilites().ToList();
        return View(facilities);
    }
}

页面可以正常加载,但一旦页面加载完成,它立即使用一个AngularJS控制器调用$http方法:
function facilityIndexController($scope, $http) {
    $scope.data = [];
    $http({ method: 'GET', url: '/api/facility' }).
        success(function(result) {
            angular.copy(result.data, $scope.data);
        }).error(function() {
            alert("Could not load facilities");
        });
}

...调用以下API控制器:

public class FacilityController : ApiController
{
    public IStatTrackerRepository _repo { get; set; }
    public GolfStatTrackerEntities ctx { get; set; }

    //public FacilityController()
    //{
    //    _repo = new StatTrackerRepository(ctx);
    //}

    public FacilityController(IStatTrackerRepository repo)
    {
        _repo = repo;
    }

    public IEnumerable<Facility> Get()
    {
        var facilities = _repo.GetFacilites().ToList();
        return facilities;
    }
}

当FacilityController(IStatTrackerRepository repo)没有被调用时,它会落入angular $http调用的错误函数中。

我尝试使用一个无参构造函数来为FacilityController()实例化一个StatTrackerRepository(ctx),但是这样做会导致NullReferenceException异常。

我的Ninject配置如下:

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);
        //GlobalConfiguration.Configuration.DependencyResolver =
        //    new NinjectResolver(kernel);
        return kernel;
    }
    catch
    {
        kernel.Dispose();
        throw;
    }
}


private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<GolfStatTrackerEntities>().To<GolfStatTrackerEntities>().InRequestScope();
    kernel.Bind<IStatTrackerRepository>().To<StatTrackerRepository>().InRequestScope();            
}

我不确定是Ninject出了问题还是我实现Ninject的方式有问题。在Home视图的初始加载时,注入似乎是有效的,但当它使用Angular调用API时,与Ninject之间存在断开。

请帮忙解决。


你正在使用哪个版本的Web API和哪些Ninject包/版本? - BlakeH
Ninject 3.2。WebApi 4.0.30506.0。 - MTL323
那么你也在使用 Ninject.MVC3 吗? - BlakeH
1个回答

5
我们最终在我们的一个较旧的项目上使用了类似的配置,并意识到我们需要向我们的MVC/WebApi应用程序添加一些基础设施代码:
NinjectDependencyScope.cs
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Web.Http.Dependencies;
using Ninject;
using Ninject.Syntax;

namespace YourAppNameSpace
{
    public class NinjectDependencyScope : IDependencyScope
    {
        private IResolutionRoot _resolver;

        internal NinjectDependencyScope(IResolutionRoot resolver)
        {
            Contract.Assert(resolver != null);
            _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.cs

using System.Web.Http.Dependencies;
using Ninject;

namespace YourAppNameSpace
{
    public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
    {
        private readonly IKernel _kernel;

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

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

然后我们在 NinjectWebCommon.cs 文件中添加了以下内容:
public static void RegisterNinject(HttpConfiguration configuration)
        {
            // Set Web API Resolver
            configuration.DependencyResolver = new NinjectDependencyResolver(Bootstrapper.Kernel);

        }

然后在 Global.asax.cs 文件中找到 Application_Start 方法:

NinjectWebCommon.RegisterNinject(GlobalConfiguration.Configuration);

最佳的添加这些类的位置在哪里?或者它们已经存在于Ninject包中了吗?我有NinjectWebCommon.cs和Global.asax.cs文件,但是我不熟悉之前的.cs文件。 - MTL323
它们之前并不存在。我们将它们添加到了MVC/WebAPI项目中。 - BlakeH
3
@MTL323,你需要注意的是,Web API 2项目可以使用以下NuGet包:https://www.nuget.org/packages/Ninject.Web.WebApi/3.2.0,这样你就不必创建这些类了。 - BlakeH
2
添加 Ninject.Web.WebApi 包解决了我在 API 控制器方面遇到的问题。谢谢! - MTL323

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