Click here to Skip to main content
15,881,764 members
Articles / Web Development / ASP.NET

Learn ASP.Net in MVC Style: Part 2 - Controller in ASP.Net MVC 5

Rate me:
Please Sign up or sign in to vote.
4.77/5 (25 votes)
3 Jan 2015CPOL13 min read 32.2K   31   15
A detailed description about controllers in ASP.NET MVC 5.

Table of Contents

This article will cover the following topics:

Roadmap

This is the second article of the series “Learn ASP.NET in MVC Style” and discusses controllers in ASP.NET MVC5. The following is the roadmap of the series so far:

Introduction

In my first article, I gave you an overview of the ASP.NET MVC5 framework and described it as Microsoft's implementation of the Model-View-Controller (MVC) pattern. The MVC pattern is an architectural pattern that divides the application into three interconnected parts based on the 'Separation of Concerns' principle . These three parts are called Model, View and Controller. This article focus on the Controller part of the pattern and provides you a detailed description of the role and importance of controllers in ASP.NET MVC5.

Getting Started

A controller is the most important part of the ASP.NET MVC5 framework and is responsible for the overall flow of a web application. If we look at the Request/Response pattern of an ASP.NET MVC application, it works slightly different from the traditional Web Forms applications where the requests are mapped directly to the (.aspx) files placed on the web server. 

To simplify it, consider a web application named "Developer Cafe" that has been developed using ASP.NET Web Forms and is deployed over the web server. If a user wants to access the Contact Page of the application, he should type the URL as [www.developercafe.com/contact.aspx]. The <a target="null">'contact.aspx'</a> refers to the web page placed at the root directory of the web server and contains the contact information about the application. This is the traditional approach used for web applications developed using ASP.NET Web Forms. 

If we develop the same application using the ASP.NET MVC5 framework, its Request/Response pattern is completely different. Instead of targeting files placed on the root directory of the web server, it maps the URLs to special classes referred to as Controllers. These classes contain the targeting methods termed "Action Methods" or simply "Actions" that are responsible for processing the incoming requests. So, if the same user has to access the contact information of the "Developer Cafe" application developed in ASP.NET MVC5, he should type something like this: [www.developercafe.com/Contact/Index]

Here, 'Contact' refers to the controller class that processes the user requests and 'Index' refers to the action method present inside the controller class that contains the contact information about the application.This mapping of URL requests to controller classes is done using the Routing Mechanism of the ASP.NET MVC5 Framework. The major benefit of this URL approach is better Search Engine Optimization (SEO). I'll not discuss the routing mechanism in this article, instead focus on the anatomy of a controller class. 

Controller in ASP.NET MVC5

Controller

A controller is a special class that inherits from an abstract ControllerBase class and is responsible for the overall flow of an ASP.NET MVC application. Every request that comes to an ASP.NET MVC5 application is handled by the controller. It handles the HTTP requests, retrieves and stores the data, returns the appropriate responses and executes the application logic.

The ASP.NET MVC5 framework follows the 'Convention over Configuration' principle, so all the controller classes should be suffixed with the word "Controller" and placed inside the Controllers folder of the application.

Action Methods

A controller provides public methods that respond to the incoming HTTP requests made to an ASP.NET MVC application. These methods are known as Action Methods and generally return the ActionResult objects. ActionResult is an abstract class and these action methods can return various types of objects to incoming requests that all inherit from the ActionResult class. The results could be a simple file to download, a plain text, JSON to process or an HTML page depending upon the request of the user. 

Action Results

The various types of action results that can be returned from an action method are described in the following table. 

Image 1

How to Create a Controller

Step 1: In order to dig deep into controllers, let's create an empty ASP.NET MVC5 application. Open Visual Studio and create a new project by going to File => New => Project 

A dialog window appears that asks for the type of the project. Click 'Web' on the left side of the dialog window for ASP.NET Web Application. Give it a suitable name and Click OK. 

Image 2

Step 2: A new dialog window asks you to select the template for your web application. Since we are creating a web application using the ASP.NET MVC framework and must learn everything from scratch, choose the Empty template. Also, for the basic essential files for our application, check the MVC checkbox and click OK.

Image 3

Step 3: The Visual Studio creates a project for us with minimal layout having directories like Models, Views and Controllers along with Web.config and Global.asax files. 

