Sign in to track progress and bookmarks.
Routing is how ASP.NET Core matches incoming URLs (like GET /api/users/42) to the exact C# code (Controller and Action Method) that should process the request. Understanding how to structure your routes is crucial for building a predictable, REST-compliant API.
Defined globally in Program.cs (e.g., pattern: "{controller}/{action}/{id?}"). Primarily used in traditional MVC UI applications. Anti-Pattern for Web APIs.
Defined locally using C# Attributes directly above the controllers and action methods. This is the industry standard for Web APIs because it provides fine-grained, explicit control over HTTP semantics.
Attribute Routing empowers you to strongly type your URL routes using constraints. If a client sends string data to an endpoint expecting an integer, the route rejects the request instantly with a 404 Not Found before your code even executes.
[ApiController]
// [controller] is a token. It automatically outputs "api/products"
// by stripping the word "Controller" from the class name.
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
// 1. Basic Route: Matches GET /api/products
[HttpGet]
public IActionResult GetAll() { ... }
// 2. Route Parameter: Matches GET /api/products/42
// Added a Route Constraint ":int" - enforces the ID MUST be an integer.
// Added ":min(1)" - enforces ID cannot be 0 or negative.
[HttpGet("{id:int:min(1)}")]
public IActionResult GetById(int id)
{
return Ok($"Found product {id}");
}
// 3. Optional Parameters & Defaults: Matches GET /api/products/category/books?page=1
// A "?" makes a parameter optional, but setting a default value is better.
[HttpGet("category/{categoryName=General}")]
public IActionResult GetByCategory(string categoryName) { ... }
}
The most common startup crash in ASP.NET Core APIs is an AmbiguousMatchException. This occurs when two methods try to listen to the exact same URL and HTTP Verb pattern.
// ❌ BAD: DANGEROUS CODE THAT CRASHES APP ON START
[HttpGet]
public IActionResult GetActiveUsers() { ... }
[HttpGet]
public IActionResult GetInactiveUsers() { ... }
// Both methods match "GET /api/users". The framework panics.
// ✅ GOOD: DIVERGING THE PATHS
[HttpGet("active")] // Matches GET /api/users/active
public IActionResult GetActiveUsers() { ... }
[HttpGet("inactive")] // Matches GET /api/users/inactive
public IActionResult GetInactiveUsers() { ... }
When you create a robust API, you often need to generate a URL pointing to a newly created resource. To do this, you must explicitly Name your routes using the Name = "" parameter.
[HttpPost]
public IActionResult CreateProduct(ProductDto dto)
{
var newProduct = _db.SaveToDatabase(dto);
// Creates a 201 Created HTTP Response, AND generates a "Location" header URL
// pointing back to the "GetProductById" action.
return CreatedAtRoute("GetProductById", new { id = newProduct.Id }, newProduct);
}
// We explicitly named this route so the POST method above can find it globally
[HttpGet("{id}", Name = "GetProductById")]
public IActionResult GetProduct(int id) { ... }
Q: "Why is Attribute Routing heavily preferred over Conventional Routing when building RESTful APIs in ASP.NET Core?"
Architect Answer: "RESTful principles dictate that URLs should represent *Resources*, not internal code structures. Conventional Routing forces the URL to mirror the specific Controller and Action method name (e.g., /api/Users/GetActiveUsers). This violates REST standards because 'GetActiveUsers' is an action verb. Attribute routing completely decouples the URL structure from the C# method names. We can name our method GetActiveUsers internally for C# readability, but use [HttpGet('active')] above it, making the resulting URL a clean GET /api/users/active. Furthermore, Attribute Routing natively integrates HTTP verb constraints (GET, POST, PUT), which is foundational to API design."
Quizzes linked to this course—pass to earn certificates.
On this page
1. Conventional Routing vs Attribute Routing 2. Applying Attribute Constraints 3. Handling Ambiguous Routes 4. Naming Your Routes for Resource Generation 5. Interview Mastery