Custom Controller Factory in ASP.NET MVC

25 Jul
2010

I am using ASP.NET MVC framework from the time first beta bits released, I am big fan of this framework because of it’s extensibility and specifically simplicity.

ASP.NET MVC framework activates the controllers when a request arrived to it’s pipeline. Default naming and structure rules of controllers are :

  • Controller class name must ends with “Controller”.
  • Controller class must have constructor with no parameters.

These constraints come from the default controller factory of ASP.NET MVC Framework.

Why I need to create a custom controller factory?

It doesn’t have a meaning to create because of you can create that. You may need to create your controllers in a special way like we are doing in this post, you may want to pass some parameters on constructor of controllers. You may want to manage the lifetime of objects required by controller constructors with an IoC library (like windsor, structuremap).

It’s a good practice to passing required Repository objects on constructor, so you can pass actual mocked or stub objects in the unit tests, plus, in runtime your repository objects lifetime can manage by your IoC library.

For example, I created a basic CustomerController with a action named GetCustomers.

using System.Web.Mvc;
namespace develoq.mvc.ccfactory.Controllers
{
  public class CustomerController : Controller
  {
    public CustomerController(string dummyParameterFor2CreateException)
    {

    }
    // GET: /Customer/GetCustomers
    public ActionResult GetCustomers()
    {
      return View();
    }

  }
}

Normally I must create a constructor with no parameters, for only creating an exception and demonstrating the case I added a string parameter to the constructor of the controller.

mvc_ccf1

If you try to invoke this controller action, it will throw an exception. Please look in to the stacktrace DefaultControllerFactory.GetControllerInstance method fires an exception while trying to invoke Activator.CreateInstance method (this reflection method creates an instance of an object).

No parameterless constructor defined for this object.

The point that I am trying to come is extensibility features of ASP.NET MVC Framework. You can create your own Controller Factory type, and plug them in the pipeline instead of default controller factory.

I created a new controller factory class, you can implement the IControllerFactory interface, or you can inherit from the DefaultControllerFactory class which implements IControllerFactory. I implemented IControllerFactory interface because of simplicity of the demonstration.

using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace develoq.mvc.ccfactory
{
  public class DeveloqControllerFactory : IControllerFactory
  {
    public IController CreateController(RequestContext requestContext, string controllerName)
    {
      //TODO :IoC implementation or call comes here.
      return null;
    }
    public void ReleaseController(IController controller)
    {
      var disposable = controller as IDisposable;
      if (disposable != null)
      {
        disposable.Dispose();
      }
    }
  }
}

After creating my customer controller factory class named DeveloqControllerFactory, I need to register this controller factory. Add a method call to the ControllerBuilder.Current.SetControllerFactory method in your Application_Start method in the global.asax.cs class.

protected void Application_Start()
{
   AreaRegistration.RegisterAllAreas();
   RegisterRoutes(RouteTable.Routes);
   ControllerBuilder.Current.SetControllerFactory(typeof(develoq.mvc.ccfactory.DeveloqControllerFactory)); 
}

After successfully activated my new controller factory, I added a breakpoint to the CreateController method and requested the same action of the controller (/Customer/GetCustomers), as you can see image at the below controllerName parameter contains de name of Controller, “Customer”.

mvc_ccf2

After this step I need to implement my own reflection implementation. I will not cover the using IoC in my controller factory. This will be a subject for another post.

Because of I am not indented to use an IoC library in this post, I implemented CreateController method in a basic and demonstration purposed style, for example, it gets controller name and controller type mapping from a hardcoded dictionary.

Full implementation of DeveloqControllerFactory

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;

namespace develoq.mvc.ccfactory
{
  public class DeveloqControllerFactory : IControllerFactory
  {
    public IController CreateController(RequestContext requestContext, string controllerName)
    {
      //TODO :IoC implementation or call comes here.
      IController controllerObject = null;
      Type controllerType = findTypeForTheControllerName(controllerName);
      if (controllerType != null)
      {
        var args = new object[] { "Develoq magic controller constructor string"};
        controllerObject = (IController)Activator.CreateInstance(controllerType, args);
      }
      return controllerObject;
    }
    public void ReleaseController(IController controller)
    {
      var disposable = controller as IDisposable;
      if (disposable != null)
      {
        disposable.Dispose();
      }
    }

    private static Type findTypeForTheControllerName(string controllerName)
    {
      var dummyControllerIoCDictionary = new Dictionary<string,string>();
      dummyControllerIoCDictionary.Add("Customer",
            "develoq.mvc.ccfactory.Controllers.CustomerController,develoq.mvc.ccfactory");
      string fullTypeName;
      Type type = null;
      if (dummyControllerIoCDictionary.TryGetValue(controllerName, out fullTypeName))
      {
        type = Type.GetType(fullTypeName);
      }
      return type;
    }

  }
}

After completed implementation of controller factory, I made another request to the same action (/Custome/GetCustomers) and added some breakpoint to the code to see what is going on.

mvc_ccf3 

And the magic string of us passed to the controller as a constructor parameter.

mvc_ccf4

In this example I tried to give answer of the “What is Controller Factory?” and “How can I implement my own Controller Factory?”. I want to write another post about using IoC for constructing controllers and repositories.



4 Responses to Custom Controller Factory in ASP.NET MVC

Avatar

Ryan

May 2nd, 2012 at 11:02 pm

I realize this post is a couple years old, but you definitely helped me out a ton by describing this functionality. Thanks!

Avatar

shiran Ginige

August 15th, 2012 at 1:43 pm

the nicest thing about this post is, I could get the idea just by looking at the screen-shots, without reading a single paragraph!

Avatar

Blogged By Chris » Microsoft Exam 70-486 Study Guide

November 6th, 2012 at 8:47 am

[...] ASP.NET MVC Applications and Custom Controller Factory in ASP.NET MVC develoq.net (covers “implement MVC filters and controller factories” section) [...]

Avatar

Using Ninject with DD4T | Building Blocks Knowledge Share

January 11th, 2013 at 5:38 pm

[...] with your own. Don’t like the way ASP.NET MVC creates your controllers? No problem, just write your own ControllerFactory. DD4T has followed this pattern with a provider model to enable it to work with Tridion 2011, 2011 [...]

Comment Form

top