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:
BookWebAPIEvolvable
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

    Hi Zec,
    Perfectly working. Thank you.

  • Maxim V. Pavlov

    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.

  • 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!

  • Jon Wilson

    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.”