2

In MVC 5 we get this account controller that looks like this.

public class AccountController : Controller
        {

            public AccountController()
                : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
            {

            }

            public AccountController(UserManager<ApplicationUser> userManager)
            {
                UserManager = userManager;
            }
        }

I installed Ninject to handle my dependency injection. I have two repositories, that I want to use in my AccountController and the code now looks like this

    public class AccountController : Controller
    {
              private readonly ILicenserepository _licenserepository;
              private readonly IUserRepository _userRepository;    

        public AccountController(ILicenserepository licenserepository, IUserRepository userRepository)
            : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
        {
            _licenserepository = licenserepository;
            _userRepository = userRepository;
        }

        public AccountController(UserManager<ApplicationUser> userManager)
        {
            UserManager = userManager;
        }
    }

in ninject.web.common this is what i've done

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind(typeof (ILicenserepository)).To(typeof (Licenserepository));
    kernel.Bind(typeof (IUserRepository)).To(typeof (UserRepository));
}    

but when I run the application i get the error on browser that says no parametereless constructor found. And if i create parameter less constructor my repositories doesn't get instantiated. So wherever i called the method from repository the value is null. How can I solve this problem? Or make MVC or Ninject know which constructor to call?

Cybercop
  • 8,475
  • 21
  • 75
  • 135
  • I don't have a concrete solution on top of my head, but you need to replace the code which creates the controllers when using dependency injection of ANY kind. Usually you will have to implement your own (simple) controller factory that will inject the dependencies you need. The default Factory will require parameter less constructors You can also extend from `DefaultControllerFactory`(see msdn: http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultcontrollerfactory(v=vs.118).aspx) and resolve your dependencies there. Then register your new Factory to the MVC5 – Tseng Jan 23 '14 at 15:38
  • You can set the new controller via `ControllerBuilder.SetControllerFactory` (Link: http://msdn.microsoft.com/en-us/library/system.web.mvc.controllerbuilder.setcontrollerfactory(v=vs.118).aspx). Hope it helps – Tseng Jan 23 '14 at 15:41
  • And fwiw: Don't create `UserManager` within the constructor, this makes your class not UnitTest-able. Implement UserManager as an Interface and pass `IUserManager` as only dependency to the class and resolve it via your DI framework – Tseng Jan 23 '14 at 15:42

3 Answers3

6

You need a DependencyResolver registered in Global.asax.cs

Registration would look something like this:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    RegisterDependencyResolver();
}

private void RegisterDependencyResolver()
{
    var kernel = new StandardKernel();

    // you may need to configure your container here?
    RegisterServices(kernel);

    DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}

And the DependencyResolver

public class NinjectDependencyResolver : IDependencyResolver
{
    private readonly IKernel kernel;

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

    public object GetService(Type serviceType)
    {
        return this.kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return this.kernel.GetAll(serviceType);
        }
        catch (Exception)
        {
            return new List<object>();
        }
    }
}
qujck
  • 14,388
  • 4
  • 45
  • 74
  • umm sorry, it may sound stupid but by configure my container you meaan bind Irepository to repository, and where is that RegisterServices coming from? – Cybercop Jan 24 '14 at 07:40
  • 4
    You shouldn't need to roll your own DependencyResolver - it's provided by the Ninject.Mvc3 package (it works with MVC4 & 5 as well). – Sam Feb 27 '14 at 13:28
  • This is what I thought but after adding the nuget package in my MVC5 project I was getting nowhere until I had to do the scaffolding detailed above by qujck. – Trevor Dec 10 '17 at 11:57
2

This is an update: If your are using MVC5 and WebAPI 2 then all you need to do is use NuGet Manager and add NinjectMVC5 and NinjectWebApi2 into your project. Then the error goes away. (Using Visual Studio 2013)

Cheers

  • You will need `Ninject.Web.WebApi` and `Ninject.Web.WebApi.WebHost` from nuget, or the OwinHost package. See http://stackoverflow.com/a/22774893/982237 – obsoleter Aug 10 '15 at 05:24
  • Didn't do anything for me. I tried the MVC5 package again but I don't see what it adds or how you use it (made no difference). I had to resort to the example provided above by qujck (https://stackoverflow.com/a/21313049/4826364) – Trevor Dec 10 '17 at 12:24
0

I just got this working without issue using .NET MVC 5 and Ninject 3.3.4.

Steps Taken:

  1. Install Ninject 3.3.4
  2. Install Ninject.Web.Common 3.3.1
  3. Install Ninject.Web.Common.WebHost 3.3.1
  4. Install Ninject.MVC5 3.3.0 (for use with an MVC Controller)

(Optional) Api Controller Steps

  1. Install Ninject.Web.WebApi 3.3.0 (for use with an api ApiController)
  2. Install Ninject.Web.WebApi.WebHost (for use with an ApiController)

The important distinction here is whether your project uses Api Controllers or Mvc Controllers. If you are unfamiliar with the difference please check out the below post:

Difference between ApiController and Controller in ASP.NET MVC.

Note: I did not have to do any extra configuration to my Ninject.Web.Common.cs file. Below is my configuration omitting my bindings


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

namespace YourProject.Web.App_Start
{
    using System;
    using System.Web;
    using Microsoft.Web.Infrastructure.DynamicModuleHelper;
    using Ninject;
    using Ninject.Web.Common;
    using Ninject.Web.Common.WebHost;

    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);
                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)
        {
            // Common

            // Repositories

            // Services

            // Factories

            // Misc
        }        
    }
}

Agrejus
  • 722
  • 7
  • 18