Enabling Add-In functionality in ASP.NET MVC 3 (Part 2)

August 22, 2011 | ASP.NET MVC

In this post I discussed the implementation of a Unity-specific controller factory  that could take a delegate as a parameter in the constructor acting as the fallback factory when the DI container can not supply a controller.

However, I did not really like the initial design. There are cases when the UnityControllerFactory can be used standalone without third party extensiblity in mind.

One possible improvement in the design is to introduce a composite implementation for an IControllerFactory. That way, we still have the chance to supply a MEF-specific controller factory.

A possible implementation of the CreateController method is the one below:

public override IController CreateController(
   RequestContext requestContext, 
   string controllerName)
{
    return (from factory in this.Factories
            let controller = factory.CreateController(
                requestContext, controllerName)
            where controller != null
            select controller).FirstOrDefault();
}

It will iterate through all controller factories calling their CreateController method. The first IController instance provided by the controller factories is returned.

With this implementation, if the Unity-specific controller factory can not provide an IController instance we will ask the next controller factory (MEF-specific controller factory in this example) to provide the IController instance, and so on.

The SetControllerFactory method can accept an instance of a CompositeControllerFactory type as shown below:

private static void BootstrapContainer()
{
    // No direct reference on the container outside this method.
    var unityControllerFactory = new UnityControllerFactory(
        new UnityContainer()
            .Install(Registrator.ForControllers,
                     Registrator.ForServices,
                     Registrator.ForEnterpriseLibrary));


    string extensionsPath = Path.Combine(
        AppDomain.CurrentDomain.BaseDirectory, "Extensions");

    var discoverableControllerFactory = new DiscoverableControllerFactory(
        new CompositionContainer(
            new DirectoryCatalog(extensionsPath))
            );

    ControllerBuilder.Current.SetControllerFactory(
        new CompositeControllerFactory(
            unityControllerFactory, 
            discoverableControllerFactory)
            );
}

ImplementationUnit tests and NuGet Package. Sample application available here.