Explicit routing gives an endpoint its own route template: a pattern that maps a request URL to code that handles it. In an ASP.NET Core web API controller, you declare that template with an attribute on an action method, so this approach is also called attribute routing. It gives you direct control over API URLs, at the cost of more attributes than convention-based routing. section 14.2 section 20.3
Give an action a URL
Put [HttpGet("fruit")] on an action that returns a list of fruit. A GET request to /fruit executes that action and returns the list as JSON. To fetch one item, [HttpGet("fruit/{id}")] adds a route parameter; the action can receive id as an int and return NotFound() when no item exists. Register controller services with AddControllers() and expose controller actions as endpoints with MapControllers(). section 20.1
An attribute’s template determines the URL; the controller and action names do not determine it by default. [Route("")] can map an action to /, while [Route("contact")] maps one to /contact. You can place multiple [Route] attributes on one action when several URLs should execute it. Templates can also contain route parameters, defaults, and constraints. section 20.3
To avoid repeating a prefix, put a route attribute on a controller or inherited base controller and a shorter one on each action. The attributes combine to form the final template. Tokens such as [controller] and [action] substitute the corresponding names after combination; a template beginning with / instead stands apart from the prefix. Use literal strings when renaming a class or method must not change a public URL. section 20.3.2 section 20.7
Listing 20.8 Token replacement in RouteAttributes
[Route("api/[controller]")] #1
public abstract class BaseController { } #2
public class CarController : BaseController
{
[Route("[action]")] #3
[Route("ignition")] #4
[Route("/start-car")] #5
public IActionResult Start()
{
/* method implementation*/
}
}
#1 You can apply attributes to a base class, and derived classes will inherit them.
#2 Token replacement happens last, so [controller] is replaced with “car” not “base”.
#3 Combines and replaces tokens to give the “api/car/start” template
#4 Combines and replaces tokens to give the “api/car/ignition” template
#5 Does not combine with base attributes because it starts with /, so it remains as “start-car”
Compare the combined api/car/start and api/car/ignition templates with the separate /start-car template. The listing also shows when [controller] and [action] are replaced. section 20.3.2
Choose a verb-specific attribute when an API action should handle only one request type. [HttpGet("/appointments")] and [HttpPost("/appointments")] can route the same URL to different actions. By contrast, [Route] accepts all HTTP verbs; a request that matches a verb-specific route’s URL but not its verb receives a 405 Method Not Allowed response. section 20.3.3
Minimal APIs also use explicit routes, declared with methods such as MapGet(), while Razor Pages generate explicit templates from page conventions and can customize them with @page. Traditional HTML-generating MVC controllers often use global conventions instead. For web API controllers marked [ApiController], attribute routing is required. section 14.2 section 20.4
