NOTEBOOK HEAVY

Setup StructureMap with ASP.NET Web API Release Candidate

One important change from the Beta of Web API to RC was the way it handles IoC. So far, there have been a few guides of how to do it with Ninject or Unity, but I’m still using StructureMap for many of my projects. In a previous post, I showed how I used StructureMap in an integration test of Web API using NUnit. However, that was against the Beta and was in the context of automated testing. This post works against the RC and is direct usage of StructureMap within the Web API.

Before IoC

Before we start using the IoC, lets look at the sample I created. I have a Web API controller called ValuesController with the GET verb functionality implemented. We’ll start with an empty constructor and a controller that looks like this:


public class ValuesController : ApiController
{
public ValuesController() {}

public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}

public string Get(int id)
{
return "value";
}
}

That’s pretty simple. I’m going to put a little jQuery code to call our Web API and confirm it’s working without IoC:


$(function () {

$.getJSON('/api/values/1?timestamp=' + new Date().getTime(), function(data) {
alert(data);
});

});

After running this, we get this result:

(The timestamp is in there to make sure nothing is caching for demonstration purposes.) Great, a simple Web API controller.

Let’s Get Some IoC In There!

However, let’s say we now want to add IoC to the controller. In my demo, I started with a new MVC 4 Web API project and pulled down StructureMap from NuGet. It installs itself with 3 files (I realize that I installed the MVC3 version even though there is an MVC4 version available…oh well):

  1. DependencyResolution/IoC.cs
  2. DependencyResolution/SmDependencyResolver.cs
  3. App_Start/StructureMap.cs

Of these three, number 1 won’t change at all. In my case, I’ve got a sample interface called ISampleFish and an implementation class called SampleFish. They are both empty, so don’t worry about what’s inside them.

Let’s now change the constructor on the ValuesController to take in an ISampleFish. Here’s what I want:


public class ValuesController : ApiController
{
private readonly ISampleFish _sampleFish;

public ValuesController(ISampleFish sampleFish)
{
_sampleFish = sampleFish;
}

// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}

// GET api/values/5
public string Get(int id)
{
return "value";
}
}

Note that I don’t actually use the interface in the controller. It’s merely a vessel for demonstrating the IoC. Running the same JavaScript again, we now fail. Hitting F12 to open the developer tools, we see this in the network panel:

Digging into the exception information, we see this:

{“ExceptionType”:”System.ArgumentException”,”Message”:”Type ‘WebApiStructureMapDemo.Controllers.ValuesController’ does not have a default constructor”,”StackTrace”:” at System.Linq.Expressions.Expression.New(Type type)rn at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)rn at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)”}

The key part here is: ValuesController does not have a default constructor

This means that the IoC engine isn’t being used correctly and the ASP.NET engine cannot find a constructor without any parameters. It’s time to fix the IoC.

The StructureMap Doctor Is In

Here’s what SmDependencyResolver.cs currently looks like:


public class SmDependencyResolver : IDependencyResolver {

private readonly IContainer _container;

public SmDependencyResolver(IContainer container) {
_container = container;
}

public object GetService(Type serviceType) {
if (serviceType == null) return null;
try {
return serviceType.IsAbstract || serviceType.IsInterface
? _container.TryGetInstance(serviceType)
: _container.GetInstance(serviceType);
}
catch {

return null;
}
}

public IEnumerable<object> GetServices(Type serviceType) {
return _container.GetAllInstances(serviceType).Cast<object>();
}
}

It implements IDependencyResolver, but in this case, the interface is System.Web.Mvc.IDependencyResolver. For Web API, we need a completely different IDependencyResolver. The one we want is System.Web.Http.Services.IDependencyResolver. If we take a look at that interface, it looks like this:


namespace System.Web.Http.Dependencies
{
public interface IDependencyResolver : IDependencyScope, IDisposable
{
IDependencyScope BeginScope();
}
}

So IDependencyResolver implements IDependencyScope and IDisposable. IDisposable is fairly straight forward. Taking a closer look at IDependencyScope, it looks like this:


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

