Back to: ASP.NET Core Tutorials For Beginners and Professionals
Controllers in ASP.NET Core MVC Application
In this article, I am going to discuss the Controllers in ASP.NET Core MVC Applications with Examples. Please read our previous article before proceeding to this article, where we discussed Models in ASP.NET Core MVC Applications with Examples. Controllers are the brain of an ASP.NET Core MVC Application. They process incoming HTTP requests, perform operations on data provided through Models, and select Views to render on the browser. As part of this article, we are going to discuss the following pointers.
- What is a Controller?
- Role of Controller
- How to add Controller in ASP.NET Core Application?
- What are Action Methods?
- How to call the Action method of a Controller?
- How to Pass Parameters in Action Methods?
- When should we create a new controller?
- How many controllers can we have in a single application?
- How Controller Instance Created in ASP.NET Core MVC Application?
What is a Controller in ASP.NET Core?
A Controller is a special class in ASP.NET Core Application with .cs (for C# language) extension. By default, when you create a new ASP.NET Core Application using Model View Controller (MVC) Project Template, you can see the Controllers reside in the Controllers folder. In ASP.NET Core MVC Application, the controller class should and must be inherited from the Controller base class.
Controllers in MVC Design Pattern are the components that handle user interaction, work with the model, and ultimately select a view to render. In an MVC application, the one and only responsibility of a view is to render the information; the controller handles and responds to user input and interaction. In the MVC Design Pattern, the controller is the initial entry point and is responsible for selecting which model types to work with and which view to render (hence its name – it controls how the app responds to a given request).
The Controllers in the ASP.NET Core MVC Application logically group similar types of actions together. This aggregation of actions or grouping of similar types of action together allows us to define sets of rules, such as caching, routing, and authorization, which will be applied collectively.
When the client (browser) sends a request to the server, then that request first goes through the request processing pipeline. Once the request passes the request processing pipeline, it will hit the controller. Inside the controller, there are lots of methods (called action methods) that actually handle the incoming HTTP Requests. The action method inside the controller executes the business logic and prepares the response, which is sent back to the client who initially made the request. For a better understanding, please have a look at the following diagram.
Role of Controller in MVC:
- A Controller is used to group actions, i.e., Action Methods.
- The Controller is responsible for handling the incoming HTTP Request.
- The Mapping of the HTTP Request to the Controller Action method is done using Routing. That is, for a given HTTP Request, which action method of which controller is going to be invoked is decided by the Routing Engine.
- Many important features, such as Caching, Routing, Security, etc., can be applied to the controller.
How to add Controllers in ASP.NET Core Application?
If you create the ASP.NET Core Application using the MVC Project Template, then by default, it will create a controller called HomeController within the Controllers folder. But if you create the ASP.NET Core Application with the Empty Project template, then by default, you will not find the Controllers folder in your project. As we discuss everything from scratch, we will create the ASP.NET Web Core Application with Empty Template and manually add the Controllers folder and the Controllers.
Step 1: Creating ASP.NET Core Empty Web Application
To create a new Empty ASP.NET Core Web Application, open Visual Studio 2022 and click on the Create a new project tab, as shown in the image below.
Once you click on the Create a new project tab, it will open the Create a new project window. You need to select the ASP.NET Core Empty project template from this window and click the Next button, as shown in the image below.
Once you click on the Next button, it will open the Configure Your New Project window. Here, you need to provide the necessary information to create a new project. First, give an appropriate name for your project (FirstCoreMVCWebApplication), set the location where you want to create this project, and the solution name for the ASP.NET Core Web application. And finally, click on the Create button, as shown in the image below.
Once you click on the Next button, it will open the Additional Information window. Here, you need to select .NET 6.0 as the Framework; you also need to check the Configure for HTTPS and Do not use top-level statements check boxes, and finally, click on the Create button as shown in the below image.
That’s it. Once you click on the Create Button, the project is going to be created with the Empty template with the following folder and file structure.
Step 2: Adding Controllers Folder
Once you create the ASP.NET Core Empty Project, next we need to add the Controllers folder where we will create our Controllers. To do so, right-click on the project and then select the add => new folder option from the context menu, which will add a new folder to your project. Just rename the folder as Controllers.
Step 3: Adding Controller in ASP.NET Core
Once you create the Controllers folder, next, we need to add a controller (StudentController) inside this Controllers folder. To do so, right-click on the Controller folder and select the Add => Controller option from the context menu, which will open the Add Controller window, as shown in the below image. Here, we are going to create the MVC Controller with the Empty template. So, select the MVC Controller – Empty option and click the Add button, as shown in the image below.
As you can see in the above image, we have three templates to create an MVC controller. So you can use any of the following three templates:
- MVC Controller – Empty: It will create an Empty Controller.
- MVC Controller with read/write actions: This template will create the controller with five action methods to create, read, update, delete, and list entities.
- MVC Controller with views, using Entity Framework: This template will create an MVC Controller with actions and Razor views to create, read, update, delete, and list entities using Entity Framework.
Once you click on the Add button, it will open the below window where you need to select the Controller Class – Empty option and give a meaningful name to your controller. Here, I give the StudentController name and click on the Add button. Here, you need to remember that the Controller names should be suffixed with the word Controller.
Once you click on the Add button, it will add StudentController within the Controllers folder, as shown in the image below.
Understanding StudentController:
Now let us understand the StudentController class and the different components of this class. First of all, it is a class having a .cs extension. Open the StudnetController.cs class, and you should get the following default code in it.
As you can see in the above image, the StudentController class is inherited from the Controller base class, and this controller base class is present in Microsoft.AspNetCore.Mvc namespace, and that’s why it imports that Microsoft.AspNetCore.Mvc namespace. Now right-click on the Controller and select Go to the definition, and you will see the following definition of the Controller class.
As you can see in the above image, the Controller is an abstract class having many methods (Json, View, PartialView, OnActionExecuting, etc.) and properties (TempData, ViewBag, ViewData, etc.), and the point that you need to remember is these methods and properties are going to be used when we are working with ASP.NET Core MVC Application. Again, if you look, this Controller class is inherited from the ControllerBase class.
Let us see the ControllerBase class definition as well. Right-click on the ControllerBase class and select Go to definition, and you will see the following definition. Here, you will see the RequestData, Response, Request, ModelState, Routing, Model Binder, HttpContext, and many more properties and methods, which we will use as part of our ASP.NET Core MVC Application.
Now I hope you got clarity on ASP.NET Core MVC Controllers. Let us move forward and understand the next topic, which is Action Methods.
What are Action Methods?
All the public methods of a controller class are known as Action Methods. Because they are created for a specific action or operation in the application. A controller class can have many related action methods. For example, adding a Student is an action. Modifying the student data is another action. Deleting a student is another action. So, you need to remember that all the related actions should be created inside a particular controller.
An action method can return several types. Let us modify the HomeController as shown below, where one method returns all the student details. Intentionally we returned a string from this method, but as we progress in this course, we will discuss the real implementation of this method. But for now, we have to return a string just for learning purposes.
using Microsoft.AspNetCore.Mvc; namespace FirstCoreMVCWebApplication.Controllers { public class StudentController : Controller { public string GetAllStudents() { return "Return All Students"; } } }
How to Call an Action Method of a Controller?
When we get an HTTP Request, it is the controller action method gets that call. So, whenever we say we are hitting a controller, it means we are hitting an action method of a controller.
The default structure is: http:domain.com/ControllerName/ActionMethodName
As we are working with the development environment using visual studio, the domain name is going to be our local host with some available port numbers. So, if we want to access the GetAllStudents action method of the HomeController, then the URL is something like below.
http://localhost:<portnumber>/student/GetAllStudents
Let us prove this. At this moment, if you run the application and navigate to the above URL, then you will not get the output. This is because we have created this project using the ASP.NET Core Empty Project template. And the Empty Project template, by default, will not add the required MVC Service as well as it will not set the required MVC middleware to the application processing pipeline. So, let us set these two.
Modifying the Program Class:
Open the Program.cs class file and then copy and paste the code below into it, adding the required MVC service to the dependency injection and the MVC middleware to the request processing pipeline.
namespace FirstCoreMVCWebApplication { public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add Framework MVC Services to the container. builder.Services.AddMvc(); var app = builder.Build(); //Adding MVC Middleware app.UseRouting(); app.UseEndpoints(endpoints => { //Configuring the MVC middleware to the request processing pipeline endpoints.MapDefaultControllerRoute(); }); app.Run(); } } }
With the above change in place, now run the application and navigate to the URL http://localhost:<portnumber>/student/GetAllStudents, and you should get the output as expected, as shown in the below image.
For a better understanding of how the above URL mapped to the GetAllStudents action method of the controller, please have a look at the following image.
How to Pass Parameters in Action Methods?
Let us understand this with an example. Now we want to search for students based on their names. To do so, add the following action method inside the Student Controller.
public string GetStudentsByName(string name) { return $"Return All Students with Name : {name}"; }
Now run the application, navigate to the URL http://localhost:<portnumber>/student/GetStudentsByName?name=james, and see the output.
The query string parameter name is mapped with the GetStudentsByName action method name parameter in this case. Our upcoming articles will discuss parameter mapping, default mapping, and many more.
When should we create a new controller?
Whenever we need to define a new group of actions or operations in our applications, then we need to create a new controller. For example, to do operations of students, we can create Student Controller. To manage the security of your application, like login, logout, etc., you can create a Security Controller.
How Many Controllers can we have in a Single Application?
It depends on the application. At least one controller is required to perform operations. Maximum n number of Controllers we can have into one application.
Note: The Controller is the component in an MVC application that is used to handle the incoming HTTP Request. Based on the user action, the respective controller will work with the model, select a view to render the information, and then send the response back to the user who initially made the request. So, Controller is the component that will interact with both the models and views to control the flow of application execution.
How is Controller Instance Created in ASP.NET Core MVC?
We have discussed How to Create and use Controllers in ASP.NET Core MVC Applications. And we also understand that it is the Controller Action Method that is going to handle the incoming HTTP Request. But, if you look at the controller, then you will see that it is a class inherited from the Controller Base class, and this class has some method called Action Method.
We also know that if we want to invoke a method (non-static), then we need an instance of that class. Now, the question is, who and how created the Controller class instance, and how the action method is called using that instance? Let us proceed and understand this with an example.
How is Controller Instance Created in ASP.NET Core MVC?
In order to create ASP.NET Core MVC Application, we need to add the required MVC Services and Middleware into the Request Processing Pipeline. For example, you can add the MVC services using the following statement within your Main method of the Program.cs class file in .NET 6 Application. So, you can use either AddMvc or AddControllersWithViews method to add MVC services.
Then we need to configure the MVC Middleware into the Request Processing Pipeline either using conventional or attribute routing. For example, the following code will add the MVC Middleware Component to the Application Processing Pipeline.
So, in ASP.NET Core MVC Web Application, the MVC Middleware Component will receive the request when the client sends an HTTP Request. Once the MVC Middleware receives the request, based either on the conventional or attribute routing, it will select the controller and action method to execute.
But, in order to execute the action method, the MVC Middleware must create an instance of the selected controller. And it makes sense, as we know if we want to invoke a non-static method, then we need an instance of the class. And this is not different in the case of a controller action method. So, to execute an action method, we need an instance of the controller class.
In order to create an instance of the Controller class, the MVC Middleware uses the concept called reflection, and it will use the following IControllerActivator class. As you can see, this interface provides three methods. This IControllerActivator interface provides methods to create and release a controller.
The meaning of each method is as follows:
- object Create(ControllerContext context): This method is used to Create a controller. Here, the parameter context is used for executing the action method.
- void Release(ControllerContext context, object controller): This method is used to Release a controller. Here, the parameter context is used for executing the action method. And the parameter controller specifies the controller to release.
- ValueTask ReleaseAsync(ControllerContext context, object controller): This is the same as the Release method, but it Releases a controller asynchronously.
Now, the above interface is implemented by a class called DefaultControllerActivator, which will implement the IControllerActivator interface methods and provides the logic to create and release the controller. If you go to the definition of DefaultControllerActivator class, then you will see the following.
As you can see, this class provides implementations for the IControllerActivator interface methods. Further, if you notice, the ASP.NET Core Framework uses the DefaultControllerActivator constructor, which takes the ITypeActivatorCache instance to create the controller. This is how the controller instance is created in ASP.NET Core MVC Application.
Reflection in C#:
Now, I am going to give you a basic idea of how to use Reflection, and we can create an instance of a class and invoke instance members of that class. Reflection is needed when you want to determine or inspect the content of an assembly. Here, content means the metadata of an assembly, like what are the methods in that assembly, what are the properties in that assembly, are they public, are they private, etc.
You can also use reflection to create an instance of a type dynamically, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. Please check the below link for more detailed information about Reflection.
https://dotnettutorials.net/lesson/reflection-in-csharp/
How to Invoke Methods Dynamically Using Reflection in C#?
One of the good features of reflection is that we can invoke the members of an assembly in C#. To invoke the assembly method using reflection, we need to use the InvokeMember method, as shown in the image below.
public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args);
This method invokes the specified member, using the specified binding constraints and matching the specified argument list. It returns an object representing the return value of the invoked member. This method takes the following parameters:
- name: The string containing the name of the constructor, method, property, or field member to invoke.
- invokeAttr: A bitmask comprised of one or more System.Reflection.BindingFlags that specify how the search is conducted. The access can be one of the BindingFlags such as Public, NonPublic, Private, InvokeMethod, GetField, and so on. The type of lookup need not be specified. If the type of lookup is omitted, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static is used.
- binder: An object that defines a set of properties and enables binding, which can involve the selection of an overloaded method, argument types, and invocation of a member through reflection. Here, we are passing a null value.
- target: The object on which to invoke the specified member. In our example, the object is MyObject.
- args: An array containing the arguments to pass to the member to invoke. As our method does not take any arguments, we pass null here.
Note: This method of invocation is completely done at runtime. If the method exists at runtime, it will invoke the method; else, it will throw an exception. That means Reflection in C# does the complete dynamic invocation of the method during runtime.
Example to Invoke a Method Dynamically using Reflection in C#:
Create a Console Application with the name ReflectionDemo. And then, add a class file with the name SomeClass.cs and copy and paste the following code into it.
namespace ReflectionDemo { public class SomeClass { public int SomeMethod(int x, int y) { return x + y; } } }
Now, what is my requirement? I want to create an instance of SomeClass and wants to invoke the SomeMethod method dynamically using the Reflection concept. So, let us modify the Main method of the Program class as follows. The following example code is self-explained, so please go through the comment lines for a better understanding.
using System; // Import the Reflection namespace using System.Reflection; namespace ReflectionDemo { class Program { static void Main(string[] args) { // Get the Type which instance you want to Create //Get the Assembly Reference of SomeClass i.e. Get the Assembly where the SomeClass is created //The Assembly you can find inside the bin=>debug directory of your project var MyAssembly = Assembly.LoadFile(@"D:\Projects\ReflectionDemo\ReflectionDemo\bin\Debug\ReflectionDemo.exe"); //Get the Class Reference var MyType = MyAssembly.GetType("ReflectionDemo.SomeClass"); //Create an instance of the type using the CreateInstance Method of the Activator Class dynamic MyObject = Activator.CreateInstance(MyType); //Get the Type of the class Type parameterType = MyObject.GetType(); //To Get all Public Fields/variables Console.WriteLine("All Public Members"); foreach (MemberInfo memberInfo in parameterType.GetMembers()) { Console.WriteLine(memberInfo.Name); } Console.WriteLine("\nInvoking SomeMethod"); object[] parametersArray = new object[] {10, 20 }; var result = parameterType.InvokeMember("SomeMethod", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, Type.DefaultBinder, MyObject, parametersArray ); Console.WriteLine(result); Console.ReadKey(); } } }
Output:
In the next article, I am going to discuss ASP.NET Core MVC Views with Examples. Here, in this article, I try to explain ASP.NET Core MVC Controllers with Examples. I hope you enjoy this ASP.NET Core MVC Controllers article.
About the Author: Pranaya Rout
Pranaya Rout has published more than 3,000 articles in his 11-year career. Pranaya Rout has very good experience with Microsoft Technologies, Including C#, VB, ASP.NET MVC, ASP.NET Web API, EF, EF Core, ADO.NET, LINQ, SQL Server, MYSQL, Oracle, ASP.NET Core, Cloud Computing, Microservices, Design Patterns and still learning new technologies.
very usefull guide