Controllers in ASP.NET Core

Controllers in ASP.NET Core

Controllers are the brain of an ASP.NET Core application. They process incoming requests, perform operations on Model data and selects Views to be rendered to the user. Controllers are stored inside the Controllers folder in the root of the web application. They are basically C# classes whose Public methods are called as Action Methods. These Action Methods handles the HTTP request and prepares the response to be sent to the client.

ASP.NET Core View is a user interface which displays data from the Model to the user (in the browser) and also enables them to modify this data. They resides inside the Views folder located in the root of the application.

This folder can contain a separate folder for each of the controller’s action method. Inside these folders separate views for these actions are placed. For example, the views of HomeController, resides in Views ➤ Home folder. In the same way, views which will be rendered from StudentController will resides in Views ➤ Student folder.

Creating Controllers

Start by creating a new ASP.NET Core Web Application in your Visual Studio. Select the Empty Template, framework as .NET Core and version as ASP.NET Core 3.1.

I have named my application as UnderstandingControllersViews.

Add the following services and configuration inside the Startup.cs as highlighted by the code below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace UnderstandingControllersViews
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Create a Controllers folder in the root of your application by right clicking the project name and selecting Add/New Folder. Rename the folder as Controllers.

create controllers folder

Now right click on the Controllers folder and select Add ➤ Controller. You will see a new dialog window opens up, in this window select the first option – MVC Controller – Empty and click the Add button.

adding a new controller

Give the Controller name as HomeController and click the Add button.

The Controller will be created with the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
 
namespace UnderstandingControllersViews.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Your newly created controller class derives from a Controller base class and has 1 action method by the name of ‘Index’. The Index Action only renders a View to the Client.

You need to create an Index View inside the Views ➤ Home folder. The shortcut method for this is by right clicking the Index text in Visual Studio. Then on the options, which you get, select Add View. The below image explains this:

adding a view

After that you will get Add MVC View dialog box. In this dialog box make sure you do these things:

  • 1. View name: Index
  • 2. Template: Empty (without model)
  • 3. Create a partial view: uncheck
  • 4. Use a Layout Page: uncheck

Finally click the Add button to create this View. See the below image for reference:

add mvc view dialog

The Index View will be created inside the Views ➤ Home folder. The Views and Home folder will be created automatically instead of you creating them manually one-by-one. Check this by openings the Views ➤ Home folder in your application.

The created View will have the HTML code shown below:

@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
</body>
</html>

Add a text message inside the body tag of the view:

<body>
    Welcome from <b>Index View</b> of <b>Home Controller</b>
</body>

The view will need ASP.NET Core Built-in Tag Helpers to create links from routes. Therefore create a view imports file called _ViewImports.cshtml inside the Views folder and add to it the following code shown below:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Run your application and you will see this view is rendered on the browser.

Index view rendered

Adding Bootstrap 4

Bootstrap is an HTML, CSS and JavaScript framework for making modern web design. For the next sections I will need to add it to my application.

I have written an article that explains how to install Bootstrap in ASP.NET Core. You can use LibMan or Bower to install Bootstrap package in Visual Studio. Make sure to install Bootstrap inside the wwwroot ➤ lib folder

Transfer Data from View to Controller

Data from View is transferred to the Controller in the form of Query string, form values and parameters parsed from the URL. These are collectively known by the term called context data.

You can get this Context Data using 3 methods which are:

  • 1. Controller’s request property.
  • 2. Receive the data as a parameter to an action method.
  • 3. Model Binding.

1. Controllers Request Property – Request.Form

The Request property of the Controller class returns an HttpRequest object that describes the request received from the client.

The HttpRequest contains a Form property which returns a dictionary of form data. You can use the ‘Form’ property to get the data transferred from the View.

Let’s create a small example to understand it.

First you need to create a form inside the Index View. So change the Index View of the Home Controller code as given below:

