Episerver Structure Map Guide

With the release of Episerver 7, having a good understanding about dependency injection is critical to make a successful project.  Out of the box Episerver uses structure map so you don’t have to add it in.  You will need to be able to configure it

The Dependency Resolver

The first step to get structure map working in your solution is to define a StructureMap dependency resolver.  I usually created this code within the ‘App_Code’ folder.

namespace JonDJones.Com.App_Code
{
public class StructureMapDependencyResolver : IDependencyResolver
{
readonly IContainer _container;
public StructureMapDependencyResolver(IContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (serviceType.IsInterface || serviceType.IsAbstract)
{
return GetInterfaceService(serviceType);
}
return GetConcreteService(serviceType);
}
private object GetConcreteService(Type serviceType)
{
try
{
return _container.GetInstance(serviceType);
}
catch (StructureMapException)
{
return null;
}
}
private object GetInterfaceService(Type serviceType)
{
return _container.TryGetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances(serviceType).Cast<object>();
}
}
}

Configuring Structure Map

After we have the dependency resolver set-up, the next thing to do is to configure structure map itself.  This is done by adding a configurable module into your project.  A configurable module is like an Episerver initializable module, however, it’s purpose is to tell EPiServer how to resolve dependencies.  To make a configurable module, create a class and implement from IConfigurableModule.  In the ConfigureContainer() method we can then define our interface to concrete class definitions. We set the dependency resolver to use the custom class we created above:

public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Container.Configure(ConfigureContainer);
DependencyResolver.SetResolver(new StructureMapDependencyResolver(context.Container));
_container = context.Container;
}

If you do not do this then structure map won’t resolve correctly. Next we need to add in the custom mappings:

private static void ConfigureContainer(ConfigurationExpression container)
{
container.For<IEpiserverDependenciesResolver>().Use<EpiserverDependenciesResolver>();
}

In here we use the ConfigurationExpression to add in custom mappings.  What the code says is that whenever Episerver finds a reference to IEpiserverDependenciesResolver in a constructor, new up an instance of a class called EpiserverDependenciesResolver.

If I had the following class in my project, Episerver would auto populate IEpiserverDependenciesResolver for me.

public class StartController : PageController<StartPage>
{
private IEpiserverDependenciesResolver _epiServerDependenciesResolver;
public StartController(IEpiserverDependenciesResolver epiServerDependenciesResolver)
{
_epiServerDependenciesResolver = epiServerDependenciesResolver;
}
}

One of the main advantages of this approach is that in your production code you can talk to database, services etc… as normal and then in your unit test project you can mock IEpiserverDependenciesResolver or even only use a test version.  This approach allows you to test aspects of your code that were previously untestable.

Configuring Structure Map

In it’s simplest form the code to register a mapping looks like this:

x.For<IClass>().Use<Class>();

This code is also equivalent to this:

x.For<IClass>().Use(new Class());

After you add a mapping, it should resolve automatically for you.  If you make a typo or forget to register your dependency correctly when your site loads, you’ll get this exception:

‘StructureMap Exception Code: 202 No Default Instance defined for IClass’

Whenever you see this, look in your dependency mappings section and make sure your definition is correct.

Class with constructor parameters

So far we’ve talked about classes that have a parameterless constructors. What happens if you had the following class:

public EpiserverDependenciesResolver : IEpiserverDependenciesResolver
{
public EpiserverDependenciesResolver(IClass parameterOne, string parameterTwo)
{
}
}

When the class you want to resolve has constructor arguments, you’ll also need to add them to the mapping:

container.For<IEpiserverDependenciesResolver >().Use<EpiserverDependenciesResolver >()
.Ctor<IClass >().Is<Class>()
.Ctor<string>("parameterTwo").Is("Random String");;

In the code above, I define the two constructor parameters that the EpiserverDependenciesResolver depends on, in the second and third lines.

The first one is a simple interface to concrete class.  I’ve used an alternative method for the second parameter to show the different ways you can configure structure map.  If you want to, you can manually type in the parameter name in the Ctor.  As this isn’t type safe I wouldn’t recommend it but it is an option you should be aware of that can be useful once in a blue moon.

