Configuring MVC 4 with StructureMap

I started a new MVC4 project and wanted to use StructureMap for my IOC container of choice. I followed Phil’s post about wiring up dependency resolvers in mvc 4, but I kept getting the following error: “StructureMapDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator.
Parameter name: commonServiceLocator”

Took a little digging, but I found the CommonServiceLocator project from the Microsoft Patterns and Practice group.  That project has a StructureMap implementation of the IServiceLocator interface for StructureMap.  After I installed the CommonServiceLocator nuget, I was able to reference IServiceLocator in my code.   Taking the code from the CommonServiceLocator implementation, I ended up with the following:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using StructureMap;
// This is part of MvcKickstart (https://nuget.org/packages/mvckickstart)
namespace MvcKickstart.Infrastructure
{
/// <summary>
/// Wrapper for IDependencyScope, so that StructureMap plays nicely with built in mvc4 dependency resolution.
/// </summary>
public class StructureMapDependencyScope : ServiceLocatorImplBase
{
protected readonly IContainer Container;
public StructureMapDependencyScope(IContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
Container = container;
}
public new object GetService(Type serviceType)
{
if (serviceType == null)
return null;
try
{
return serviceType.IsAbstract || serviceType.IsInterface
? Container.TryGetInstance(serviceType)
: Container.GetInstance(serviceType);
}
catch
{
return null;
}
}
/// <summary>
/// When implemented by inheriting classes, this method will do the actual work of resolving
/// the requested service instance.
/// </summary>
/// <param name="serviceType">Type of instance requested.</param>
/// <param name="key">Name of registered service you want. May be null.</param>
/// <returns>
/// The requested service instance.
/// </returns>
protected override object DoGetInstance(Type serviceType, string key)
{
if (string.IsNullOrEmpty(key))
{
return GetService(serviceType);
}
return Container.TryGetInstance(serviceType, key);
}
/// <summary>
/// When implemented by inheriting classes, this method will do the actual work of
/// resolving all the requested service instances.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>
/// Sequence of service instance objects.
/// </returns>
protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
{
return Container.GetAllInstances(serviceType).Cast<object>();
}
public IEnumerable<object> GetServices(Type serviceType)
{
return Container.GetAllInstances(serviceType).Cast<object>();
}
public void Dispose()
{
Container.Dispose();
}
}
}

The following code will setup mvc to use structuremap as the dependency resolver. Add the webactivator nuget and toss the following file in your app_start folder:

using System.Web.Mvc;
using MvcKickstart.Infrastructure;
using StructureMap;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourProject.IocConfig), "PreStart", Order = -100)]
// This gets installed automatically with the MvcKickstart nuget (https://nuget.org/packages/mvckickstart)
namespace YourProject
{
public static class IocConfig
{
public static void PreStart()
{
// If changes need to be made to IocRegistry, please subclass it and replace the following line
ObjectFactory.Initialize(x => x.AddRegistry(new IocRegistry(typeof(IocConfig).Assembly)));
DependencyResolver.SetResolver(new StructureMapDependencyScope(ObjectFactory.Container));
}
}
}

Hope this helps someone looking to do the same!

5 thoughts on “Configuring MVC 4 with StructureMap

  1. Your .Cast() extension method isn’t included here, or its namespace isn’t if it’s a built-in method.

    Is there a working MVC4RC project you can point to that shows everything wired up, perhaps on Github?

  2. And … of course you would also need the following line in global.cs : )

    GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(ObjectFactory.Container);

Leave a Reply to Steve Cancel reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.