Back to News List

ASP.NET MVC 4, Web API and StructureMap

Share This

ASP.NET MVC 4 is now released and along with it Web API! This post is not going to cover the new features of MVC 4 or all the good stuff Web API brings to the table, but will cover them in the context of Dependency Resolution. As you may have expected the new ApiController supports Dependency Injection, however you may not have expected that your MVC 3 IDepdencyResolver implementation would not work for instances of ApiController.

If you Install-Package StructureMapMVC3 and create a mapping:

Code snippet for creating a mapping

Then try to use constructor injection in a Web API controller:

Code snippet to show using a constructor injection in a web API controller

You will receive the 'Type Controllers.AwesomeApiController does not have a default constructor' argument exception.

#fail

What, why?

This is because Web API is a completely different stack than MVC and does not have access to the DependencyResolver from System.Web.Mvc. This was by design so that Web API could be self hosted. Web API's ability to self host is awesome but this means we now have two interfaces named IDependencyResolver.

  • System.Web.Http.Dependencies.IDependencyResolver (Web API)
  • System.Web.Mvc.IDependencyResolver (MVC)

The IDependencyResolver interface for Web API inherits two other interfaces, IDependencyScope and IDisposable:

Code snippet showing IDependencyScope and IDisposable

The IDependencyResolver only has a single method that returns and instance of IDependencyScope:

Code snippet showing method

The IDependencyScope interface defines two methods:

  • GetService : Creates one instance of a specified type.
  • GetServices : Create a collection of objects of a specified type.

Web API IDependencyResolver and StructureMap

The dependency resolver attached to the HttpConfiguration object has global scope. When the framework creates a new instance of a controller, it calls IDependencyResolver.BeginScope. This method returns an IDependencyScope. The framework calls GetService on the IDependencyScope instance to get the controller. When the framework is done processing the request, it calls Dispose on the child scope. You can use the Dispose method to dispose of the controller’s dependencies.

We can simply implement the needed interfaces using StructureMap as our container:

Code snippet showing how to implement the needed interfaces using StructureMap as container

The StructureMapDependencyScope class implements IDependencyScope and represents a child scope. The StructureMapDependencyResolver class implements the global-scope dependency resolver. In the BeginScope method, it creates a new StructureMapDependencyScope instance. The StructureMap container also has the concept of a child container, so we initialize the child StructureMapDependencyScope with a StructureMap child/nested container. The StructureMapDependencyScope.Dispose method disposes of the StructureMap child container.

Now we can wire this up in our App_Start:

Code snippet for adding to App_Start

MVC and CommonServiceLocator

This takes care of Web API but is not much help for MVC. If you look at the System.Web.Mvc.DependencyResolver.SetResolver method, you will notice it has three overloads

  • void SetResolver(System.Func getService, System.Func> getServices)
  • void SetResolver(System.Web.Mvc.IDependencyResolver resolver)
  • void SetResolver(object commonServiceLocator)

In the past we would have used the overload that takes an instance of MVC's IDependencyResolver. Because I would like to use my StructureMapDependencyResolver for both Web API and MVC, we can use the overload that takes an instance of CommonServiceLocator. CommonServiceLocator is an interface for dependency injection that all vendors can implement.

There are a few ways to have the adapter implement the interface. You can either use the IServiceLocator interface or you can use ServiceLocatorImplBase (Microsoft.Practices.ServiceLocation), which is used as a convenience for those who wants to implement the IServiceLocator interface:

Code snippet for using ServiceLocatorImpIBase

With the ServiceLocatorImplBase as our base, we only need to implement the DoGetInstance and DoGetAllInstances methods:

Code snippet for implementing DoGetInstance and DoGetAllInstances methods

The updated StructureMapDependencyResolver:

Code snippet for the updated StructureMapDependencyResolver

The updated App_Start:

Code snippet for the updated App_Start

The good news!

The good news is, thanks to NuGet, you don't need to worry about any of the pluming needed to get this working. By using

Showing how to install the package

and you are all set. For those who would like to see the implementation details, you can view the code here StructureMap.MVC4.

What's Next?

Back to Top