Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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.

share|improve this question
    
What version of Web API and what Ninject packages/versions are you using? –  SonicTheLichen Apr 1 at 14:15
    
Ninject 3.2. WebApi 4.0.30506.0 –  MTL323 Apr 1 at 14:18
    
So you are using Ninject.MVC3 as well? –  SonicTheLichen Apr 1 at 14:48
    
That is correct. –  MTL323 Apr 1 at 14:50
add comment

1 Answer 1

up vote 3 down vote accepted

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);
share|improve this answer
    
Where would be the best place to add these classes or do they already exist within the Ninject packages? I have the NinjectWebCommon.cs and Global.asax.cs but I am unfamiliar with the previous .cs files. –  MTL323 Apr 1 at 16:02
    
They did not exist. We added them to the mvc/webapi project. –  SonicTheLichen Apr 1 at 16:07
    
@MTL323, you should note that Web API 2 projects can utilize the following nuget package: nuget.org/packages/Ninject.Web.WebApi/3.2.0 and you won't have to create these classes –  SonicTheLichen Apr 1 at 16:40
1  
Adding the Ninject.Web.WebApi package resolved the issue that I was having with the API controller. Thank you! –  MTL323 Apr 2 at 2:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.