Controllers

.

Controllers

"A controller is the link between a user and the system. It provides the user with input by arranging for relevant views to present themselves in appropriate places on the screen. It provides means for user output by presenting the user with menus or other means of giving commands and data. The controller receives such user output, translates it into the appropriate messages and pass these messages on to one or more of the views."Trygve Reenskaug, Dec. 1979


Web page by Kevin Harris of Homer IL

Please contact Kevin Harris of Homer IL concerning this web site

Controllers are the center of activity in ASP.NET MVC. The code inside the controller is used to process the HTTP request initiated by the user, obtain needed data from the model, and pass it to the selected view for display. The routing engine in MVC is the component which accepts a request URL and directs it to the proper logic inside the controller. See the Routing Article for more information about routing in MVC.

Controllers are classes which implement the IController interface. The IController interface is the lowest level abstraction which only implements an execute method. Richer abstractions include a ControllerBase class which includes properties for passing data to a view. Derived from the ControllerBase class is the Controller class which contains actions. It is from the Controllers class that custom controllers are typically derived.

Controllers have a naming conventions which requires the string "Controller" to be appended to the controller name. For example the Account controller, which controls authentication/authorization, must be named "AccountController.cs". However controllers have no location convention which must be followed, they can be located anywhere in the project, or even in a different assembly.

Typical controller activities consist of:

  1. The routing system directs a request to an action method inside the controller.

  2. For GET requests, the action method obtains data and sends it to the view for display.

  3. For POST requests, the action method checks with the model to determine if the data enter is valid. If validation fails, the view is returned with the entered data and validation messages. If the data passes validation, the data is written to a database.

Controller Actions

Controllers must implement the IController interface. The ControllerBase class implements the interface and contains properties for passing data. The Controller class is derived from the ControllerBase class and provides for the implementation of actions for executing logic. Custom controllers are typically derived from the Controller class.

  1. IController - an interface which requires an "Execute" method and writes to the response stream.

  2. ControllerBase - a class which implements IController. It includes properties for passing data (ViewData) and a context which support the processing thread ( ControllerContext).

  3. Controller - a class derived from ControllerBase. It includes actions for executing custom logic.

  4. MyController - a user created controller which is derived from Controller. Contains the custom processing logic.

Actions are the ultimate destination for a request. Routing directs the request to a particular method inside a controller to perform an action. The methods which perform the action are called Action Methods. Action Methods must be public and non-static. Action methods default to processing a GET request. To have a method process a POST request, a [HttpPost] attribute is used to decorate the action method. GET requests pass data in query string parameters, while POST requests pass data in the form body. Other attributes, known as Action Filters, also allow additional processes to be executed before or after the action method. See the Action Filters for more information. Note: GET operations should not modify any data on the server, because GET requests can be cached.

MVC employees a mechanism known as a Model Binder to mapping request data to action methods. The Model Binder is a convenience that alleviates the developer from having to dig through the Request.Form values to manually map the data in the action method. Model Binders will look through the form fields and query strings for data to map as parameters. The default model binder in MVC works well in most cases, but there are times when a custom model binder must be created. An example of where a custom model binder is required is when a data type conversion is required between the data store and the displayed data. Custom model binders implement the IModelBinder interface and are registered in the Application_Start method in the Global.asax.cs file.

An action method can return any type of value, however it typically returns an action result which is a type derived from the abstract ActionResult class. The action result relates to the action being performed. The Controller class contains Helper Methods which help return action results. For example, a common action is to call a View method, in which case an instance of the ViewResult action result would be returned through the use of the View helper method.

1
2
3
4
public ActionResult Index()
{
    return View();
}


Action Method Returing a ViewResult


The following table lists the built-in action result types along with their helper methods.

