2

Why Controllers should have a default constructor?

by volkanuzun 13. November 2009 03:21

    I am still in the journey of exploring MVC source code.  Yesterday, I wrote about controllers and why they need “Controller” suffix. Today, I will try to find out in the code, why does a controller need a default constructor. First of all, what is default constructor?
You can check wikipedia for its complete definition; but basically a default constructor is a constructor that has no parameters. If there is no other constructors in the code, compiler puts a default constructor for you in the code. You don’t believe me? Here is a simple class:

public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }


This class does not have any type of constructors, so the compiler put a default constructor for us. compile the project, check the assembly with either reflector or ildasm tool. You will see the default constructor in your compiled code (besides some other stuff):

image 
.ctor() is the default constructor that the compiler added for us, when we did not supply any constructor. So what happens when we add a constructor that takes a parameter but no default constructor:

public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public Person(string FirstName)
        {
            this.FirstName = FirstName;
        }
    }

We now have a constructor that takes the FirstName as a parameter, and we don’t have a default constructor. This time if you check the assembly again, you will find:

image

You see that, the constructor .ctor does take 1 parameter, and there is no default constructor for us. This means when you want to create a new instance of Person, you can NOT use parameter less constructor such as: Person p = new Person();  You have to call it with a parameter.
So far, this is basic C#, where is MVC section? Here you are:

When a request comes into the MVC, we saw that the framework finds the controller first. Inside the DefaultControllerFactory (if you downloaded the source code, it is in DefaultControllerFactory.cs line # 83), an instance of the controller is being created to process the request. Here is the code from the controller factory:

 protected internal virtual IController GetControllerInstance
(Type controllerType) { // some code is here... try { return (IController)Activator.CreateInstance(controllerType); } // some other code is here...

Activator.CreateInstance is used to create an instance of the controller. Let’s see MSDN for Activator.CreateInstance:

“CreateInstance(Type)    Creates an instance of the specified type using that type's default constructor.” So Activator.CreateInstance(controllerType) will create an instance of the specified controller using the controller’s default constructor. This is the main reason controllers should have a constructor, as DefaultControllerFactory creates the controller by using its default constructor.  Luckily if we don’t have a default constructor, the framework will throw an exception at runtime when it is trying to generate a new instance (I wish we could have compile time error).  The error you will have is very self explanatory.

image 

The framework is even showing us the exact location that throws the exception. So we need to supply a default constructor if we have defined constructors with parameters.
Why would you have a constructor in your controller that takes parameter if the framework does not call it? For 2 simple reasons:

  1. Unit Testing: You want to unit test your controller, and by supplying some values in the constructor you can swap the dependencies with some other implementations that you have control of.
  2. You want to do inversion of control. Basically if you have a class, and your class depends on some other entities (such as your controller needs a class to communicate with database, or a logger class to log the errors), it shouldn’t be a task of your controller to create an instance of this classes that it depends. The classes  should be instantiated and given to your controller ready to use.

 

Let’s see an example again, assume you have a DatabaseLogger class which derives from ILogger interface and sends the logged message to the database:

public interface ILogger
{
    void SendMessage(string Message);
}

public class DatabaseLogger: ILogger
{
    public void SendMessage(string Message)
   {
      // some code to write the message to the database


Our HomeController needs the DatabaseLogger class to send some messages. One way  of doing this is to put the instantiation inside the default controller such as:

public class HomeController:Controller
{
    private ILogger logger;

    public HomeController():base(new DatabaseLogger())
    {     
    }

    public HomeController(ILogger logger)
    {
        this.logger = logger;
    }
}

There are 2 constructors in this controller. The second one that has a parameter, sets the controller’s dependency to the passed in logger interface. The default constructor is creating an instance of DatabaseLogger and passing this to the second constructor. With this technique here we can unit test our controller as the second constructor gives us the ability to swap the ILogger with an object that we can control.  However, if you look at the default constructor, the controller is creating the class that it has the dependency on. It should be passed the depedency ready to use. In this simple example maybe the benefit is not obvious however think that DatabaseLogger() needs some construction parameters that will setup the database connection string, and maybe to read the database connection string, you have some other dependencies such as a configuration file reader. Now your homecontroller has to supply all these settings to create the DatabaseLogger. This is too much now, this is where you need to use dependency injection such as Castle Windsor, StructureMap, Ninject etc…

This will be another story :)

Tags: ,

MVC

Comments

Tom Opgenorth
Tom Opgenorth Canada
11/13/2009 5:48:46 AM #

Hey Volkan, I'd have to respectfully disagree with you on this one.  If your controller has no dependencies, then sure, have a default constructor.  However, if your controller has dependencies, then this technique (aka Poor Man's DI) can cause problems.

If you check out MVCContrib, you'll see that with the use of the IoC of your choice this whole problem goes away.

Anyway, we can discuss more when I head down to sunny California this March.

volkanuzun
volkanuzun United States
11/13/2009 6:07:04 AM #

Hi Tom,
I agree that pmd is not that great, I am trying to dig in to MVC source code, and explain it while learning it. I am already planning to write a blog about Ninject.
It is always great seeing you here Smile

Comments are closed

Powered by BlogEngine.NET 1.6.0.0
Original Design by Laptop Geek, Adapted by onesoft