When you define constructor parameters you can also use the IsTheDefault() parameter, like this:

container.For<IEpiserverDependenciesResolver>()
.Use<EpiserverDependenciesResolver>()
.Ctor<IClass>()
.IsTheDefault();

This approach is the way that I would recommend as it involved less code. If you have an interface called IClass and you have a class called Class, when you use IsTheDefault() structure map will automatically figure everything for you.

Episerver Goodies

Episerver also provide some other useful goodies for dependency resolving.  If you create something like a selection factory or an attribute you can’t inject things via the constructor. If you still want to write testable code you can use the Injected property.

Injected&lt;IEpiserverDependencies&gt; epiServerDependencies;
public void Initialize(InitializationEngine context)
{
var dependency = epiServerDependencies.Service;
}

In the code above when the class loads structure map will auto populate the property epiServerDependencies.  This is really handy in the rare instances when you can’t use constructor injection.  If you don’t have a a correct structure mapping Episerver will throw
‘An exception of type ‘EPiServer.ServiceLocation.ActivationException’ occurred in EPiServer.Framework.dll but was not handled in user code’ error:

episerver_structure_map

Auto Configuration

As developers, we want to write the least amount of code as possible.  Defining all these mappings can be tedious at times.  Luckily, structure maps provides an automatic resolver.

container.Scan(x =&gt;
{
x.TheCallingAssembly();
x.WithDefaultConventions();
});

If you add this code into your configuration, then when the application first loads, StructureMap scans all the types defined in the current assembly, and applies default StructureMap conventions to determine if/how they should be registered in the container.  The WithDefaultConventions part means that if structure maps find an interface called ‘IClass’ for example and also finds class called ‘Class’ that implements ‘IClass’ then automatically register ‘Class’ as the default type for ‘IClass’. Using this approach will save you a lot of time as you can get away without a lot of additional configuration.

Conclusion

That pretty much sums up everything you need to know about structure map to get you up and running.  Below shows my complete IConfigurableModule.

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class StructureMapSetUp : IConfigurableModule
{
private IContainer _container;
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Container.Configure(ConfigureContainer);
DependencyResolver.SetResolver(new StructureMapDependencyResolver(context.Container));
_container = context.Container;
}
public void Initialize(InitializationEngine context)
{
}
public void Preload(string[] parameters)
{
}
public void Uninitialize(InitializationEngine context)
{
}
private static void ConfigureContainer(ConfigurationExpression container)
{
container.For&lt;IEpiserverDependenciesResolver&gt;().Use&lt;EpiserverDependenciesResolver&gt;();
container.For&lt;IBlockHelper&gt;().Use&lt;BlockHelper&gt;();
container.For&lt;IContextResolver&gt;().Use&lt;ContextResolver&gt;();
container.For&lt;ILinkResolver&gt;().Use&lt;LinkResolver&gt;()
.Ctor&lt;IEpiserverDependenciesResolver&gt;().Is&lt;EpiserverDependenciesResolver&gt;();
container.For&lt;IEpiserverDependencies&gt;()
.Use&lt;EpiserverDependencies&gt;();
}
}

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

More Posts

3 replies
  1. David
    David says:

    Good post! I was wondering about the configuration for constructor parameters. I think it is enough to define the mappings for the parameters, instead of using the Ctor feature, right? In your example, The LinkResolver constructor has a parameter of the type IEpiServerDependencyResolver – and the mappings for that interface is done in a couple of rows above – wouldn’t StructureMap recognize the mappings when creating an instance of LinkResolver (without the Ctor config)?

    Reply
    • jon
      jon says:

      Good spot, yes I think your right as long as you have a mapping for the constructor structure map should be clever enough to pick it up.

      Reply

Trackbacks & Pingbacks

  1. […] map and EpiServer many times before, if you want to know a bit more then I recommend reading, EpiServer Structure Map Guide and Dependency Injection In Episerver – ServiceLocator and Injected […]

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

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