Mastering API Routing and Controllers in ASP.NET

When interacting with API endpoints, we often need to send authentication, authorization, and task-specific data. Applications usually have multiple endpoints, each serving a specific purpose — login, loading page data, processing payments, etc. For each endpoint, it’s crucial to evaluate its functionality, the required data, and how this data will be provided.
Routing and Controllers
In ASP.NET, we can map routes to controllers using attribute-based routing. Below is a basic example of how to configure this in the Program.cs
file:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseRouting(); // Adds routing middleware to the pipeline
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers(); // Enables attribute-based controller routing
});
app.Run();
Attribute-Based Routing
Define your routes directly in the controllers:
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult GetAll()
{
return Ok(new[] { "Product1", "Product2" });
}
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
return Ok($"Product {id}");
}
}
[Route("api/[controller]")]
: Sets the base route for the controller. The[controller]
token dynamically replaces the controller name.[HttpGet]
: Specifies the HTTP method supported by the action.[HttpGet("{id}")]
: Adds a route parameter (id
), accessible via URLs like/api/products/1
.
Generated URLs:
GET /api/products
→ Maps toGetAll
.GET /api/products/1
→ Maps toGetById
.
Dynamic Tokens in Routing
You can dynamically replace tokens in routes:
[controller]
: The controller name without the "Controller" suffix.[action]
: The method name.[area]
: The area name (used with areas).
[Route("api/[controller]/[action]")]
[ApiController]
public class OrdersController : ControllerBase
{
[HttpGet]
public IActionResult List()
{
return Ok("Listing orders");
}
[HttpPost]
public IActionResult Create()
{
return Ok("Creating an order");
}
}
Generated URLs:
GET /api/orders/list
→ Maps toList
.POST /api/orders/create
→ Maps toCreate
.
Custom Routes
Custom routes provide flexibility for specific methods:
[Route("api/orders")]
[ApiController]
public class OrdersController : ControllerBase
{
[HttpGet("latest")]
public IActionResult GetLatestOrders()
{
return Ok("Latest orders");
}
[HttpPost("create")]
public IActionResult CreateOrder()
{
return Ok("Order created");
}
}
Generated URLs:
GET /api/orders/latest
→ Maps toGetLatestOrders
.POST /api/orders/create
→ Maps toCreateOrder
.
Route Constraints
You can enforce constraints on route parameters for validation:
[HttpGet("{id:int}")]
public IActionResult GetById(int id)
{
return Ok($"Product {id}");
}
{id:int}
ensuresid
is an integer. Similarly:{name:minlength(3)}
ensuresname
has at least three characters.
If a request doesn’t meet the constraints, the server returns HTTP 404 Not Found. To customize this behavior, use middleware to handle these cases with tailored responses.
You can create custom constraints implementing IRouteConstraint
interface.
Areas
Areas are used to organize controllers into different sections of an application.
Configuration:
[Area("Admin")]
[Route("admin/[controller]/[action]")]
public class DashboardController : Controller
{
public IActionResult Index()
{
return View();
}
}
Resulting URL:/admin/dashboard/index
→ Maps to DashboardController.Index
.
Conclusion
Understanding and configuring routing in ASP.NET allows you to streamline your application’s behavior and enhance its flexibility. From attribute-based routing to custom constraints, these techniques enable precise control over how endpoints are accessed. In the next post, we’ll delve into securing these routes with authentication and authorization.