Software Blog

Back

Simple Injector in ASP.NET MVC & WebAPI

TLDR: Simple Injector is good, use it.

As most developers do, we use IOC in our ASP.NET MVC sites, it cleans up the code and allows for better testing.  If you're not familiar with check out this article on Dependency Injection.

One of the longest running IOC libraries is Structure Map, which we originally choose because of it maturity and stability.  After running with this for 4 (ish) years (with complete success), I started to look into different possibilities for my Injector library.  Knowing that Structure Map has every feature you would ever want leads me to think there might be code that is affecting performance.  I only use IOC for a Service Layer & Repository Layer injection and its very simple at that, so I really don’t need all of the bells and whistles. I would rather have less features and better performance.

Dependency Injection in .NET has matured over the years and we now have options upon options.  After researching and reading many different perspectives and gauging community participation, Simple Injector was to be my next experiment.  The following is how I set it up in a new MVC project. (fyi this is all with Visual Studio 2013)

1) On the Package Manager Console input (Tools -> NuGet Package Manager -> Package Manager Console)

Install-Package SimpleInjector -Version 2.4.1

This will install 2 dlls

2) Install WebApi

Install-Package Microsoft.AspNet.WebApi

This installed the needed libs for WebApi

3) The pattern used with the previous Structure Map code will still work here.  Create a file under App_Start named "DependencyConfig.cs"

This is where all of your dependency code would be.  We use PreApplicationStartMethod (.NET 4 and above only) to auto wire up our dependency list and keep things clean.  If you are stuck in a world less than .NET 4.0, you might be able to use WebActivator to get similar functionality.

[assembly: System.Web.PreApplicationStartMethod(typeof(Blog_SimpleInjector.DependencyConfig), "Initialize")]

namespace Blog_SimpleInjector
{
	public static class DependencyConfig
	{
		public static void Initialize()
		{
			//build the injector
		}
	}
}

You can see DependencyConfig is a static class with and Initialize method.  The Assembly attribute will execute Initialize on PreApplicationStartMethod which is the perfect time for DI.

4) Build the Dependency Resolver to integrate with MVC and WebApi

There is another package called Simple Injector ASP.NET MVC Integration that you can install, but I didn't.  I try to limit the # of packages/dlls if I can.  Having done a similar trick with my Strucutre Map code I dove into the source of this package and pulled out only what I needed.  Specifically the SimpleInjectorDependencyResolver.cs file and repurposed the class for MVC and WebApi.  Resulting in the following class

public class SimpleInjectorDependencyResolver : System.Web.Mvc.IDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver, System.Web.Http.Dependencies.IDependencyScope
{
	/// <summary>
	/// Initializes a new instance of the <see cref="SimpleInjectorDependencyResolver"/> class.
	/// </summary>
	/// <param name="container">The container.</param>
	/// <exception cref="ArgumentNullException">Thrown when <paramref name="container"/> is a null
	/// reference.</exception>
	public SimpleInjectorDependencyResolver(Container container)
	{
		if (container == null)
		{
			throw new ArgumentNullException("container");
		}

		this.Container = container;
	}

	/// <summary>Gets the container.</summary>
	/// <value>The <see cref="Container"/>.</value>
	public Container Container { get; private set; }

	/// <summary>Resolves singly registered services that support arbitrary object creation.</summary>
	/// <param name="serviceType">The type of the requested service or object.</param>
	/// <returns>The requested service or object.</returns>
	public object GetService(Type serviceType)
	{
		// By calling GetInstance instead of GetService when resolving a controller, we prevent the
		// container from returning null when the controller isn't registered explicitly and can't be
		// created because of an configuration error. GetInstance will throw a descriptive exception
		// instead. Not doing this will cause MVC to throw a non-descriptive "Make sure that the 
		// controller has a parameterless public constructor" exception.
		if (!serviceType.IsAbstract && typeof(IController).IsAssignableFrom(serviceType))
		{
			return this.Container.GetInstance(serviceType);
		}

		return ((IServiceProvider)this.Container).GetService(serviceType);
	}

	/// <summary>Resolves multiply registered services.</summary>
	/// <param name="serviceType">The type of the requested services.</param>
	/// <returns>The requested services.</returns>
	public IEnumerable<object> GetServices(Type serviceType)
	{
		return this.Container.GetAllInstances(serviceType);
	}

	IDependencyScope System.Web.Http.Dependencies.IDependencyResolver.BeginScope()
	{
		return this;
	}

	object IDependencyScope.GetService(Type serviceType)
	{
		return ((IServiceProvider)this.Container)
			.GetService(serviceType);
	}

	IEnumerable<object> IDependencyScope.GetServices(Type serviceType)
	{
		return this.Container.GetAllInstances(serviceType);
	}

	void IDisposable.Dispose()
	{
	}
}

Notice the inheritance here, both the System.Web.Mvc & System.Web.Http namespaces are included, allowing me to use a single class to handle both MVC & WebApi.  This class works, is it best practice?  I really don't know, you could split them up if you wanted to but this seemed to make more since to me.  I actually place this class directly into the DependencyConfig.cs file to keep everything together.  Once this is wired up, you can then inject on your MVC Controllers and your API controllers following the same pattern.

5) Connect Initialize with the Dependency Resolver

DependencyConfig.cs now needs to do some work in the Initialize method.

public static void Initialize()
{
    var container = BuildContainer();
	
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorDependencyResolver(container);
}

public static Container BuildContainer()
{
    var container = new Container();
    var lifestyle = Lifestyle.Singleton;
	
    //repository
    container.Register<IAccountRepository, AccountRepository>(lifestyle);
	
    //service
    container.Register<IAccountService, AccountService>(lifestyle);
    container.Verify();
	
    return container;
}

A new method is created that will contain the custom code to the application. BuildContainer registers AccountRepository & AccountService to the corresponding interfaces.  Build your list as your application demands.  Because we created a combined class for our Dependency Resolver that covers both MVC and WebApi the resolver code is very clean.

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

Covers MVC and

GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorDependencyResolver(container);

Covers WebApi

5) Enjoy your IOC!

You can now use constructor injection for anything that you need. In the above code Account Service could take an IAccountRepository in its constructor and the resolvers will handle it for you.  Most of my Controllers have a constructor needing my Service layer classes, so IAccountService would be delivered to my controller automagically.

Jason Brozek

Feedback? Better Idea? General Comment?

RSS