问题
I am using Ninject together with ASP.NET MVC 4. I am using repositories and want to do constructor injection to pass in the repository to one of the controllers.
Here is my context object (EntityFramework) that implements my StatTracker interface:
public class StatTrackerRepository : IStatTrackerRepository
{
private GolfStatTrackerEntities _ctx;
public StatTrackerRepository(GolfStatTrackerEntities ctx)
{
_ctx = ctx;
}
public IQueryable<Facility> GetFacilites()
{
return _ctx.Facilities;
}
}
This is my Repository interface:
public interface IStatTrackerRepository
{
IQueryable<Facility> GetFacilites();
}
Which then calls my Home Controller:
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);
}
}
The page loads properly, however, once the page is loaded, it immedately uses an angularjs Controller which calls the $http method:
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");
});
}
...which calls the following API controller:
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;
}
}
....where it falls into the error function of the angular $http call because the FacilityController(IStatTrackerRepository repo) is never ran.
I have tried using a parameterless contstructor that instantiates a StatTrackerRepository(ctx) for FacilityController(), however, I get a NullReferenceException when I do so.
My Ninject config is as follows:
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();
}
I'm not sure if this is something wrong with Ninject or if there is an issue with how I am implementing Ninject. The injection seems to be working on the initial load of the Home view, however, when it uses angular to call the API, there is a disconnect with Ninject.
Please help.
回答1:
We ended up using a similar configuration on one of our older projects and realized that we needed to add a little more infrastructure code to our MVC/WebApi App:
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());
}
}
}
Then we added the following to the NinjectWebCommon.cs file:
public static void RegisterNinject(HttpConfiguration configuration)
{
// Set Web API Resolver
configuration.DependencyResolver = new NinjectDependencyResolver(Bootstrapper.Kernel);
}
And then the following to Global.asax.cs file, Application_Start method:
NinjectWebCommon.RegisterNinject(GlobalConfiguration.Configuration);
来源:https://stackoverflow.com/questions/22788538/cannot-inject-dependencies-using-ninject-into-asp-net-web-api-controller-called