@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/lib/css/bootstrap.css" rel="stylesheet" />
</head>
<body>
    <div class="container">
        <form method="post" asp-action="ReceivedDataByRequest">
            <div class="form-group">
                <label>Name:</label>
                <input class="form-control" name="name" />
            </div>
            <div class="form-group">
                <label>Sex:</label>
                <select class="form-control" name="sex">
                    <option value="M">Male</option>
                    <option value="F">Female</option>
                </select>
            </div>
            <button class="btn btn-primary" type="submit">Submit</button>
        </form>
    </div>
</body>
</html>

I applied the bootstrap.css link on the page head section. So I can now do some good designing of the UI. The css classes like container, form-group, form-control, btn btn-primary are bootstrap classes that are used for the designing of the form.

This form will look like:

index view form

I have created a form tag that contains 2 important controls – name of type input & sex of type select. User will fill or select a value on these controls and click the submit button. The values of these controls will then be transferred to the Controller. Note the names of these 2 controls are name and sex while the ‘labels’ are only for displaying purpose.

See the Form tag which has the asp-action="ReceivedDataByRequest" tag helper. This tag helper creates the action property for the form. So in this case the controller’s action method by the name of ReceivedDataByRequest will be called on the submit button’s click.

Now I have to create ReceivedDataByRequest action method in my Home Controller. This action method will receive the form’s data sent by the View. So add the below code to create this action method:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace UnderstandingControllersViews.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult ReceivedDataByRequest()
        {
            string name = Request.Form["name"];
            string sex = Request.Form["sex"];
            return View("ReceivedDataByRequest", $"{name} sex is {sex}");
        }
    }
}

Look how I am capturing the form’s value in the action method using the Request.Form. It returns the dictionary of form’s data.

So Request.Form["name"] will give me the value of the name input control and Request.Form["sex"] will give the selected value of the select control in the form.

Note that I am returning to another View by the name of ReceivedDataByRequest at the end of the Action method. This is done by another signature of the View method which takes 2 parameters and is shown below:

View("ReceivedDataByRequest", $"{name} sex is {sex}")

The 1st parameter is for the View name to be rendered and 2nd one is for the data in object form that will be transferred to the view.

Now create the ReceivedDataByRequest view inside the Views ➤ Home folder with the code shown below:

@model string
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ReceivedDataByRequest</title>
</head>
<body>
    <h1>@Model</h1>
</body>
</html>

This View accepts the string data so I have defined the model as – @model string. Finally I have shown that data inside the h1 tag like @Model. So whatever the action method passes to this View will be displayed inside the h1 tag.

Now run your application, fill the form and press the submit button. Your submitted values will be displayed on the browser, as shown by the following image:

fetching data from view in controller using request.Form

2. Receive Context Data as a parameter to an action method

Another method to fetch the Context Data sent from View to the Controller is by providing action method’s parameters.

The form has 2 controls that allow users to enter their name and sex. I can declare parameters on the action method whose names correspond to these form controls. This let’s MVC to know that it has to transfer these 2 controls value to these 2 parameters.

So simply add a new action method by the name ReceivedDataByParameter to the Home Controller. The Code for it is given below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace UnderstandingControllersViews.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult ReceivedDataByRequest()
        {
            string name = Request.Form["name"];
            string sex = Request.Form["sex"];
            return View("ReceivedDataByRequest", $"{name} sex is {sex}");
        }

        public IActionResult ReceivedDataByParameter(string name, string sex)
        {
            return View("ReceivedDataByParameter", $"{name} sex is {sex}");
        }
    }
}

See the 2 parameters of the Action method. These have the names same like the 2 control names (‘name’ & ‘sex’).

Also do a small change on the Index View by changing the asp-action="ReceivedDataByRequest" tag helper to asp-action="ReceivedDataByParameter".

The changed code is highlighted below:

<form method="post" asp-action="ReceivedDataByParameter">
    ...
</form>

Next, add a new View inside the Views ➤ Home folder and name it ReceivedDataByParameter. It also receives Model Value of string type and displays the model value in the h1 tag. Check it’s code as shown below:

