Integrating MVC Web API with Castle.Windsor

Unfortunately the mechanism we use to integrate the normal MVC controllers with Castle.Windsor doesn’t work when we have to integrate Web API controllers. In order to integrate these kind of controllers as well we need to use another technique. First of all we need to create a new Dependency Resolver and a new Dependency Scope (e.g. within the usual “Infrastructure” folder):

public class CastleDependencyResolver : IDependencyResolver
{
    private readonly IKernel _kernel;
 
    public CastleDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }
 
    public IDependencyScope BeginScope()
    {
        return new CastleDependencyScope(_kernel);
    }
 
    public object GetService(Type type)
    {
        return _kernel.HasComponent(type) ? _kernel.Resolve(type) : null;
    }
 
    public IEnumerable<object> GetServices(Type type)
    {
        return _kernel.ResolveAll(type).Cast<object>();
    }
 
    public void Dispose()
    {
    }
}

public class CastleDependencyScope : IDependencyScope
{
    private readonly IKernel _kernel;
    private readonly IDisposable _disposable;
 
    public CastleDependencyScope(IKernel kernel)
    {
        _kernel = kernel;
        _disposable = kernel.BeginScope();
    }
 
    public object GetService(Type type)
    {
        return _kernel.HasComponent(type) ? _kernel.Resolve(type) : null;
    }
 
    public IEnumerable<object> GetServices(Type type)
    {
        return _kernel.ResolveAll(type).Cast<object>();
    }
 
    public void Dispose()
    {
        _disposable.Dispose();
    }
}

Now we have to tell MVC Framework to use our DependencyResolver instead of the default one. To do this we have to add some code (as usual) to the Application_Start() method of the global.asax file. Here is how it appears with both the normal MVC and the Web API controllers configured to be integrated with Castle.Windsor:

void Application_Start(object sender, EventArgs e)
{
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
 
    //Creates Castle Container
    var container = new WindsorContainer();
    container.Install(new CastleInstaller());
 
    //Creates Castle Controller Factory (MVC)
    var castleControllerFactory = new CastleControllerFactory(container);
    ControllerBuilder.Current.SetControllerFactory(castleControllerFactory);
 
    //Creates Castle Controller Factory (Web API)
    var castleDependenctResolver = new CastleDependencyResolver(container.Kernel);
    GlobalConfiguration.Configuration.DependencyResolver = castleDependenctResolver;
}

Adding all the controllers to the installer

As usual we must register all the Web API controllers (as we did with the normal MVC controllers). Here is how to register both the normal MVC and the Web API controllers with few lines of code:

//Register all the controllers
//in the current executing assembly
container.Register(Classes.FromThisAssembly().BasedOn<Controller>().LifestylePerWebRequest());
container.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestyleScoped());
Advertisements

Interceptors with Castle.Windsor

While registering a dependency I can tell Castle that I want to set an interceptor for its methods. Before each dependency’s method is invoked the interceptor will be called, with the opportunity to proceed with the invocation, stop it, or execute other operation before its execution. Interceptors are very useful with legacy code, that we prefer not to touch, to append additional behaviors to the methods. Here is an example with different ways to set an interceptor:

public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(
 
        //Here I'm setting the interceptors for the IRepository dependency.
        //I'm referring the interceptors to use by telling Castle their name.
        //With "Anywhere" I'm telling that all the interceptor must trigger
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>()
            .Named("RepositoryInterceptor"),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors(InterceptorReference.ForKey("RepositoryInterceptor"))
            .Anywhere,
 
        //Here I'm telling Castle which interceptor to use by its type. I can
        //create sub-interfaces of IInterceptor to group different interceptors
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>(),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors(InterceptorReference.ForType<IInterceptor>()).Anywhere,
 
        //This is another way to refer interceptors by type
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>(),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors<IInterceptor>(),
 
        //Here I'm using a selector to filter which interceptor use for each
        //method of the target dependency. Is useful when i want an interceptor
        //to be called only for some particular methods
        Component.For<IInterceptor>().ImplementedBy<RepositoryInterceptor>(),
        Component.For<IRepository>().ImplementedBy<Repository>()
            .Interceptors(InterceptorReference.ForType<IInterceptor>())
            .SelectedWith(new InterceptorSelector()).Anywhere,
 
        Component.For<IService>().ImplementedBy<Service>());
}

Here is our interceptor:

public class RepositoryInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Debug.Print("The Repository {0} method has been called with arguments {1}",
            invocation.Method.Name, invocation.Arguments.FirstOrDefault());
        invocation.Proceed();
    }
}

Here is our selector:

public class InterceptorSelector : IInterceptorSelector
{
    public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
    {
        if (type == typeof(Repository))
            if (method.Name == "GetList")
            {
                return interceptors.Where(i => i.GetType() == typeof(RepositoryInterceptor)).ToArray();
            }
        return null;
    }
}

Specifying an alternative resolution rule with Castle.Windsor

Let’s imagine that we want a particular interface resolved with a particular element (another class for example, or the same class but with a different lifestyle) just when is a dependency of a particular object. In all other situations we want to use another basic rule. How can we do this with Castle.Windsor?

First of all we define the two different rules (in this case we want our interface to be resolved with an Entity Framework context with two different lifestyles)

//This is the default rule. In Castle.Windsor, when multiple rules match, the first one wins.
//If we aren't sure about the rule's order (because the rules are in different files) we can
//use the IsDefault() method to force Castle.Windsor to use a particular rule as default
Component.For<MyDependency>().ImplementedBy<MyDependency>().LifestylePerWebRequest().IsDefault(),
 
//This is our alternative rule. In order to use it we must provide a name with the Named() method,
//so we can specifically instruct Castle.Windsor to use this rule when resolving a dependancy
Component.For<MyDependency>().ImplementedBy<MyDependency>().Named("MyDependency_Singleton"),

(Notice that in this case we are defining a rule for a dependency that isn’t an interface, but a normal class, so we are telling Castle.Windsor to use the same class to resolve the dependency.) As we can see our two rules are different just for the lifestyle: the first one is for web request and the second one is a singleton (as default). We know that the first rule is the default one, so we are sure that the second rule will never be used, unless we expressly require to use it. Ho can we do this? Within the configuration of the object which have a dependency on MyDependency and that must resolve that dependency using the second rule we can write:

Component.For<IMyRepository>().ImplementedBy<MyRepository>()
    .DependsOn(Dependency.OnComponent("myDependencyParameterName", "MyDependency_Singleton"),

Here we are using the DependsOn() method (the same we use to specify a constant dependency) to say that we want to to resolve the “myDependencyParameterName” contructor’s parameter using the “MyDependency_Singleton” rule, instead of the default one.

Integrating MVC with Castle.Windsor

To be able to use the DI within our MVC controllers we have to replace the default MVC Framework’s Controller Factory with a custom one that uses Castle.Windsor. First of all we have to create the new Controller Factory (e.g. within a folder named “Infrastructure”):

public class CastleControllerFactory : DefaultControllerFactory
{
    public IWindsorContainer Container { get; private set; }
 
    public CastleControllerFactory(IWindsorContainer container)
    {
        if (container != null)
        {
            Container = container;
        }
        else
        {
            throw new ArgumentNullException("container");
        }
    }
 
    protected override IController
        GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        //Resolves Controller
        if (controllerType != null)
        {
            return Container.Resolve(controllerType) as IController;
        }
        return null;
    }
 
    public override void ReleaseController(IController controller)
    {
        if (controller is IDisposable)
        {
            ((IDisposable)controller).Dispose();
        }
 
        //Releases Controller
        Container.Release(controller);
    }
}

Now we have to tell MVC Framework to use our Controller Factory instead of the default one. To do this we have to add some code to the Application_Start() method in the global.asax file:

void Application_Start(object sender, EventArgs e)
{
    AreaRegistration.RegisterAllAreas();
    RouteConfig.RegisterRoutes(RouteTable.Routes);
 
    //Creates Castle Container
    var container = new WindsorContainer();
    container.Install(new CastleInstaller());
 
    //Creates Castle Controller Factory (MVC)
    var castleControllerFactory = new CastleControllerFactory(container);
    ControllerBuilder.Current.SetControllerFactory(castleControllerFactory);
}

The CastleInstaller class is the usual class that we use to configure the mapping between each interface and its concrete class. We can create it within the same “Infrastructure” folder in which we created the Controller Factory.


Adding all the controllers to the installer

To have Castle working with our MVC application we should remember to register all the controllers within our CastleInstaller class. To avoid this (and to not have a too long configuration) we can automatically set the configuration of all the controllers via reflection. In this way any new controller will be found and properly added to Castle without writing any explicit line of code. Here is the code:

//Register all the MVC controllers
//in the current executing assembly
container.Register(Classes.FromThisAssembly().BasedOn<Controller>().LifestylePerWebRequest());

IoC and DI with Castle.Windsor

Castle.Windsor is the most complete and diffused IoC Container for .Net (is more powerful than Ninject).

To configure the IoC Container we have to specify the mapping between each interface and its concrete class. This can be done within a class which implements the IWindsorInstaller interface:

class CastleInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<IDependency1>().ImplementedBy<Dependency1>());
        container.Register(Component.For<IDependency2>().ImplementedBy<Dependency2>());
        container.Register(Component.For<IDependency3>().ImplementedBy<Dependency3>());
        container.Register(Component.For<IDependency4>().Instance(new Dependency()
        {
            Property1 = "Value1",
            Property2 = "Value2",
            Property3 = "Value3",
        }));
    }
}

After the configuration has been defined we can create the container and use it to resolve our instances. Castle will automatically resolve each dependency with the configured object:

static void Main(string[] args)
{
    //Creates Castle Container
    WindsorContainer container = new WindsorContainer();
    container.Install(new CastleInstaller());
 
    //Resolves MarshallFeed Service
    IMarshallFeedService service = container.Resolve<IMarshallFeedService>();
 
    ...
 
    //Releases MarshallFeed Service
    container.Release(service);
}

Automatically installing all the installer within an assembly

Instead of providing a specific instance of the installer to the container.Install() method (as in the example above) we can tell Castle to find all the installers within the assembly and to install them:

container.Install(FromAssembly.This());