Controllers in ASP.NET Core MVC

Controllers are a fundamental component of the Model-View-Controller (MVC) architectural pattern used in ASP.NET Core. They act as the central orchestrator, handling incoming requests, interacting with models to retrieve or manipulate data, and selecting views to render the response.

What is a Controller?

A controller is a class that contains methods, known as action methods, which are responsible for processing specific HTTP requests. These action methods typically:

  • Receive user input from the request (e.g., form data, URL parameters).
  • Interact with the application's data models to perform business logic.
  • Select the appropriate view to display the results.
  • Return an HTTP response to the client.

Creating a Controller

Controllers in ASP.NET Core are typically plain C# classes that inherit from the Controller base class (or ControllerBase for API-only scenarios). The Controller class provides properties and methods that help manage the request-response cycle, such as:

  • ControllerContext: Access to information about the current request and response.
  • ModelState: Manages validation state for incoming data.
  • TempData: A mechanism for passing data between requests.
  • ViewBag and ViewData: Properties for passing data to the view.

using Microsoft.AspNetCore.Mvc;

namespace MyWebApp.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            // Logic to prepare data for the view
            ViewBag.Message = "Welcome to ASP.NET Core MVC!";
            return View(); // Renders the Index.cshtml view
        }

        public IActionResult About()
        {
            ViewBag.Title = "About Us";
            return View(); // Renders the About.cshtml view
        }

        // Action method with a parameter
        public IActionResult Details(int id)
        {
            // Fetch data for the given ID
            var item = GetItemById(id);

            if (item == null)
            {
                return NotFound(); // Returns a 404 Not Found result
            }

            return View(item); // Passes the item data to the view
        }

        private object GetItemById(int id)
        {
            // Placeholder for data retrieval logic
            if (id == 1) return new { Id = 1, Name = "Sample Item" };
            return null;
        }
    }
}
                    

Routing to Controllers

ASP.NET Core uses a routing system to map incoming HTTP requests to specific action methods within controllers. The default routing configuration in ASP.NET Core MVC uses a convention-based approach where the URL typically follows the pattern /{controller}/{action}/{id?}.

Tip: The IActionResult return type for action methods is highly flexible. It allows you to return various types of results, such as ViewResult (for rendering a view), RedirectResult (for redirection), JsonResult (for returning JSON data), and ContentResult (for returning plain text).

Action Methods

Action methods are public methods within a controller class. They are invoked by the routing system based on the incoming request URL. Key characteristics of action methods:

  • Must return an IActionResult or a type that can be converted to one.
  • Can accept parameters that are bound from the request (e.g., query string, route data, form body).
  • Are typically public.

Model Binding

Model binding is a powerful feature that automatically maps incoming request data (like form fields, route data, and query string parameters) to parameters of your action methods. This significantly reduces the amount of manual data parsing you need to do.

Important: Ensure your action method parameters match the names of the data you expect from the request for automatic model binding to work seamlessly. You can use attributes like [FromQuery], [FromRoute], [FromBody], and [FromForm] to explicitly control how parameters are bound.

Controller Filters

Filters are a way to implement cross-cutting concerns, such as authorization, error handling, logging, and response caching, that can be applied to action methods or entire controllers. ASP.NET Core provides several built-in filter types, and you can also create custom filters.

  • Authorization Filters: Execute before the action method to determine if the request is authorized.
  • Resource Filters: Execute at the beginning and end of the action method execution pipeline.
  • Action Filters: Execute before and after the action method.
  • Result Filters: Execute before and after the result is executed.
  • Exception Filters: Handle exceptions that occur during action method execution.

Working with Views

After processing the request and preparing data, controllers select a view to render the final HTML response. This is typically done by calling the View() method, which can optionally take a model object to be passed to the view.


// In the Controller:
public IActionResult ProductDetails(int productId)
{
    var product = _productService.GetProductById(productId);
    if (product == null)
    {
        return NotFound();
    }
    return View(product); // Passes the 'product' object to the view
}

// In ProductDetails.cshtml (a Razor view):
@model Product

@Model.Name

@Model.Description

Price: @Model.Price.ToString("C")

API Controllers

For building web APIs, ASP.NET Core offers ApiController, which inherits from ControllerBase. ApiController provides additional conveniences for API development, such as automatic model validation and HTTP status code handling.

Note: When creating API controllers, you typically don't return views. Instead, you return data formats like JSON or XML using methods like Ok(), NotFound(), BadRequest(), and by returning objects that are automatically serialized.

Conclusion

Controllers are the heart of an ASP.NET Core MVC application, handling the logic of processing requests and orchestrating the flow of data and presentation. Understanding how to create, route to, and manage controllers is essential for building robust and maintainable web applications.