Action Result Helper Method Description
ViewResult View Renders a specifed view to the response stream.
PartialViewResult PartialView Renders a specifed partial view to the response stream.
RedirectResult Redirect Performs an HTTP redirection to a specifed URL.
RedirectToRouteResult RedirectToAction or RedirectToRoute Redirects to another action method.
ContentResult Content Returns a user-defined content type.
JsonResult Json Returns a serialized JSON object.
JavaScriptResult JavaScript Returns a script that can be executed on the client.
HttpStatusCodeResult (None) Returns a specific HTTP response code and description.
HttpUnauthorizedResult (None) Returns the result of an unauthorized HTTP request.
HttpNotFoundResult HttpNotFound Indicates the requested resource was not found.
FileResult File Returns binary output to write to the response.
FileContentResult Controller.File(Byte[], String) or
Controller.File(Byte[], String, String)
Sends the contents of a binary file to the response.
FilePathResult Controller.File(String, String) or
Controller.File(String, String, String)
Sends the contents of a file to the response.
FileStreamResult Controller.File(Stream, String) or
Controller.File(Stream, String, String)
Sends binary content to the response through a stream.
EmptyResult (None) Returns a null result (empty response).


The following graphic shows how to obtain the name of the destination controller and action method from the route data.

.Controller and Action Shown in Immediate Window


Controller and Action Shown in Immediate Window

Below is the code for a controller which contains action methods for handling the CRUD operations of a database table contain bill information

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using System.Linq;
using System.Web.Mvc;
using CathySite.Web.ViewModels;
using CathySite.DAL.Models;
using CathySite.Web.Models;

namespace CathySite.Web.Controllers
{
    public class BillController : Controller
    {
        // GET: Bill
        public ActionResult Index()
        {
            BillIndexViewModel viewModel = new BillIndexViewModel().Load();
            return View(viewModel);
        }

        // POST: Bill/Create
        public ActionResult Create()
        {
            return View("Create");
        }

        // POST: Bill/Save
        public ActionResult Save(Bill B, string btnSubmit)
        {
            switch (btnSubmit)
            {
                case "Save":
                    if (ModelState.IsValid)
                    {
                        using (var db = new CathySiteEntities())
                        {
                            bill theBill = new bill();
                            theBill.ID = B.ID;
                            theBill.Payee = B.Payee;
                            theBill.Amount = B.Amount;
                            theBill.PeriodID = B.PeriodID;
                            theBill.Date = B.Date;
                            theBill.Balance = B.Balance;
                            db.bills.Add(theBill);
                            db.SaveChanges();
                        }

                        return RedirectToAction("Index");
                    }
                    else
                    {
                        return View("Create");
                    }
                case "Cancel":
                    return RedirectToAction("Index");
            }
            return new EmptyResult();
        }

        //Get: Bill/ShowPrevPayment
        public ActionResult ShowPrevPayment(Bill B)
        {
            return Content("Previous Payment: xxxx");
        }


        // GET: Display
        public ActionResult Display(int ID)
        {
            BillViewModel vmBillViewModel = new BillViewModel();

            using (var context = new CathySiteEntities())
            {
                bill theBill = context.bills
                    .Where(x => x.ID == ID)
                    .FirstOrDefault();

                if (theBill != null)
                {
                    vmBillViewModel.ID = theBill.ID;
                    vmBillViewModel.Amount = theBill.Amount;
                    vmBillViewModel.Balance = theBill.Balance;
                    vmBillViewModel.Date = theBill.Date;
                    vmBillViewModel.Payee = theBill.Payee;
                    vmBillViewModel.Period = theBill.period.Name;
                }
            }

            return View(vmBillViewModel);
        }
    }
}


BillController.cs

Asynchronous Controllers

Asynchronous controllers were releases in MVC 2 for actions with latency, such as network or I/O operations. Async controllers add complexity to the code, so the process should be evaluated to ensure there will be a benefit before coding controllers which are async. Async controllers are derived from AsyncController which has two methods (ActionAsync and ActionCompleted).


Custom Controller Factories

The routing system forwards a request to a controller factory. The controller factory is responsible for searching and creating controllers. MVC has a default controller factory called DefaultControllerFactory which is sufficient in most cases. However there are situations, such as when using dependency injection, that a custom controller factory is required. The following code is a shell for a custom controller factory.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 :Insert IoC logic here
      return null;
    }
    public void ReleaseController(IController controller)
    {
      var disposable = controller as IDisposable;
      if (disposable != null)
      {
        disposable.Dispose();
      }
    }
  }
}


Custom Controller Factory