Thursday, January 8, 2015

Controllers in MVC


In this third blog post, I am going to talk about the heart of an MVC application: The Controllers.

CONTROLLER

In old web applications, there used to be a direct relationship between the URL and web server's hard drive. In an MVC application, similar relationship exists between the URL and controller's action methods. That will become more clear when I explain routing in a future post. Until then, just understand that routing allows us to map a URL to a controller action.
Controllers are the classes which respond to user input. It contains the actions that are executed on a user request and build a response that is returned to the user. In other words, they control the flow of execution, i.e. they work with the data coming in and provide the data going out to the relevant view.

By now, I will expect that you have installed an MVC project in Visual Studio 2013. By default, the project has 2 controllers: HomeController and AccountController. Technically, controller is a simple class derived from System.Web.MVC Controller class. Let's talk about this in detail.

Controller Class

If we take a closer look at the Controller class, we will see that it's an abstract class derived from ControllerBase class and implementing a bunch of interfaces where IController is one of the interface.

public abstract class Controller : ControllerBase, 
       IActionFilter, IAuthorizationFilter, IDisposable, 
       IExceptionFilter, IResultFilter, IAsyncController, 
       IController, IAsyncManagerContainer
 

Since its an abstract class, we cannot instantiate it directly. In order to understand the relationship between IController, ControllerBase and Controller classes, lets take a closer look at these.

IController

 IController interface has an Execute method which gets executed when a request is made for the controller. This takes RequestContext as a parameter. When a request cones in, the routing system identifies the appropriate controller and executes the Execute method


// Summary:
    //     Defines the methods that are required for a 
    //     controller.
    public interface IController
    {
        // Summary:
        //     Executes the specified request context.
        //     The request context.
        void Execute(RequestContext requestContext);
    }




ControllerBase

ControllerBase is another abstract base class that layers some more API surface on top of the IController interface. It implements Execute method of IController where it creates ControllerContext, which in turn, encapsulates information about HTTP request that matches specified RouteBase and ControllerBase instances.
It also provides TempData, ViewData, ViewBag, etc. We can look at their data types here. ViewData and ViewBag are used to send data from controller to view. ViewData is a dictionary in nature used to store key value data. ViewBag is simply a wrapper around ViewData. TempData is used to send data across subsequent requests.
namespace System.Web.Mvc

{

    public abstract class ControllerBase : IController

    {

        protected ControllerBase();

        public ControllerContext ControllerContext { get; 
                                                     set; }

        public TempDataDictionary TempData { get; set; }

        public IValueProvider ValueProvider { get; set; }

        public dynamic ViewBag { get; }

        public ViewDataDictionary ViewData { get; set; }

        protected virtual void Execute(RequestContext 
                                        requestContext);

        protected virtual void Initialize(RequestContext 
                                           requestContext);

    }

}



Controller Class

So let's come back to the controller class. The Controller class is also an abstract class which is derived from controller base and implements IController interface. It contains all the useful properties and methods for a controller to work out properly.

We can define our own Controller class from ControllerBase

public class TestController : ControllerBase
{
    protected override void ExecuteCore()
    {
        throw new System.NotImplementedException();
    }

    public ActionResult Index()
    {
        return null;
    }
}


So when we try hit the URL Test/Index, ExecuteCore() is executed first and then Index() is called. Technically, we can implement these but we don't need to. Microsoft has already done all this for us, so we can directly use Controller class.

In theory, we might never need to override any of the default behavior but its always good to know that we have the power to do so. We get a default behavior but we can always change it according to our needs and preferences. 

Each controller has methods which map to specific actions and have a specific return type. In the next post, we will discuss Action Methods and Action Results.

Reference: "Professional ASP.NET MVC 5"

No comments:

Post a Comment