For the past few weeks, I've been working on creating a RESTful web service using the new ASP.NET Web API framework. One particular problem that arose for me was how to handle dependency injection for controllers. Basic constructor injection won't work out of the box because the framework automatically creates the controllers for you and doesn't know anything about their dependencies. On the ASP.NET website, there's a helpful post discussing the use of the
Web API Dependency Resolver which provides an example of how to create "A Simple Dependency Resolver" that can create objects that the framework requires at run time, including controllers. The example works just fine, but if your API has more than a few controllers it can become very cumbersome to maintain. This is where IoC (Inversion of Control) containers can be very handy. The ASP.NET post goes on to provide an example of how to use the
Unity IoC container which was developed by Microsoft. I, however, wanted to explore other options of IoC containers to use. After doing quite a bit of research, I finally settled on using
Castle Windsor.
If you are unfamiliar with the IoC technique, I highly recommend reading
this 4-part article by Simone Busoli which talks about the overall concept of IoC as well as providing some Castle Windsor specific implementation.
Unfortunately, the specifics on how to setup and use Castle Windsor in an ASP.NET Web API project are a bit difficult to find and, at the moment, are scattered all over the internet. So, this post is my attempt to put it all together in one concise place. I don't go into great detail about some of the Castle Windsor specifics in my examples, but I've and provided links that should help fill in the blanks.
IDependencyResolver
First things first. The ASP.NET Web API framework allows you to configure a custom "Dependency Resolver" which handles the instantiation of objects (like controllers) and their dependencies behind the scenes. What we're going to do is create a custom "WindsorDependencyResolver" which, as it's name implies, resolves dependencies using the Castle Windsor container. Our WindsorDependencyResolver will need to implement System.Web.Http.Dependencies.IDependencyResolver (NOT System.Web.Mvc.IDependencyResolver). Our class will initially look like this:
public class WindsorDependencyResolver : IDependencyResolver
{
public IDependencyScope BeginScope()
{
throw new NotImplementedException();
}
public object GetService(Type serviceType)
{
throw new NotImplementedException();
}
public IEnumerable<object> GetServices(Type serviceType)
{
throw new NotImplementedException();
}
public void Dispose()
{
throw new NotImplementedException();
}
}
The first thing our new class needs is an actual Windsor Container. So lets add a private field and call it _container, as well as a constructor to instantiate it. While we're at it we can implement the GetService, GetServices and Dispose methods:
public class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
throw new NotImplementedException();
}
public object GetService(Type serviceType)
{
if(_container.Kernel.HasComponent(serviceType)
return this._container.Resolve(serviceType);
else
return null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
_container.Dispose();
}
}
Notice that even in our dependency resolver class, we're still using a good dependency injection pattern. The IWindsorContainer interface will be implemented by a WindsorContainer object which we will discuss in detail later. The GetService, GetServices, and Dispose methods will be calling the
Resolve, ResolveAll, and
Dispose methods of the injected WindsorContainer object. It is important to note that the GetService method should return null if the component was not available, this will ensure that the framework default implementation will be used instead.
IDependencyScope (borrowing heavily from Can Gencer's post)
During the life-cycle of a request, a dependency scope (implemented by IDependencyScope) is created on the request using the BeginScope method on the IDependencyResolver. You guessed it, we need to create our own implementation of IDependencyScope. Since IDependencyResolver inherits from IDependencyScope, our "WindsorDependencyScope" implementation will look pretty similar to our "WindsorDependencyResolver" one:
public class WindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorDependencyScope(IWindsorContainer container)
{
this._container = container;
this._scope = container.BeginScope();
}
public object GetService(Type serviceType)
{
if (_container.Kernel.HasComponent(serviceType))
return _container.Resolve(serviceType);
else
return null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this._container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
this._scope.Dispose();
}
}
The Scoped Lifestyle is a new lifestyle in Castle Windsor 3 that makes it possible to create an arbitrary scope bounded by the object returned from the Container.BeginScope call. When this object is disposed, the scope is ended and Castle will then release all the objects with Scoped lifestyle that have been resolved in the same call stack after the scope is generated. Our WindsorDependencyResolver's BeginScope method can now be updated:
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
With our WindsorDependencyResolver and WindsorDependencyScope implementations, we're ready to register our components (using installers) and then replace the default dependency install with our Windsorified one.
Windsor Installers
I don't want to spend too much time on this, but in order for the Windsor IoC container to work, your application's services (interfaces) and components (concrete implementations) must be registered. Windsor uses Installers to encapsulate and partition the registration logic. You can read all about Installers and how to use them on Windsor's
website. Windsor strongly recommends that a "single installer installs some coherent closed set of related services (like repositories, controllers, etc), and you have separate installer for each of these sets." So, this means that we should write one installer that is dedicated to our controllers, and another installer for the stuff (repositories for example) that our controllers depend on, and so forth. Assuming all of our controllers inherit from ApiController abstract class, our controller installer could look like this:
public class ApiControllersInstaller : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<ApiController>()
.LifestylePerWebRequest());
}
}
Generally speaking, the
lifestyle of a controller (and it's dependencies) should be "
per web request." Remember, you'll need a separate installer for each separate set of related services. So if you have a typical MVC/Web API architecture with Controllers that depend on Business Services, which depend on Data Repositories then you'll need at least three separate installers (one for each layer).
Putting it All Together
Now we're ready to put everything together. Somewhere inside the Application_Start method of Global.asax add the following lines of code:
IWindsorContainer container = new WindsorContainer();
container.Install(FromAssembly.This());
config.DependencyResolver = new WindsorDependencyResolver(container);
First we instantiate a new WindsorContainer. Then we
install our installers into the container, utilizing the FromAssembly helper method. Finally we replace the default dependency resolver with our custom WindsorDependencyResolver.
Happy injecting!