How to create a custom controller factory ASP.Net MVC

Table of Content

I was reading about "Control application behavior by using MVC extensibility points" which is one of the objectives for the 70-486 Microsoft certification, and it was not clear to me, the explanation provided. So I decided to write about it to make clear for me, and I hope this help you as well.

An ASP.NET MVC application contains the following class:

public class HomeController: Controller
{
   public HomeController(Ilogger logger)//notice the parameter in the constructor
   {

   }
}

This throw an error with the DefaultControllerFactory see image below.
Dependency injection controller error

The application won't be able to load the HomeController because it have a parameter. You need to ensure that HomeController can be instantiated by the MVC framework. In order to accomplish this we are going to use dependency injection.

The solution is to create a custom controller factory.

It calls the default constructor of that class. To have the MVC framework create controller class instances for constructors that have parameters, you must use a custom controller factory. To accomplish this, you create a class that implements IControllerFactory and implement its methods. You then call the SetControllerFactory method of the ControllerBuilder class to an instance of your custom controller factory class.

Create the CustomControllerFactory that inherit from IControllerFactory:

 public class CustomControllerFactory : IControllerFactory
    {

        public CustomControllerFactory()
        {
        }


        public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
             ILogger logger = new DefaultLogger();
        var myController = new HomeController(logger);
        return controller;
        }

        public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
             return SessionStateBehavior.Default;
        }

        public void ReleaseController(IController controller)
        {
            var disposable = myController as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }

        }
    }

 

book

Book Tip

MCSD Certification Toolkit (Exam 70-483): Programming in C
The MCSD 70-483 exam is the entry-level Microsoft certification exam for C# developers and this must-have resource offers essential coverage of the exam that will test your competency in C# programming.


Amazon

 

You can implement the CreateController() method with a more generic way, using reflection.

public class CustomControllerFactory : IControllerFactory
{
    private readonly string _controllerNamespace;
    public CustomControllerFactory(string controllerNamespace)
    {
        _controllerNamespace = controllerNamespace;
    }
    public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        ILogger logger = new DefaultLogger();
        Type controllerType = Type.GetType(string.Concat(_controllerNamespace, ".", controllerName, "Controller"));
        IController controller = Activator.CreateInstance(controllerType, new[] { logger }) as Controller;
        return controller;
    }
} 

Set your factory in Application_Start by using SetControllerFactory method:

 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory));
        }

This could be one of the objective of the Microsoft certification exam 70-486, more specific for "Develop the user experience", sub-objective "Control application behavior by using MVC extensibility points".
Hope this helped you to understand how to do dependency injection in controllers with MVC.

External references:
http://www.asp.net/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-dependency-injection