One of the interesting things to be noticed here is the App_Start folder that was also created having a RouteConfig.cs file in it. This file contains the routing configuration of the entire application. It defines the classes and methods to start looking for, when the incoming requests came to the server. I'll explain in complete detail about the routing mechanism of an ASP.NET MVC application in future articles in the series. The only thing to remember right now is that the file contains routing configuration needed by the application to execute the Request/Response pattern.

Image 4

Step 4: The ASP.NET MVC5 framework works heavily on the 'Convention over Configuration' principle. By default, every controller class should be suffixed with the Controller keyword and placed inside the Controllers folder of the ASP.NET MVC application. We'll follow the same principle in this article. 

To create a Controller, right-click on the the Controllers Folder and select Add and then Controller.

Image 5

Step 5: A dialog window appears with several options to choose from. Select the 'MVC 5 Controller - Empty' option and click Add.

Image 6

Step 6: Since I already told you about the 'Convention over Configuration' principle, it gives you a dialog window to name your controller. You should note that the Controller keyword should be suffixed with the name.

Image 7

Initially, I told you about the RouteConfig.cs file. This class is used by the ASP.NET MVC framework to route incoming user requests to controllers. It has a default route configuration that is followed by the ASP.NET MVC application. If we open the RouteConfig.cs file, you'll notice a static method RegisterRoutes() that contains the routing information.

public class RouteConfig   
{   
  public static void RegisterRoutes(RouteCollection routes)  
  {   
       routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  

       routes.MapRoute(   
           name: "Default",   
           url: "{controller}/{action}/{id}", 
           defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
        );   
    }   
} 

It contains the two properties routes.IgnoreRoute and routes.MapRoute. If this scares you, don't worry. You don't need to understand this right now. For now, just remember that the routes.MapRoute property contains the routing information of the application. 

The three parameters of routes.MapRoute are described as follows.

  1. name: It describes the name of the Route
  2. url: It describes the syntax of the requested URL that user should type in the browser.
  3. defaults: It contains the default configurations for the incoming URLs. The defaults are: 

    controller = "Home", 
    action = "Index", 
    id = UrlParameter.Optional 
    }

It means that the default controller to be mapped for all incoming requests is Home, the default action method to be targeted inside the controller class should be Index and the parameter is optional to be passed with the URL. 

After looking at the default routing configuration for an ASP.NET MVC application, we should name our controller as HomeController. However, this is only the default configuration and can be changed depending upon the requirements of your application. But for the sake of simplicity, we will stick with the defaults and type the name as Home suffixed with the Controller keyword and click Add. 

Image 8

Step 7: Voila, the HomeController is created inside the Controllers folder. An interesting point to be noted is that a folder with the same name of controller is created inside the Views folder. This is because the Controller is responsible for responding to incoming requests and generally the user wants HTML pages to be rendered down to the browser. To respond with HTML pages to the user, we make use of views. 

A View is nothing but an HTML file returned to the user as a response and by the 'Convention over Configuration' principle, for every controller, a View folder should be created with the same name in the Views folder.

Image 9

Step 8: Open the HomeController.cs file and get ready to work with it: 

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

namespace ControllerDemo.Controllers   
{   
    public class HomeController : Controller   
    {   
        // GET: Home   
        public ActionResult Index()   
        {   
            return View();   
        }   
    }  
}  

Working with Controller

Until now, we have learned what a controller is and how to create one. Let's look inside the controller class and play with the methods provided by the controller that responds to the incoming requests. 

public class HomeController : Controller  
{    
    public ActionResult Index()   
    {    
        return View();   
    }    
} 

When we create a controller class, it inherits the System.Web.Mvc.Controller class and gives us a public method named 'Index'. I mentioned the word 'public' because in C#, by default all the methods in a class are private. So, if we have to manually create a method inside a controller to be treated as an action method, we should declare it as public. 

Types of Action Results

The public methods inside a controller class are termed Action Methods. By default, these methods return the ActionResult objects to incoming requests of the user. The ActionResult is an abstract class and the instance of this class represents the result of an action method in response to a user request. There are several types of results an action method can return. The following describes some of the common results:

1. ViewResult: This is the most common and default result returned to the user. It renders a web page to the user from the Views folder. If we look at the HomeController class, it calls the helper method View() that looks for the associated 'Index' view to be rendered on the browser. 

public class HomeController : Controller 
{  
      public ActionResult Index()  
       {  
          return View();  
       }
}

If we execute the code, it shows the following output

Image 10

