Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC5, Web API 2 and Ninject

I have created a new MVC5 project with Web API 2, I then added the Ninject.MVC3 package from NuGet.

Constructor injection is working fine for the MVC5 controllers, but i am getting an error when trying to use it with the Web API Controllers.

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

Constructor for working MVC5 controller:

public class HomeController : Controller {     private IMailService _mail;     private IRepository _repo;      public HomeController(IMailService mail, IRepository repo)     {         _mail = mail;         _repo = repo;     } } 

Constructor for non-working Web API Controller:

public class UserProfileController : ApiController {     private IRepository _repo;      public UserProfileController(IRepository repo)     {         _repo = repo;     } } 

Below is the full NinjectWebCommon.cs file:

[assembly: WebActivator.PreApplicationStartMethod(typeof(DatingSite.App_Start.NinjectWebCommon), "Start")] [assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(DatingSite.App_Start.NinjectWebCommon), "Stop")]  namespace DatingSite.App_Start { using System; using System.Web;  using Microsoft.Web.Infrastructure.DynamicModuleHelper;  using Ninject; using Ninject.Web.Common; using DatingSite.Services; using DatingSite.Data;  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();         kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);         kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();          RegisterServices(kernel);         return kernel;     }      /// <summary>     /// Load your modules or register your services here!     /// </summary>     /// <param name="kernel">The kernel.</param>     private static void RegisterServices(IKernel kernel)     { #if DEBUG         kernel.Bind<IMailService>().To<MockMailService>().InRequestScope();  #else         kernel.Bind<IMailService>().To<MailService>().InRequestScope(); #endif         kernel.Bind<SiteContext>().To<SiteContext>().InRequestScope();         kernel.Bind<IRepository>().To<Repository>().InRequestScope();     } } } 
like image 554
Declan Avatar asked Dec 15 '13 14:12

Declan


People also ask

What is ninject?

Ninject is a lightweight dependency injection framework for . NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner.

What is .NET Web API 2?

ASP.NET Web API is a framework for building HTTP service for a wide range of devices. WEB API is very similar to ASP.NET MVC. It contains most of the MVC features like routing, controllers, action results, filter, model binders, etc. Let us create a simple application using the WEB API 2.

Which is best MVC or Web API?

1. Asp.Net MVC is used to create web applications that returns both views and data but Asp.Net Web API is used to create full blown HTTP services with easy and simple way that returns only data not view. 2. Web API helps to build REST-ful services over the .

Can I use MVC controller as Web API?

Before I illustrate how an ASP.NET MVC controller can be used as an API or a service, let's recap a few things: Web API controller implements actions that handle GET, POST, PUT and DELETE verbs. Web API framework automatically maps the incoming request to an action based on the incoming requests' HTTP verb.


2 Answers

The Ninject.Web.WebApi NuGet package has just been released. From now on the preferred solution is using that package. I couldn't find any related documentation but after installing the package everything worked for me.

Install-Package Ninject.Web.WebApi  

After installation both the normal MVC and the API controller instances are provided by Ninject.

If you have Ninject.Web.Common already installed make sure to save your bindings from NinjectWebCommon.cs and let Nuget rewrite NinjectWebCommon.cs during install and put back your bindings when finished.

As pointed out in the comments depending on your execution context you will need one of the following packages as well:

  • Ninject.Web.WebApi.WebHost
  • Ninject.Web.WebApi.OwinHost
  • Ninject.Web.WebApi.Selfhost

The most common scenario is IIS for that pick the WebHost package.

In the case you start an IIS MVC5 web app from scratch and want to use Ninject install the following packages:

  • Ninject - Ninject core dll
  • Ninject.Web.Common - Common Web functionality for Ninject eg. InRequestScope()
  • Ninject.MVC5 - MVC dependency injectors eg. to provide Controllers for MVC
  • Ninject.Web.Common.WebHost - Registers the dependency injectors from Ninject.MVC5 when IIS starts the web app. If you are not using IIS you will need a different package, check above
  • Ninject.Web.WebApi WebApi dependency injectors eg. to provide Controllers for WebApi
  • Ninject.web.WebApi.WebHost - Registers the dependency injectors from Ninject.Web.WebApi when IIS starts the web app.
like image 171
Hari Avatar answered Oct 02 '22 11:10

Hari


You have this problem because Controller and ApiController use different Dependency Resolvers. Solution is very simple.

At first create new classes of Dependency Resolver and Dependency Scope. You can use this:

 public class NinjectResolver : NinjectScope, IDependencyResolver {     private readonly IKernel _kernel;     public NinjectResolver(IKernel kernel)         : base(kernel)     {         _kernel = kernel;     }     public IDependencyScope BeginScope()     {         return new NinjectScope(_kernel.BeginBlock());     } }  public class NinjectScope : IDependencyScope {     protected IResolutionRoot resolutionRoot;     public NinjectScope(IResolutionRoot kernel)     {         resolutionRoot = kernel;     }     public object GetService(Type serviceType)     {         IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);         return resolutionRoot.Resolve(request).SingleOrDefault();     }     public IEnumerable<object> GetServices(Type serviceType)     {         IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);         return resolutionRoot.Resolve(request).ToList();     }     public void Dispose()     {         IDisposable disposable = (IDisposable)resolutionRoot;         if (disposable != null) disposable.Dispose();         resolutionRoot = null;     } } 

After that, add next line to method CreateKernel() in NinjectWebCommon

 GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); 
like image 33
Artur Movsesyan Avatar answered Oct 02 '22 12:10

Artur Movsesyan