Search code examples
asp.net-mvc-3controller-factory

How can I load multiple controller factories and pass control on to the next one?


I've created a generic controller factory to load entities from the database by parsing out the url:

entity/products/123456.htm

However, I'd like to be able to load an actual controller if the entity is not found, or to override the default entity behavior if necessary by creating a physical controller, instead of a "virtual" one created by the URL pattern.

Right now, in global.asax.cs I'm doing:

ControllerBuilder.Current.SetControllerFactory(typeof(EntityControllerFactory));

How can I, either in EntityControllerFactory, or here in global.asax.cs, pass control on to another factory, in the event that I'd like MVC's default controller/action scheme to take over?


Solution

  • You could create a composite IControllerFactory implementation:

    public class EntityControllerFactory : IControllerFactory {
        private IControllerFactory defaultFactory = new DefaultControllerFactory();
    
        public IController CreateController(RequestContext requestContext, string controllerName) {
            if(needsCustomLogic) {
                // do your custom logic here and return appropriate result
            } else {
                return defaultFactory.CreateController(requestContext, controllerName);
            }
        }
    
        // same for the other methods on IControllerFactory
    }
    

    This works because by default the value of ControllerBuilder.Current.GetControllerFactory() is an instance of DefaultControllerFactory.

    You might also consider making your factory more future-proof (in case a new version of MVC starts returning a different type from GetControllerFactory; unlikely but it could happen) by getting the default instance and passing it into your factory:

    // in Global.asax
    var defaultFactory = ControllerBuilder.Current.GetControllerFactory();
    ControllerBuilder.Current.SetFactory(new EntityControllerFactory(defaultFactory));