Introduction

For anyone learning ASP.NET Core, understanding controllers, routes, and endpoints is crucial. These are the building blocks of a web API or MVC application.

Controllers handle incoming requests, routes define how requests reach controllers, and endpoints determine the response sent back to clients. A proper understanding of these concepts helps you design clean, maintainable, and efficient web applications.

This article explains these concepts in a step-by-step, beginner-friendly manner, with examples suitable for beginners and web developers building APIs or full-stack applications.

What is a Controller?

A controller in ASP.NET Core is a class that handles HTTP requests. It acts as a bridge between the client and the server, processing requests, executing logic, and returning responses.

Controllers can be used in two main types of projects:

  1. MVC Applications – Controllers return views or pages.

  2. Web API Applications – Controllers return data in JSON, XML, or other formats.

Creating a Simple Controller

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    [HttpGet]
    public IActionResult GetUsers()
    {
        var users = new string[] { "John", "Jane", "Rahul" };
        return Ok(users);
    }
}

Explanation

Understanding Routes in ASP.NET Core

A route defines the URL pattern that maps to a controller and its actions. ASP.NET Core supports two types of routing:

  1. Conventional Routing

  2. Attribute Routing

1. Conventional Routing

Conventional routing is defined in Program.cs or Startup.cs and follows a predefined pattern:

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

Example URL

/Users/GetUsers

Maps to UsersController.GetUsers().

2. Attribute Routing

Attribute routing uses attributes directly on controllers and action methods to define routes:

[ApiController]
[Route("api/users")]
public class UsersController : ControllerBase
{
    [HttpGet("all")]
    public IActionResult GetAllUsers() => Ok(new[] { "John", "Jane" });

    [HttpGet("{id}")]
    public IActionResult GetUserById(int id) => Ok($"User {id}");
}

Understanding Endpoints

An endpoint is the final destination of a request in ASP.NET Core. It represents a combination of:

ASP.NET Core maps requests to endpoints using middleware and routing configurations.

Example of Multiple Endpoints

[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult GetAllProducts() => Ok(new[] { "Laptop", "Phone" });

    [HttpPost]
    public IActionResult AddProduct([FromBody] string product) => Ok($"Added {product}");

    [HttpGet("{id}")]
    public IActionResult GetProductById(int id) => Ok($"Product {id}");
}

Endpoints

HTTP MethodURLAction
GET/api/productsGetAllProducts
POST/api/productsAddProduct
GET/api/products/1GetProductById

Route Parameters

Routes can accept parameters that are passed to action methods.

[HttpGet("{id}/details")]
public IActionResult GetProductDetails(int id)
{
    return Ok($"Details of product {id}");
}

Optional parameters

[HttpGet("{id?}")]
public IActionResult GetProduct(int? id)
{
    return Ok(id.HasValue ? $"Product {id}" : "All Products");
}

Query Strings vs Route Parameters

  1. Route Parameters – Part of the URL path:

GET /api/products/5
  1. Query Strings – Appended after ? in the URL:

GET /api/products?id=5&name=Laptop

Action method

[HttpGet("search")]
public IActionResult SearchProduct(int id, string name)
{
    return Ok($"Product {id} - {name}");
}

Combining Multiple Routes

You can define complex routing with multiple segments:

[HttpGet("category/{categoryId}/product/{productId}")]
public IActionResult GetCategoryProduct(int categoryId, int productId)
{
    return Ok($"Category {categoryId} - Product {productId}");
}

HTTP Methods and Endpoints

ASP.NET Core supports all HTTP methods:

Example

[HttpPut("{id}")]
public IActionResult UpdateProduct(int id, [FromBody] string product)
{
    return Ok($"Updated product {id} to {product}");
}

[HttpDelete("{id}")]
public IActionResult DeleteProduct(int id)
{
    return Ok($"Deleted product {id}");
}

Best Practices

  1. Use Attribute Routing for APIs: Provides clear, readable URLs.

  2. Keep Controllers Focused: Each controller should handle a single resource (e.g., UsersController handles users).

  3. Use HTTP Status Codes Properly: 200 for success, 201 for created, 404 for not found, 400 for bad request.

  4. Validate Route Parameters: Avoid unexpected errors by validating input.

  5. Consistent Naming: Use plural names for controllers (UsersController) and lowercase for URLs (/api/users).

  6. Version Your APIs: For example, /api/v1/users to maintain backward compatibility.

Common Mistakes to Avoid

  1. Mixing multiple resources in one controller.

  2. Using complex URLs when simple ones suffice.

  3. Forgetting [ApiController] attribute for APIs.

  4. Not handling optional parameters carefully.

  5. Returning plain strings instead of proper HTTP responses with IActionResult.

Conclusion

Understanding controllers, routes, and endpoints is the foundation of building web APIs and MVC applications in ASP.NET Core.

Mastering these concepts allows you to design clean, scalable, and maintainable APIs. Once you are comfortable with these basics, you can integrate ASP.NET Core APIs with frontend frameworks like Angular, React, or Vue.js for full-stack development.