@model string
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ReceivedDataByParameter</title>
</head>
<body>
    <h1>@Model</h1>
</body>
</html>

Run the application and fill the form. On clicking the submit button you will get to see your form controls values displayed on the browser. Check the below image:

fetching data from view in controller using action method parameters
Note: MVC will also transfer the QueryString values to action method parameters. You can learn all this in my tutorial called – Model Binding in ASP.NET Core

3. Model Binding

In Model Binding you will have to create a Model, which is basically a class kept inside the Models folder. Next you have to map this model class with the form.

Finally in order to receive the values in the Controller, you include this model class type parameter in the Action method’s parameter. Let us see this through an example.

In professional projects you need to harness the extreme power of Model Binding technique. I have covered all this in my separate article – Advanced Model Binding Concepts in ASP.NET Core

So first create a Models folder in your application root directory and add a new class by the name of Person.cs inside it. Include the following code in this class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
 
namespace UnderstandingControllersViews.Models
{
    public class Person
    {
        public string name { get; set; }
        public string sex { get; set; }
    }
}

The class has 2 public properties that MVC will automatically fill with the values from the controls given inside the form tag of the the View.

Next add the ReceivedDataByModelBinding Action in the Home Controller as shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using UnderstandingControllersViews.Models;
 
namespace UnderstandingControllersViews.Controllers
{
    public class HomeController : Controller
    {
        // removed for clarity
         
        public IActionResult ReceivedDataByModelBinding(Person person)
        {
            return View("ReceivedDataByModelBinding", person);
        }
    }
}

This action has a parameter of type Person and therefore MVC applies Model Binding to this Action. On the last line of the code the Person’s object is returning to the ReceivedDataByModelBinding View. So it means this view will accept Model object of type Person.

Before creating the ReceivedDataByModelBinding View, import the Model namespace inside the _ViewImports.cshtml file so that in my Views I can directly access the Person class without having to write its full namespace. The Code for this is highlighted below:

@using UnderstandingControllersViews.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Now create the ReceivedDataByModelBinding View inside the Views ➤ Home folder with the code given below, the View is slightly different that the other Views you built previously. It accepts model of type Person and shows the values of the name and sex properties of the Person class.

@model Person
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ReceivedDataByModelBinding</title>
</head>
<body>
    <h1>@Model.name sex is @Model.sex</h1>
</body>
</html>

Now comes the final part. You need to update the Form inside the Index View so that MVC knows the form is mapping with the Person’s class properties (i.e. name & sex). I have highlighted these changes (see below code).

@model Person
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <link href="~/lib/css/bootstrap.css" rel="stylesheet" />
</head>
<body>
    <div class="container">
        <form method="post" asp-action="ReceivedDataByModelBinding">
            <div class="form-group">
                <label>Name:</label>
                <input class="form-control" asp-for="name" />
            </div>
            <div class="form-group">
                <label>Sex:</label>
                <select class="form-control" asp-for="sex">
                    <option value="M">Male</option>
                    <option value="F">Female</option>
                </select>
            </div>
            <button class="btn btn-primary" type="submit">Submit</button>
        </form>
    </div>
</body>
</html>
The point to note here are:

1. The View accepts the model of type person – @model Person.

2. I have changed the form’s action to ReceivedDataByModelBinding.

3. The Controls (input & select) are now binding with the name and sex property of the Person’s class. The asp-for="class_property" is used to bind the control with a property of the class.

Run the application,fill the form and click the submit button. You will see the Model Binding feature comes into play and the forms data is shown by the ReceivedDataByModelBinding View as described in the image below:

fetching data from view in controller using model binding

You can download the full codes of this tutorial from the below link:

Download

Conclusion

In this tutorial I explained Controllers and their usage in Core Framework. I hope you find it useful. Next tutorial is – Actions in ASP.NET Core, do check it to.

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "ASP.NET Core, jQuery, EF Core, SEO, jQuery, HTML" and more.