Brett Allred

be a student, not a follower

MVC4 With StructureMap

So I fired up MVC4 today excited to get started with APIController.

As usual the first two nuget packages I loaded were RavenDB and StructureMap.  I noticed that there was a nuget package for structuremap called structuremap.mvc4 which said it worked out of the box with MVC4 Api Controllers.

It didn’t.

I kept getting Activation Exceptions like:

Activation error occured while trying to get instance of type IHttpControllerFactory, key “”

After a little research here is how I solved it and what I learned.

In MVC3 we were given an new interface IDependencyResolver which lives in System.Web.Mvc.  By implementing this interface , our IOC container could plug directly into the framework as follows:

DependencyResolver.SetResolver(new Your IOC’s Implementation);

With MVC4 there is a second resolver which needs to be configured using:

GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new Your IOC’s Implementation);

Where this gets a little confusing is that this also takes an IDependencyResolver but NOT the one which lives in System.Web.Mvc.  It needs to IDependencyResolver which lives in System.Web.Http.Services.

The interfaces are identical, they are just in different namespaces.

StructureMap has a built in ServiceLocator called StructureMapServiceLocator which is the default when using the nuget package.  I could not get this to work.

Instead I used a little adapter class from Phil Haack’s Blog 

which looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;
using System.Collections.Generic;
using System.Web.Http.Services;

namespace StructureMapTest.DependencyResolution
{
  public class ServiceResolverAdapter : IDependencyResolver
  {
    private readonly System.Web.Mvc.IDependencyResolver dependencyResolver;

      public ServiceResolverAdapter(System.Web.Mvc.IDependencyResolver dependencyResolver)
      {
        if (dependencyResolver == null) throw new ArgumentNullException("dependencyResolver");
          this.dependencyResolver = dependencyResolver;
      }

      public object GetService(Type serviceType)
      {
        return dependencyResolver.GetService(serviceType);
      }

      public IEnumerable GetServices(Type serviceType)
      {
        return dependencyResolver.GetServices(serviceType);
      }
  }

    public static class ServiceResolverExtensions
    {
      public static IDependencyResolver ToServiceResolver(this System.Web.Mvc.IDependencyResolver dependencyResolver)
      {
        return new ServiceResolverAdapter(dependencyResolver);
      }
    }
}

Now you can modify the second service resolver to use this adapter class

1
2
GlobalConfiguration.Configuration.ServiceResolver
.SetResolver(DependencyResolver.Current.ToServiceResolver());

With the nuget package, this all lives in the App_StartStructureMapMvc.cs Here is the finished version

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.Web.Http;
using System.Web.Mvc;
using StructureMap;
using StructureMap.ServiceLocatorAdapter;

[assembly: WebActivator.PreApplicationStartMethod(typeof(StructureMapTest.App_Start.StructuremapMvc), "Start")]

namespace StructureMapTest.App_Start {
  public static class StructuremapMvc {
    public static void Start() {
      var container = (IContainer) IoC.Initialize();
        DependencyResolver.SetResolver(new SmDependencyResolver(container));
        // this override is needed because WebAPI is not using DependencyResolver to build controllers 
        GlobalConfiguration.Configuration
        .ServiceResolver.SetResolver(DependencyResolver.Current.ToServiceResolver());
    }
  }
}