Share via


ASP.NET Core: Understanding Controller Suffix in Model View Controller

This article is under construction! please do not edit it yet, till this comment removed


Introduction

In this article we will see why there is a "Controller" suffix in controller class name in MVC. This article is specially focusing on newcomers and anyone new wants to learn how MVC works. This sample illustrates a way to let user to dig deeper into controller name convention in MVC.

What is Controller?

The Controller handles any incoming URL request. Controller classis derived from the base class Microsoft.AspNetCore.Mvc.Controller. Controller class contains public methods called Action methods. Controller and its action method handles incoming browser requests, retrieves necessary model data and returns appropriate responses. Controller class name ends with a word "Controller". For example, controller for home page must be "HomeController" and controller for product must be "ProductController". This convention is only followed to avoid name conflict and to make it easier to identify Controllers.

Understanding Controller

Lets see how controller resides in a prject layout. In the following CoreWeb03 project we have a home controller known as "HomeController.cs" which is in Controller folder and has following Action Methods:

  • Index
  • About
  • Contact
  • Error

Let's see how view resides in the project layout. View is the UI part of a web application. ASP.NET Core MVC Views has a .cshtml extension (for C# ) and by default, these files are stored in Views folder. For our case we will taliking about _Layout.cshtml file. The Visual Studio ASP.NET Core MVC project template includes this layout file in the "Views/Shared: folder:

An example _Layout.cshtml:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication1</title>
 
    <environment names="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment names="Staging,Production">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">WebApplication1</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
                </ul>
                @await Html.PartialAsync("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>© 2016 - WebApplication1</p>
        </footer>
    </div>
 
    <environment names="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    </environment>
    <environment names="Staging,Production">
        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery">
        </script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/bootstrap.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
        </script>
        <script src="~/js/site.min.js" asp-append-version="true"></script>
    </environment>
 
    @RenderSection("scripts", required: false)
</body>
</html>

Highlighted part:

As you can see View is calling the HomeController and methods in that controller (Index, About, Contact). But wait! our controller name is HomeController then why View is calling it as "Home"?

In the following we will try give the answer of this question in details.

Convention of Controller Name

Turns out the convention for controller names resides in, deep inside the roots of the MVC Framework. The following code snippet is part of the ASP.Net Core MVC Framework. Which is in DefaultApplicationModelProvider.cs class under Microsoft.AspNetCore.Mvc.Core library.

var controllerModel = new  ControllerModel(typeInfo, attributes);
 
AddRange(controllerModel.Selectors, CreateSelectors(attributes));
 
controllerModel.ControllerName =
           typeInfo.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) ?
                  typeInfo.Name.Substring(0, typeInfo.Name.Length - "Controller".Length) :
                  typeInfo.Name;

Look into the above code, how MVC framework recognizing a Controller class? It is looking for a class name which ends with Controller and performing a substring operation to get the name of the controller. See now how controller name in View "Home" matched with the controller name HomeController in Controller folder.