This error occurs because we didn't create any view with the name Index to be rendered on the browser, but you get the idea about the ViewResult class that is used to return the View to the user.

2. ContentResult: It is used to return a user-defined content type (text, xml). We can return a simple string to the user using the Content() method. Consider the following code:

public class HomeController : Controller  
{    
       public ActionResult Index()  
      {  
           return Content("This method returns plain text.");  
     }    
   } 

If we execute the code, it shows the following output.

Image 11

3. JsonResult: We can use this class to return a JavaScript Object Notation (JSON) object to the user. We need to use the Json() helper method to return JSON. Consider the following code:

public class HomeController : Controller
{   
       public ActionResult Index()
       {        
          var employee = new    
         {   
            Name = "Sahil Sharma",  
            Age = "25",   
            Occupation = "Software Developer"
         };   
 
         return Json(employee,JsonRequestBehavior.AllowGet);
       }  
  } 

Here, we need to provide an extra parameter 'JsonRequestBehaviour.AllowGet' with the Json() method to allow it to work on the GET requests.

Image 12

4. FileResult: We can also provide a facility to the user to request a file to download from the application. To do this, we need to return the FileResult object using the File() method. Consider the following code: 

public class HomeController : Controller
{   
       public ActionResult Index()
       {   
           return File(Server.MapPath("~/App_Data/documentation.pdf"),
                       contentType: "application/pdf", 
                       fileDownloadName: "documentation.pdf");    
      }   
} 

If we run the following code, it gives us an option for a PDF file to be downloaded to our local system.

Image 13
 

5. RedirectToAction: This class is used to redirect to another action method of the controller class. Consider the following code: 

public class HomeController : Controller
{  
    public ActionResult Index()  
   {   
        return RedirectToAction("Contact");  
   }
    
    public ActionResult Contact()  
   {   
        return Content("This is the redirected Contact method.");  
   }   
 } 

Here, I'm using the Contact() action method as the redirected method to be displayed whenever a request comes to Index() method. 

Image 14

The Useful Attributes

There are several attributes that can be applied to action methods of a controller for various tweaks. These are termed Action Selectors. As the MSDN says, "An action selector represents an attribute that is used to influence the selection of an action method". The following describes some of the commonly used selectors.

1. ActionName: This attribute allows us to specify a different name to an action method irrespective of its original name. Consider the following code: 

public class HomeController : Controller
{  
    [ActionName("Contact")]
    public ActionResult Index()  
   {   
        return Content("This method is originally named Index");  
   }     
 } 

If we execute the following code and look for the Index action method, it gives us a HTTP 404 error. 

Image 15

This is because the name of the method is now changed to Contact and we should look for the Contact method of the Home controller.

Image 16

2. NonAction: Suppose we want a method of the controller class to be treated as a normal method instead of an action method. How can we do that? We learned in the beginning of the article that only public methods are treated as action methods. So, we can simply convert an action method into a normal method by declaring it as private or protected. 

But there may be other situations. What if there is a requirement that demands the public methods of a controller class not to be treat as action methods. Can we do that as well? The answer is Yes, we can. There is an attribute called NonAction that indicates the public method should not be treated as an action method. Consider the following code: 

public class HomeController : Controller
{  
    [NonAction]
    public ActionResult Index()  
   {   
        return View();  
   }     
 } 

If we execute the following code, we'll get a HTTP 404 error because the Index method is no longer an action method and cannot be invoked. 

Image 17

3. HttpGet: This attribute is used to restrict an action method to respond only to the HTTP GET requests. It is also the default request attribute for action methods. Consider the following code: 

public class HomeController : Controller
{  
    [HttpGet]
    public ActionResult Index()  
   {   
        return View();  
   }     
 } 

If we specify an HttpGet attribute to an action method, it works only for the GET requests and otherwise returns an HTTP 404 error. 

4. HttpPost: This attribute is similar to the HttpGet attribute with the only difference that instead of responding to GET requets, it responds to POST requests. Consider the following code: 

public class HomeController : Controller
{  
    [HttpPost]
    public ActionResult Index()  
   {   
        return View();  
   }     
 } 

A Trivial Question About Action Methods?

There is an interesting question asked about Action Methods in the MVC interviews. We learn in this article that the Controller is a class and a class can have multiple methods. According to the OOP principles, a class can have two methods with the same name. This principle is known as Function Overloading that is an example of Static or Compile Time Polymorphism

If we follow the same principle here, it concludes that we can have two action methods with the same name inside a controller. Let's have a look at the following code:

