Share Dependency Resolvers between MVC and Web API

I was messing around with a web project last week that required the use of MVC 5 and Web API in the same application. I was also experimenting with Unity, as it was my first time and had usually chosen something like MEF or StructureMap to handle my dependencies. Previously, I also went the “classic” route of creating a custom controller factory and handling controller instantiation that way, so I figured it was time to start using IDependencyResolver to handle it. When I began to look around for the proper way to go about this cleanly, I began noticing some odd things about getting configuring the resolvers.

The first thing I noticed was that, in order to get both systems hooked up with a IoC container, it required two separate NuGet packages, Unity.MVC and Unity.WebAPI. I thought this was strange, as the implementation seemed quite similar. The second thing I noticed was, while MVC uses DependencyResolver.SetResolver(…) and Web API uses GlobalConfiguration.Configuration.DependencyResolver, both accepted a IDependencyResolverinstance. The strange thing is that IDependencyResolver exists, but in nearly identical form, in two different namespace: System.Web.Mvc and System.Web.Http.Dependencies, respectively.

Here’s a look at System.Web.Http.Dependencies.IDependencyResolver and the IDependencyScope interface that it also implements.

namespace System.Web.Http.Dependencies 
{     
    public interface IDependencyScope : IDisposable     
    {         
        object GetService(Type serviceType);         
        IEnumerable<object> GetServices(Type serviceType);     
    }
}
namespace System.Web.Http.Dependencies
{
    public interface IDependencyResolver : IDependencyScope, IDisposable
    {
        IDependencyScope BeginScope();
    }
}

This, as you see, is identical to System.Web.Mvc.IDependencyResolver.

namespace System.Web.Mvc
{
    public interface IDependencyResolver
    {
        object GetService(Type serviceType);
        IEnumerable<object> GetServices(Type serviceType);
    }
}

Why? I have no idea. I imagine due to the separate development tracks, they had to keep them in separate namespaces. My hopes is these will be merged when MVC and Web API become merged into one. However, the solution came in the form of simply implementing both versions of theIDependencyResolver interface. This method allows for me to share the same resolver instance with both frameworks.

UnityDependencyResolver.cs

public class UnityDependencyResolver : System.Web.Mvc.IDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver
{
    private IUnityContainer _container;

    public UnityDependencyResolver(IUnityContainer container)
    {
        _container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return _container.Resolve(serviceType);
        }
        catch
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return _container.ResolveAll(serviceType);
        }
        catch
        {
            return null;
        }
    }

    public System.Web.Http.Dependencies.IDependencyScope BeginScope()
    {
        var child = _container.CreateChildContainer();
        return new UnityDependencyResolver(child);
    }

    public void Dispose()
    {
        _container.Dispose();
    }
}

Afterwards, the wiring-up of the resolver for both MVC and Web API is simple.

Global.asax.cs (Application_Start)

var unityResolver = new UnityDependencyResolver(Dependencies.Container);
DependencyResolver.SetResolver(unityResolver); // MVC
GlobalConfiguration.Configuration.DependencyResolver = unityResolver; // Web API

Dependencies.Container is merely an global instance of my UnityContainer (IUnityContainer). Granted, I was lazy with the try/catch, this solution allowed me to better re-use code and not have to deal with three packages, but rather one. Keep in mind that I did NOT have the need to install any addition packages outside of the default Unity NuGet package.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *