ASP.NET MVC Chained Controller Factory

Edit on GitHub

My last post on the REST for ASP.NET MVC SDK received an interesting comment… Basically, the spirit of the comment was: “There are tons of controller factories out there, but you can only use one at a time!”. This is true. One can have an IControllerFactory for MEF, for Castle Windsor, a custom one that creates a controller based on the current weather, … Most of the time, these IControllerFactory  implementations do not glue together… Unless you chain them!

kick it on DotNetKicks.com

Chaining IControllerFactory

The ChainedControllerFactory that I will be creating is quite easy: it builds a list of IControllerFactory instances that may be able to create an IController and asks them one by one to create it. The one that can create it, will be the one that delivers the controller. In code:

[code:c#]

public class ChainedControllerFactory : IControllerFactory
{
    const string CHAINEDCONTROLLERFACTORY = "__chainedControllerFactory";

    protected List<IControllerFactory> factories = new List<IControllerFactory>();

    public ChainedControllerFactory Register(IControllerFactory factory)
    {
        factories.Add(factory);
        return this;
    }

    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        IController controller = null;
        foreach (IControllerFactory factory in factories)
        {
            controller = factory.CreateController(requestContext, controllerName);
            if (controller != null)
            {
                requestContext.HttpContext.Items[CHAINEDCONTROLLERFACTORY] = factory;
                return controller;
            }
        }

        return null;
    }

    public void ReleaseController(IController controller)
    {
        IControllerFactory factory =
            HttpContext.Current.Items[CHAINEDCONTROLLERFACTORY] as IControllerFactory;
        if (factory != null)
            factory.ReleaseController(controller);
    }
}

[/code]

We have to register this one as the default IControllerFactory in Global.asax.cs:

[code:c#]

protected void Application_Start()
{
    ChainedControllerFactory controllerFactory = new ChainedControllerFactory();
    controllerFactory
        .Register(new DummyControllerFactory())
        .Register(new OnlyHomeControllerFactory())
        .Register(new DefaultControllerFactory());

    ControllerBuilder.Current.SetControllerFactory(controllerFactory);

    RegisterRoutes(RouteTable.Routes);
}

[/code]

Note: the DummyControllerFactory and the OnlyHomeControllerFactory are some sample, stupid IControllerFactory implementations.

Caveats

There is actually one caveat to know when using this ChainedControllerFactory: not all controller factories out there follow the convention of returning null when they can not create a controller. The ChainedControllerFactory expects null to determine if it should try the next IControllerFactory in the chain.

Download source code

You can download example source code here: MvcChainedControllerFactory.zip (244.37 kb) (sample uses MVC 2, code should work on MVC 1 as well)

kick it on DotNetKicks.com

This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.

Leave a Comment

avatar

3 responses

  1. Avatar for Troy Goode
    Troy Goode August 21st, 2009

    In other words, a ControllerFactoryFactory. :-)

  2. Avatar for Robert
    Robert October 27th, 2009

    There is one more thing unclear to me: I am using Windsor controller factory in order to wire controllers with all required dependencies. Is there any possibility to continue using Windsor and yet to take advantage of ResourceControllerFactory from REST for ASP.NET MVC SDK?

  3. Avatar for maartenba
    maartenba October 27th, 2009

    The ResourceControllerFactory wraps around the existing controller factory, so if you register your Windsor factory first, followed by the ResourceControllerFactory, you should be fine.