Configuring Ninject with Asp.Net MVC & Web Api

Idrees Khan picture Idrees Khan · May 5, 2013 · Viewed 49.6k times · Source

i have setup my project with Ninject IoC.
My project has regular Asp.Net MVC controllers and Web Api controllers. Now, Ninject works with Web Api but Ninject doesn't work with regular Asp.MVC controllers.
My regular MVC controller implementation;

public class GalleryController : BaseController
{
    public GalleryController(IUow uow)
    {
        Uow = uow;
    }
    ........
}

Error when using with regular controller

An error occurred when trying to create a controller of type 'Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]

However, when i try the same code with Web Api, it works

public class GalleryController : BaseApiController
{
    public GalleryController(IUow uow)
    {
        Uow = uow;
    }
    ......
}

my interface which holds difference repositories (the factory pattern)

public interface IUow
{
    // Save pending changes to the data store.
    void Commit();

    //Repositoryries
    IRepository<Gallery> Gallery { get; }
    IMenuRepository Menus { get; }
}

NinjectDependencyScope class;

public class NinjectDependencyScope : IDependencyScope
{
    private IResolutionRoot resolver;

    internal NinjectDependencyScope(IResolutionRoot resolver)
    {
        Contract.Assert(resolver != null);

        this.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 class;

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
    private IKernel kernel;

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

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

Ninject configuration for Global.asax;

public class IocConfig
{
    public static void RegisterIoc(HttpConfiguration config)
    {
        var kernel = new StandardKernel(); // Ninject IoC
        //kernel.Load(Assembly.GetExecutingAssembly()); //only required for asp.net mvc (not for webapi)
        // These registrations are "per instance request".
        // See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/

        kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
            .InSingletonScope();

        kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
        kernel.Bind<IUow>().To<Uow>();

        // Tell WebApi how to use our Ninject IoC
        config.DependencyResolver = new NinjectDependencyResolver(kernel);
    }
}

Global.asax

protected void Application_Start()
{

    // Tell WebApi to use our custom Ioc (Ninject)
    IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    GlobalConfig.CustomizeConfig(GlobalConfiguration.Configuration);
    AreaRegistration.RegisterAllAreas();
}

Answer

Ody picture Ody · Jun 23, 2013

I have written some gists to help configure Ninject with MVC and Web Api. Simply include the file(s):

To add Bindings for concrete Types, Just put them in the Load() method of the MainModule. You can create as many modules as you like to keep bindings organized. but you'll also have to add them to the array that is returned in the Modules property.

Then Add to the Application_Start() method

  • NinjectContainer.RegisterModules(NinjectModules.Modules) (for MVC)
  • NinjectHttpContainer.RegisterModules(NinjectHttpModules.Modules) (for WebApi)

Note that you can use the same NinjectModules.Modules for both the MVC and WebApi registration. I just separated it for clearity

UPDATE: Remember to Remove NinjectWebCommon.cs from your project as it loads and bootstraps a new kernel at Runtime which unfortunately is only for MVC.

UPDATE: You can also use

  • NinjectContainer.RegisterAssembly() (for MVC)
  • NinjectHttpContainer.RegisterAssembly() (for WebApi)

This will scan your current assembly for all modules. This way you can put your modules anywhere in your project and it will be registered