public class HomeController : Controller
{ 
    //First Index Method
    public ActionResult Index() 
   {  
        return Content("This is the first Index action"); 
   } 

    //Second Index Method
    public ActionResult Index(string something) 
   {  
        return Content("This is the second Index action"); 
   }
}

If we execute the code, it gives us the following:

Image 18

Whoa, it throws a System.Reflection.AmbiguousMatchException instead of executing the code. The error says, "The current request for action "Index" on controller type "HomeController" is ambiguous". 

So, how can we fix this error? There are two options by which we can fix this situation and work with two action methods having the same name and not getting an exception. 

1. Using the ActionName attribute: In order to have two action methods with the same name inside a controller, we'll use the ActionName attribute. Consider the following code: 

public class HomeController : Controller
{ 
    //First Index Method
    public ActionResult Index() 
   {  
        return Content("This is the first Index action"); 
   } 

    //Second Index Method
    [ActionName("IndexNew")]
    public ActionResult Index(string something) 
   {  
        return Content("This is the second Index action"); 
   }
} 

Here, I'm giving the second action method an alternate name IndexNew to distinguish it from the first one. In this way, we can have two action methods with the same name inside a controller. 

Image 19

Image 20

2. Using the HTTP request attributes: This approach makes use of HttpGet and HttpPost attributes to have two action methods with the same name inside a controller. Consider the following code: 

public class HomeController : Controller
{ 
    //First Index Method
    [HttpGet]
    public ActionResult Index() 
   {  
        return Content("This is the first Index action called using GET request."); 
   } 

    //Second Index Method
    [HttpPost]
    public ActionResult Index(string something) 
   {  
        return Content("This is the second Index action called using POST method."); 
   }
} 

If we execute the following code, we won't get any error and the code works properly. When a GET request is received by the application, it is automatically handled by the first method and for a POST request, the second method is invoked automatically. 

Points of Interest

In this article, we learned about controllers, their role and how they work in an ASP.NET MVC application. In the next articles of this series, we'll dig deep into the world of ASP.NET MVC5. Your feedback and constructive criticism is always appreciated, keep it coming. Until then, try to put a ding in the Universe.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
I write code for a living; sometime blogs about it.

Comments and Discussions

 
Questionhow to dynamically select single field data from data table on id parameter in asp.net mvc with entity framework 2017 Pin
yogesh vaidya11-Dec-18 7:20
yogesh vaidya11-Dec-18 7:20 
PraiseNeed more articles like this Pin
Member 134859037-Nov-17 15:34
Member 134859037-Nov-17 15:34 
QuestionNeed more articles like this. Pin
Hanumantha reddy GS15-Apr-15 8:37
Hanumantha reddy GS15-Apr-15 8:37 
AnswerRe: Need more articles like this. Pin
iSahilSharma17-Apr-15 5:13
iSahilSharma17-Apr-15 5:13 
GeneralMy vote of 5 Pin
Sandesh M Patil19-Feb-15 1:49
Sandesh M Patil19-Feb-15 1:49 
GeneralGood intro article Pin
smoore45-Jan-15 23:17
smoore45-Jan-15 23:17 
GeneralRe: Good intro article Pin
iSahilSharma6-Jan-15 19:00
iSahilSharma6-Jan-15 19:00 
GeneralMy vote of 1 Pin
Member 10745685-Jan-15 15:58
Member 10745685-Jan-15 15:58 
QuestionIncorrect code sample Pin
Aleksandr Roussu5-Jan-15 3:58
Aleksandr Roussu5-Jan-15 3:58 
AnswerRe: Incorrect code sample Pin
iSahilSharma5-Jan-15 18:29
iSahilSharma5-Jan-15 18:29 
QuestionThanks for Your Great articles Pin
Member 37462923-Jan-15 2:31
Member 37462923-Jan-15 2:31 
AnswerRe: Thanks for Your Great articles Pin
iSahilSharma4-Jan-15 19:04
iSahilSharma4-Jan-15 19:04 
GeneralRe: Thanks for Your Great articles Pin
Member 37462924-Jan-15 20:16
Member 37462924-Jan-15 20:16 
Generalvery nice Pin
saxenaabhi63-Jan-15 1:59
saxenaabhi63-Jan-15 1:59 
GeneralRe: very nice Pin
iSahilSharma4-Jan-15 18:54
iSahilSharma4-Jan-15 18:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.