So, there’s some extra stuff now that we need to take care of. To use StructureMap, we’re going to create a StructureMapScope that implements IDependencyScope. We’re essentially pulling the code from the original SmDependencyResolver and putting it in the StructureMapScope. It looks like this:


public class StructureMapScope : IDependencyScope
{
protected IContainer Container;

public StructureMapScope(IContainer container)
{
Container = container;
}

public void Dispose()
{
IDisposable disposable = (IDisposable)Container;
if (disposable != null)
{
disposable.Dispose();
}
Container = null;
}

public object GetService(Type serviceType)
{
if (serviceType == null)
{
return null;
}
try
{
if (serviceType.IsAbstract || serviceType.IsInterface)
return Container.TryGetInstance(serviceType);

return Container.GetInstance(serviceType);
}
catch
{
return null;
}
}

public IEnumerable<object> GetServices(Type serviceType)
{
return Container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
}
}

This now looks like the original SmDependencyResolver, with the addition being the Dispose() method. So, since StructureMapScope is handling all of this lifting, we need to go back and update SmDependencyResolver. It now looks like this:


public class SmDependencyResolver : StructureMapScope, IDependencyResolver
{
private IContainer _container;

public SmDependencyResolver(IContainer container)
: base(container)
{
_container = container;
}

public IDependencyScope BeginScope()
{
_container = (IContainer)IoC.Initialize();
return new StructureMapScope(_container);
}
}

Note that it essentially gets the scope going and StructureMapScope does the main work. The IoC is now done on a per request basis where before it was all globally scoped. We could do the same global scope here and just not do the disposal or reinit in the begin scope (and indeed, I don’t know enough about StructureMap to say for sure if IoC.Initialize() is the best thing to do per request). We need to change one more thing in #3 from above: StructureMap.cs. The way the IoC is activated has changed. StructureMap.cs should now look like this:


public static class StructuremapMvc {
public static void Start() {
var container = (IContainer)IoC.Initialize();
GlobalConfiguration.Configuration.DependencyResolver = new SmDependencyResolver(container);

}
}

Once this is all in place, we’re back to the alert box from before and all is right with the world. I’ve put all this together in a GitHub repository.

Let me know what you think of this post in the comments. If you have any suggestions, please let me know. I’m all ears.

Comments

    1. ken_stone

      Brad, That’s exactly correct and the point of my blog post. There’s an image in the post that shows what I got from NuGet. I got the StructureMap.MVC3 NuGet package. As you say, the interfaces aren’t the same, which is why I wrote a different dependency resolver. This blog post shows how to do that in the absence of a Web API RC StructureMap NuGet package.

      Reply
  1. J Stigsson

    When I implemented your solution above, I get my webApi to work, but the other controllers living outside the webapi get the following error:

    No parameterless constructor defined for this object.

    Any idee how to solve that problem?

    Reply
  2. Brandon Martinez

    First off, thank you for shedding some light on this subject; I was looking for a solution using SM within WebAPI. However, a few tweaks to your posted code:

    1.) IDependencyResolver implements IDependecyScope, so implementing the former is enough to use for WebAPI.

    2.) Since you are already implementing an IDependencyScope, you have your scope around; why not just return that?

    3.) Here’s my modified version of your code (single class implementation): https://gist.github.com/1464286d648e73b339be

    Reply
  3. Robert

    Shouldn’t you use StructureMap’s nested containers instead of reinitializing StructureMap over and over? I figure the ObjectFactory.Container was meant to work as a singleton, and only initialized once.

    And what are you doing with the SmDependencyResolver._container field? Why do you keep it around if you just replace it every time?

    And the protected StructureMapScope.Container, why isn’t it private and why isn’t it readonly?

    Reply
  4. Hellspawn

    This no longer seems to be an issue with the introduction of the StructureMap.MVC4 NuGet package.

    After installing this to my Web API project, the StructureMapDependencyResolver class correctly implements the System.Web.Http.Dependencies.IDependencyResolver interface and inherits the StructureMapDependencyScope class (which in turn implements System.Web.Http.Dependencies.IDependencyScope).

    Its all good…!

    Reply

Reply

Your email address will not be published.