Latest update Android YouTube

Chapter 5 - Controllers, Routing & Action Methods in ASP.NET Core

Controllers, Routing & Action Methods in ASP.NET Core

Controllers are the backbone of any ASP.NET Core API. They receive HTTP requests, process input, communicate with services and databases, and send structured responses back to clients. Routing determines which controller action gets executed, while action methods define how each endpoint behaves.

In this chapter, we take a deep dive into building controllers, configuring routing, creating action methods, handling parameters, returning responses, and following REST best practices.

1. What is a Controller?

A controller is a C# class that handles HTTP requests. In ASP.NET Core, APIs typically use ApiController classes that inherit from ControllerBase. Controllers map incoming HTTP requests to action methods, which then return responses in JSON, XML, or other formats.


using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult GetAll()
    {
        return Ok(new[] { "Laptop", "Mobile", "Tablet" });
    }
}
    

Key Attributes Explained:

  • [ApiController] → Enables automatic validation, binding, and routing conventions
  • [Route("api/[controller]")] → Maps URL to controller name
  • [HttpGet] → Maps GET HTTP method to action

2. How Routing Works in ASP.NET Core

Routing decides which controller method should handle an incoming request. ASP.NET Core uses attribute routing, which means you define your routes directly above controllers and action methods.

2.1 Attribute Routing

Attribute routing means defining routes on controller classes and action methods using attributes like [Route], [HttpGet], etc. It gives developers full control over URL structure.


[Route("api/products")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult Get() { ... }

    [HttpGet("{id}")]
    public IActionResult GetById(int id) { ... }
}
    

2.2 Route Parameters

Route parameters extract values directly from the URL. They allow you to pass dynamic information (like product ID or category name) into action methods.


[HttpGet("{id}")]
public IActionResult GetProduct(int id) { ... }

[HttpGet("category/{categoryName}")]
public IActionResult GetByCategory(string categoryName) { ... }
    

Optional Parameters:

Optional parameters allow routes to work with or without a parameter.


[HttpGet("{id?}")]
public IActionResult Get(int? id) { ... }
    

Constraint Example:

Route constraints validate the parameter format directly in the route.


[HttpGet("{id:int:min(1)}")]
public IActionResult Get(int id) { ... }
    

3. Action Methods

Action methods are the functions inside controllers that execute when a route matches the request. They return results using IActionResult or ActionResult<T>.


[HttpPost]
public IActionResult CreateProduct(ProductDto model)
{
    if (!ModelState.IsValid)
        return BadRequest(ModelState);

    return CreatedAtAction(nameof(GetById), new { id = 101 }, model);
}
    

Common IActionResult Responses:

  • Ok(obj) → 200 OK
  • CreatedAtAction() → 201 Created
  • NoContent() → 204 No Content
  • BadRequest() → 400 Bad Request
  • NotFound() → 404 Not Found

4. Query Parameters

Query parameters allow clients to filter, sort, or search resources using the URL. They appear after a ? in the request.


/api/products?category=mobile&sort=price_desc
    

[HttpGet]
public IActionResult Search(string category, string sort = "price_asc")
{
    return Ok($"Category: {category}, Sort: {sort}");
}
    

5. Request Body Parameters

Body parameters contain JSON data provided by the client, usually during POST or PUT operations.


[HttpPost]
public IActionResult AddProduct([FromBody] ProductDto model)
{
    return Ok(model);
}
    

6. [FromRoute], [FromQuery], [FromBody]

These attributes specify where ASP.NET Core should read the value from.


[HttpPut("{id}")]
public IActionResult Update(
    [FromRoute] int id, 
    [FromBody] ProductDto model)
{
    return Ok($"Updating product {id}");
}
    

7. HTTP Method Attributes

HTTP method attributes specify the type of request the action handles, ensuring REST-compliant API design.


[HttpGet]       → Fetch data
[HttpPost]      → Create resource
[HttpPut]       → Replace resource
[HttpPatch]     → Partial update
[HttpDelete]    → Remove resource
    

8. Produces and Consumes Attributes

Use [Produces] to define the output format of an action and [Consumes] to define accepted input formats.


[Produces("application/json")]
[Consumes("application/json")]
    

9. Naming Action Methods

Action names must follow REST naming conventions. Avoid method names that indicate verbs.

Good:


Get(), GetById(), Create(), Update(), Delete()
    

Avoid:


GetAllProducts(), InsertProduct(), RemoveProduct()
    

10. Route Prefixing

A route prefix defines a base URL for an entire controller. Useful for versioning.


[Route("api/v1/products")]
public class ProductsController : ControllerBase { }
    

11. Custom Route Patterns

Custom route patterns allow you to create nested or hierarchical routing structures. This is useful when resources have child entities.

Example:


GET /api/orders/10/items
    

[HttpGet("{orderId}/items")]
public IActionResult GetItems(int orderId) { ... }
    

12. Content Negotiation

Content negotiation allows clients to request responses in different formats (JSON, XML, etc.) using the Accept header.


builder.Services.AddControllers()
    .AddXmlSerializerFormatters();
    

13. IActionResult vs ActionResult<T>

IActionResult returns a generic HTTP response, while ActionResult<T> returns a typed object plus status code.


public ActionResult<ProductDto> Get(int id)
{
    return new ProductDto { Id = id, Name = "Watch" };
}
    

14. Standard API Response Structure

Creating a consistent API response format makes debugging and client-side integration easier.


public class ApiResponse<T>
{
    public bool Success { get; set; }
    public T Data { get; set; }
    public string Message { get; set; }
}
    

15. Best Practices for Controllers

To ensure clean, maintainable controllers, follow these guidelines:

  • Keep controllers thin—place business logic in services
  • Use DTOs, never expose entity classes directly
  • Use async/await for database or network calls
  • Always return appropriate HTTP status codes
  • Use dependency injection instead of instantiating objects
  • Split controllers by responsibility (small controllers)
  • Use validation libraries instead of manual validation

Conclusion

Controllers handle the core processing logic of your API. Mastering routing, HTTP methods, action methods, and response formats sets the foundation for scalable API design. In the next chapter, we will explore Models, DTOs, ViewModels, and mapping patterns.

إرسال تعليق

Feel free to ask your query...
Cookie Consent
We serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience.
Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.
AdBlock Detected!
We have detected that you are using adblocking plugin in your browser.
The revenue we earn by the advertisements is used to manage this website, we request you to whitelist our website in your adblocking plugin.
Site is Blocked
Sorry! This site is not available in your country.