Simple way to share Dependency Resolvers between MVC and Web API
I had several projects in past using ASP.NET MVC 4 and 5 and ASP.NET Web API that reside in same project. When you want to share DI container between MVC and Web API things can become complicated.
Reason for this is because ASP.NET MVC 5 uses interface System.Web.Mvc.IDependencyResolver for implementing dependency resolver and ASP.NET Web API uses System.Web.Http.Dependencies.IDependencyResolver interface which has the same name but resides in different namespace.
These two interfaces are different, even they have a same name.
Why should you use MVC and Web API in the same project
There could be many reasons for this. For me the main reason was simplifying the way to securing Web API access by implementing session support in ASP.NET Web API even it is not recommended.
This way we can detect request coming from our MVC Application without need to protect API Key and API Secret which we use for mobile access to Web API. Protecting API Key and API Secret on web application can be very complicated.
If you want to learn more about ASP.NET Web API I recommend a great book that I love written by real experts:
Designing Evolvable Web APIs with ASP.NET
Simple implementation
I am usually using Ninject as DI container of my choice. First we need to reference Ninject in our project.
After that we create class called NinjectRegistrations which inherits NinjectModule and will be used for registering types into container.
public class NinjectRegistrations : NinjectModule
{
public override void Load()
{
Bind<IApiHelper>().To<ApiHelper>();
}
}
After that we will create class NinjectDependencyResolver that will implement both required interfaces mentioned above:
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
We also need to implement class NinjectDependencyScope which is inherited from NinjectDependencyResolver:
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = this.resolver as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
this.resolver = null;
}
public object GetService(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.GetAll(serviceType);
}
}
That is entire implementation. Usage is very simple. To use the same container in MVC and Web API project we just create Ninject container in Global.asax.cs and pass same Ninject resolver to MVC and Web API.
NinjectModule registrations = new NinjectRegistrations();
var kernel = new StandardKernel(registrations);
var ninjectResolver = new NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); // MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; // Web API
You can use the same method for any kind of DI container not only Ninject.
And if you liked this post, go ahead and subscribe here to my RSS Feed to make sure you don’t miss other content like this.
Vivekanand Swamy
October 1, 2014 at 6:00 pm (10 years ago)Hi Zec,
Perfectly working. Thank you.
Radenko Zec
October 1, 2014 at 8:15 pm (10 years ago)Thanks for comment Vivekanand.
Maxim V. Pavlov
February 19, 2015 at 3:48 pm (10 years ago)What if I removed Global.asax and am just using a Startup.cs class to configure an application with both MVC and WebAPI? How can I configure MVC Resolver? Thank you.
Ben Smith
May 2, 2015 at 10:21 am (10 years ago)Many thanks, this worked great.
Just a quick note to anyone who has problems implementing this: In the article it states “first we need to reference Ninject in our project”. Make sure that you pull down ONLY the main Ninject package and not any of the other MVC or Web API specific packages as this will cause this approach to fail.
Thanks again!
Radenko Zec
May 2, 2015 at 10:29 am (10 years ago)Thanks. Glad it help you.
Jon Wilson
November 12, 2015 at 8:24 pm (9 years ago)You saved my day with this. Thank you so much! The key to getting this to work is mentioned in Ben Smith’s comment: “Make sure that you pull down ONLY the main Ninject package and not any of the other MVC or Web API specific packages as this will cause this approach to fail.”
Radenko Zec
November 12, 2015 at 9:10 pm (9 years ago)Thanks for comment Jon.
Phoébe Mac
March 21, 2018 at 11:25 am (7 years ago)I’m confused – where should these classes go so they are accessible from both api project
and web mvc project?
Max
August 22, 2018 at 10:08 am (6 years ago)Help me, please. I can`t find solution for an issue. When i write in Application_Start() method this: “GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel)” I have an error “Cannot implicity convert type Ninject.Web.MVC.NinjectDependencyResolver to System.Web.Http.Dependencies.IDependencyResolver”.