Chapter 6: Mapping URLs to endpoints using routing
This chapter introduces routing as the system that selects endpoint handlers from request URLs, matches flexible route templates, and generates URLs without hardcoding them.
After this chapter you will be able to
- Endpoint selection by routing. Explain that routing selects a particular endpoint handler from the application's defined handlers by examining the incoming request URL. Describe routing as the glue connecting the middleware pipeline to endpoints.
- Route template matching features. Describe that route templates provide flexible URL matching and can extract URL values automatically for minimal API endpoints. State that the chapter covers parameters, optional parameters, default parameters, constraints, and catch-all matching as template features.
- Route-based URL generation. Explain that routing can generate URLs at runtime from route parameters for links and redirects. Justify this approach by explaining that it decouples handlers and other code from hardcoded URLs, so changing an endpoint URL updates generated URLs without finding every literal URL use.
- Routing as handler selection. Explain that routing in ASP.NET Core selects a specific handler for an incoming HTTP request by matching the request URL to configured routes. Describe the handler types used by minimal APIs, Razor Pages, and MVC.
- Dynamic URL mapping. Describe why routing lets one handler serve multiple dynamic URLs, such as URLs for different products, instead of requiring a separate static handler for every product. Distinguish route-based URL data from a query string, which routing does not use to identify the handler.
- Endpoint and route registration. Describe an ASP.NET Core endpoint as a response-producing handler associated with a URL pattern, and explain how Map* methods register endpoints on an IEndpointRouteBuilder such as WebApplication.
- Two-stage endpoint routing. Trace how EndpointRoutingMiddleware selects a matching endpoint and records it on HttpContext, after which EndpointMiddleware executes that selected endpoint and its associated endpoint filters.
- Middleware placement around routing. Justify placing middleware that needs endpoint information after RoutingMiddleware and before EndpointMiddleware, while middleware placed before routing cannot know which endpoint will be selected.
- Literal URL matching. Explain that a literal segment must match the corresponding URL text exactly except for case, and that a template made entirely of literals matches only that URL shape. Use the /About/Contact example to distinguish it from URLs with missing, changed, or extra segments.
- Required parameter route values. Explain that a brace-delimited route parameter matches a varying URL segment but requires that segment to be present, with no unmatched extra segments. Describe how a successful match captures each parameter value as a string route value in the request's route-value dictionary, which model binding can supply to an endpoint handler.
- Default route parameter values. Explain how a route parameter with a default value, such as {name=all}, supplies that value when its URL segment is omitted. Describe that /product/shoes and /product/shoes/all are equivalent for the shown template, producing category=shoes and name=all.
- Optional route parameter behavior. Describe how an optional parameter marked with ?, such as {id?}, matches whether or not its final URL segment is present. State that a present segment becomes the id route value, whereas an absent segment creates no route value for id.
- Route constraint syntax. Describe how to attach a constraint to a route parameter with a colon, such as {id:int}, and explain that a URL matches only when its route value satisfies the constraint.
- Appropriate constraint use. Justify using route constraints sparingly for strict URL requirements or overlapping route templates, while avoiding them for general input validation because a failed constraint produces a 404 response; explain that overlapping templates should generally be designed away.
- Catch-all parameter matching. Describe how a catch-all parameter captures all unmatched URL content after earlier route segments, including slash characters, as one route-value string. Explain that it can also match an empty string.
- Greedy matching and URL encoding. Explain that catch-all parameters are greedy, so overlapping templates can be confusing, and distinguish their URL-generation behavior: {*} encodes forward slashes whereas {**} preserves them. State that the two-asterisk form usually provides the desired round-trip behavior.
- Dynamic URL generation. Explain why generating URLs through the routing infrastructure is preferable to hardcoding endpoint URLs. Describe how it lets route templates change, such as renaming /cart to /basket, without requiring every internal link to be manually updated.
- Routing reversal model. Describe URL generation as the reverse of routing: routing takes a URL, matches it to a route template, and produces route values, whereas URL generation combines route values with a route template to build a URL.
- Named endpoint references. Describe how WithName() adds a name as endpoint metadata so that LinkGenerator can refer to a target minimal API endpoint by name. State that endpoint names are case-sensitive and globally unique, because duplicate names cause runtime exceptions.
- Named-route URL generation. Explain how GetPathByName() generates a path from an endpoint name and optional route values supplied as properties of an anonymous object. Distinguish GetUriByName(), which can generate a complete URL when given host and scheme values, from HttpContext-based LinkGenerator methods that reuse ambient request values; explain that a route value fills a matching route parameter or becomes a query-string value when the route template has no such parameter.
- Route-based redirect generation. Describe how Results.RedirectToRoute() redirects a client to a named endpoint by taking the endpoint name and required route parameters, generating its URL, and returning that redirect response without exposing the URL in application code.
- Global RouteOptions conventions. Describe how to configure RouteOptions globally through WebApplicationBuilder.Services using Configure<T>. State that RouteOptions can force generated paths to lowercase, optionally lowercase query strings, and append a trailing slash; path lowercasing includes route-parameter segments.
- Per-link LinkOptions overrides. Explain that an optional LinkOptions argument passed to LinkGenerator methods overrides the app-wide RouteOptions defaults for that individual generated link. Describe this as useful when a specific link must follow a legacy API convention that differs from the application's normal URL style.
What it builds on
- Defining minimal API endpoints (chapter 5) · Minimal API endpoints, URL values, HTTP verb mappings, and route handlers.
- Defining how requests are handled with middleware and endpoints (chapter 3) · The distinction between middleware and endpoints when defining request handling.
- Combining middleware in a pipeline (chapter 4) · How a request moves through a middleware pipeline.
- Extracting values from the URL with routing (chapter 5) · The initial use of routing to extract values from a URL in minimal APIs.
- Filters or middleware: Which should you choose? (chapter 5) · The distinction between endpoint filters and middleware.
- Simple pipeline scenario 3: A minimal API application (chapter 4) · The middleware pipeline, terminal behavior, and the default 404 behavior when no component handles a request.
- Defining route handlers with functions (chapter 5) · Minimal API route handlers receive values associated with requests.
- Returning status codes with Results and TypedResults (chapter 5) · Minimal API results that return HTTP status-code responses.
Section by section
Introduction
This chapter introduces routing as the system that selects endpoint handlers from request URLs, matches flexible route templates, and generates URLs without hardcoding them.
- Routing chapter roadmap: Describe the chapter's routing topics: selecting endpoints from incoming URLs, route-template features such as parameters, defaults, optional values, and constraints, and generating URLs from route data. State that the examples focus on minimal APIs while the routing system is also used by Razor Pages and MVC.
Why it matters: This roadmap helps you connect the chapter's individual syntax features to the larger routing system. - Endpoint selection by routing: Explain that routing selects a particular endpoint handler from the application's defined handlers by examining the incoming request URL. Describe routing as the glue connecting the middleware pipeline to endpoints.
Why it matters: Routing is how an ASP.NET Core request reaches the endpoint intended to handle its URL. - Route template matching features: Describe that route templates provide flexible URL matching and can extract URL values automatically for minimal API endpoints. State that the chapter covers parameters, optional parameters, default parameters, constraints, and catch-all matching as template features.
Why it matters: Route-template features let an application accept useful URL shapes and obtain values from them without manually parsing URLs. - Route-based URL generation: Explain that routing can generate URLs at runtime from route parameters for links and redirects. Justify this approach by explaining that it decouples handlers and other code from hardcoded URLs, so changing an endpoint URL updates generated URLs without finding every literal URL use.
Why it matters: Generating URLs through routing makes endpoint URL changes less error-prone than maintaining hardcoded links and redirects.
Key terms: routing, endpoint routing, route template, minimal APIs, Razor Pages, MVC, endpoint, endpoint handler, incoming request URL, middleware pipeline
6.1 What is routing?
This section introduces routing as the process that selects a request handler and explains why customizable, dynamic URLs are preferable to purely static mappings or query-string-based URLs.
- Routing as handler selection: Explain that routing in ASP.NET Core selects a specific handler for an incoming HTTP request by matching the request URL to configured routes. Describe the handler types used by minimal APIs, Razor Pages, and MVC.
Why it matters: Routing determines which part of your application responds to each URL a user requests. - Dynamic URL mapping: Describe why routing lets one handler serve multiple dynamic URLs, such as URLs for different products, instead of requiring a separate static handler for every product. Distinguish route-based URL data from a query string, which routing does not use to identify the handler.
Why it matters: Dynamic route URLs let an application scale beyond a small fixed set of pages while keeping its URLs clean. - URL and handler decoupling: Explain that routing decouples exposed URLs from handler filenames or locations, so URLs can change without moving the handler. Describe how this flexibility enables friendlier, customizable URLs and can support site hierarchy, discovery, hackability, and SEO.
Why it matters: Separating public URLs from code location lets you improve an application's URL design without restructuring its handlers.
Key terms: routing, EndpointMiddleware, handler, endpoint handler, page handler method, action method, static URL-based mapping, query string, model binding, dynamic URLs
6.2 Endpoint routing in ASP.NET Core
This section explains how endpoint routing registers URL-patterned handlers and uses two middleware stages to select and then execute an endpoint in the ASP.NET Core pipeline.
- Endpoint and route registration: Describe an ASP.NET Core endpoint as a response-producing handler associated with a URL pattern, and explain how Map* methods register endpoints on an IEndpointRouteBuilder such as WebApplication.
Why it matters: Endpoints and their route templates are the units that routing selects to handle incoming requests. - Two-stage endpoint routing: Trace how EndpointRoutingMiddleware selects a matching endpoint and records it on HttpContext, after which EndpointMiddleware executes that selected endpoint and its associated endpoint filters.
Why it matters: The split between selection and execution determines what information middleware can use during a request. - Unmatched route behavior: Explain that when no route template matches a request URL, no endpoint is selected or executed, but the request continues through the middleware pipeline and normally ends in a 404 response.
Why it matters: A missing route does not halt the pipeline at routing; the eventual response depends on the remaining pipeline. - Middleware placement around routing: Justify placing middleware that needs endpoint information after RoutingMiddleware and before EndpointMiddleware, while middleware placed before routing cannot know which endpoint will be selected.
Why it matters: Correct middleware order lets cross-cutting concerns inspect endpoint metadata before the endpoint runs.
Key terms: endpoint, route template, IEndpointRouteBuilder, WebApplication, MapGet, MapHealthChecks, EndpointRoutingMiddleware, RoutingMiddleware, EndpointMiddleware, HttpContext
6.3 Exploring the route template syntax
Introduces the route-template features that the following subsections explore beyond fixed paths and basic parameters.
- Route template feature roadmap: Describe the route-template capabilities introduced here: fixed literal paths and basic parameters have already been used, while the upcoming coverage expands to default values, optional segments, and constraints.
Why it matters: This roadmap frames the route-template tools used to make endpoint URLs more flexible and precise.
Key terms: route template, fixed values, route parameter, default values, optional segments, constraints
6.3.1 Working with parameters and literal segments
This section explains how route templates use slash-separated literal segments and required parameters to match URLs and capture route values.
- Route template segments: Describe how routing splits a route template into segments and distinguish literal segments from route-parameter segments. State that slash is the usual segment separator and that complex segments using other separators are generally best avoided.
Why it matters: Recognizing the segments in a template lets you predict how routing will interpret a URL pattern. - Literal URL matching: Explain that a literal segment must match the corresponding URL text exactly except for case, and that a template made entirely of literals matches only that URL shape. Use the /About/Contact example to distinguish it from URLs with missing, changed, or extra segments.
Why it matters: Literal segments let an endpoint be limited to a specific, predictable URL. - Required parameter route values: Explain that a brace-delimited route parameter matches a varying URL segment but requires that segment to be present, with no unmatched extra segments. Describe how a successful match captures each parameter value as a string route value in the request's route-value dictionary, which model binding can supply to an endpoint handler.
Why it matters: Route parameters make one endpoint handle variable URLs while preserving the values the endpoint needs to act on the request.
Key terms: route template, segment, literal segment, route parameter, complex segment, route value, route values, model binding, route-value dictionary
6.3.2 Using optional and default values
This section explains how default values and optional parameters in route templates let one endpoint match multiple URL shapes.
- Default route parameter values: Explain how a route parameter with a default value, such as {name=all}, supplies that value when its URL segment is omitted. Describe that /product/shoes and /product/shoes/all are equivalent for the shown template, producing category=shoes and name=all.
Why it matters: Defaults let an endpoint support shorter common URLs while still accepting a more explicit form. - Optional route parameter behavior: Describe how an optional parameter marked with ?, such as {id?}, matches whether or not its final URL segment is present. State that a present segment becomes the id route value, whereas an absent segment creates no route value for id.
Why it matters: Optional parameters allow a single route template to accept URLs with or without an extra value. - Optional parameter placement rule: State that an optional route parameter without a default value can appear only at the end of a route template. Explain that id cannot be provided without also providing the preceding category and name segments.
Why it matters: This rule prevents ambiguous route shapes when designing templates with optional path segments. - Flexible URL design rationale: Explain why defaults and optional parameters are useful: they let one template match a greater variety of URLs, while defaults can preserve short, memorable URLs for common cases.
Why it matters: Knowing the tradeoff helps you choose route templates that are both convenient for users and flexible for an application.
Key terms: default value, route parameter, route value, route template, optional route parameter, {id?}, optional parameter, default values, optional parameters
6.3.3 Adding additional constraints to route parameters
This section explains how route constraints narrow route-template matches, prevent incompatible route values, and help—but do not fully solve—ambiguous overlapping routes.
- Route constraint syntax: Describe how to attach a constraint to a route parameter with a colon, such as {id:int}, and explain that a URL matches only when its route value satisfies the constraint.
Why it matters: Constraints prevent a broadly matching template from sending unsuitable route values to an endpoint. - Constraint matching behavior: Explain that routing checks all constraints while matching a URL, and that constraints can test type convertibility or conditions such as minimum integer values, maximum string length, and regular-expression matches; multiple constraints are separated with colons.
Why it matters: Knowing that all constraints participate in matching helps you design routes that accept only the URL shapes your application intends. - Appropriate constraint use: Justify using route constraints sparingly for strict URL requirements or overlapping route templates, while avoiding them for general input validation because a failed constraint produces a 404 response; explain that overlapping templates should generally be designed away.
Why it matters: Using constraints for the right problem avoids confusing 404 responses and fragile route designs.
Key terms: route constraint, route template, route parameter, IntRouteConstraint, {id:int}, route constraints, invariant culture, regular expression, overlapping routes, 404
6.3.4 Matching arbitrary URLs with the catch-all parameter
This section explains how catch-all route parameters capture an arbitrary remainder of a URL and how their one- and two-asterisk forms differ during URL generation.
- Catch-all parameter matching: Describe how a catch-all parameter captures all unmatched URL content after earlier route segments, including slash characters, as one route-value string. Explain that it can also match an empty string.
Why it matters: Catch-all parameters let one endpoint handle URLs with an unknown number of remaining path segments. - Catch-all template syntax: State that catch-all parameters are declared with either {*name} or {**name}, and that both forms match incoming requests in the same way.
Why it matters: Knowing both declarations helps you recognize route templates and choose the appropriate form when generating links. - Greedy matching and URL encoding: Explain that catch-all parameters are greedy, so overlapping templates can be confusing, and distinguish their URL-generation behavior: {*} encodes forward slashes whereas {**} preserves them. State that the two-asterisk form usually provides the desired round-trip behavior.
Why it matters: This prevents ambiguous route designs and avoids generated links changing slash-containing catch-all values.
Key terms: catch-all parameter, route template, route value, URL segments, {*others}, {**others}, greedy, overlap, URL encoding, round-trip behavior
6.4 Generating URLs from route parameters
This section introduces URL generation as routing in reverse, using route values and route templates to create maintainable links and redirects dynamically.
- Dynamic URL generation: Explain why generating URLs through the routing infrastructure is preferable to hardcoding endpoint URLs. Describe how it lets route templates change, such as renaming /cart to /basket, without requiring every internal link to be manually updated.
Why it matters: Dynamic URL generation avoids broken internal links and 404 errors when an application's URL design changes. - Routing reversal model: Describe URL generation as the reverse of routing: routing takes a URL, matches it to a route template, and produces route values, whereas URL generation combines route values with a route template to build a URL.
Why it matters: Seeing URL generation as the reverse of route matching makes clear what information the URL generator needs to construct a link. - LinkGenerator scope and routes: State that LinkGenerator can generate URLs for minimal APIs and can be used throughout an application, including middleware and other services. Identify named-route methods as the focus here, while methods such as GetPathByPage and GetPathByAction are for Razor Pages and MVC actions covered later.
Why it matters: Knowing that LinkGenerator is available beyond endpoint handlers allows application components to create routing-aware URLs consistently.
Key terms: URL generation, routing infrastructure, route templates, routing, route values, route template, routing middleware, LinkGenerator, minimal APIs, named routes
6.4.1 Generating URLs for a minimal API endpoint with LinkGenerator
This section shows how minimal API endpoints use the DI-provided LinkGenerator and endpoint names to generate paths or full URLs from route values.
- Named endpoint references: Describe how WithName() adds a name as endpoint metadata so that LinkGenerator can refer to a target minimal API endpoint by name. State that endpoint names are case-sensitive and globally unique, because duplicate names cause runtime exceptions.
Why it matters: A stable endpoint name lets one endpoint link to another without hardcoding its URL template. - LinkGenerator service injection: Explain that LinkGenerator is an ASP.NET Core service registered automatically in the dependency injection container and can be received as a parameter of a minimal API handler. Describe its role as generating links to endpoints from their names and route templates.
Why it matters: Injecting LinkGenerator into a handler makes URL generation available where the application needs to create links. - Named-route URL generation: Explain how GetPathByName() generates a path from an endpoint name and optional route values supplied as properties of an anonymous object. Distinguish GetUriByName(), which can generate a complete URL when given host and scheme values, from HttpContext-based LinkGenerator methods that reuse ambient request values; explain that a route value fills a matching route parameter or becomes a query-string value when the route template has no such parameter.
Why it matters: Correctly supplying route values produces links that continue to match an endpoint even if its route template changes. - Host-value security caution: State that GetUriByName() can create security vulnerabilities when it uses unvalidated host values, so host values require care and validation/filtering when generating complete URLs.
Why it matters: Treating host values as trustworthy can allow an application to generate unsafe links.
Key terms: WithName(), endpoint metadata, endpoint names, minimal API endpoint, LinkGenerator, dependency injection container, handler, GetPathByName(), GetUriByName(), route data
6.4.2 Generating URLs with IResults
This section explains how minimal API IResults generate redirect responses to named endpoints or arbitrary URLs and how redirect status codes are selected.
- Route-based redirect generation: Describe how Results.RedirectToRoute() redirects a client to a named endpoint by taking the endpoint name and required route parameters, generating its URL, and returning that redirect response without exposing the URL in application code.
Why it matters: It lets an API direct a browser to another endpoint while keeping URL construction tied to routing. - Redirect response status selection: Explain that RedirectToRoute() returns 302 Found with the generated URL in the Location header by default, and describe how permanent and preserveMethod select 301, 307, or 308 redirect responses.
Why it matters: The redirect status communicates whether the move is permanent and whether the HTTP method should be retained. - Redirect destination safeguards: Distinguish Results.RedirectToRoute(), which targets a named endpoint, from Results.Redirect(), which accepts an arbitrary URL, and state that missing route values or an incorrect endpoint name can make route URL generation return null.
Why it matters: Choosing the appropriate redirect API and checking questionable route generation avoids broken redirect destinations.
Key terms: Results.RedirectToRoute(), named endpoint, route parameters, IResult, 302 Found, Location header, permanent, preserveMethod, 301 Moved Permanently, 307 Temporary Redirect
6.4.3 Controlling your generated URLs with RouteOptions
This section shows how to set global URL-generation conventions with RouteOptions and override them for individual LinkGenerator calls with LinkOptions.
- Route matching and generation casing: Distinguish case-insensitive matching of incoming URLs from URL generation by LinkGenerator. Explain that LinkGenerator normally preserves the casing used in the route template when choosing the generated path.
Why it matters: A route can accept several casing variations from clients, but generated links need one deliberate, consistent representation. - Global RouteOptions conventions: Describe how to configure RouteOptions globally through WebApplicationBuilder.Services using Configure<T>. State that RouteOptions can force generated paths to lowercase, optionally lowercase query strings, and append a trailing slash; path lowercasing includes route-parameter segments.
Why it matters: Global conventions keep generated links consistent even when route templates were written inconsistently. - Per-link LinkOptions overrides: Explain that an optional LinkOptions argument passed to LinkGenerator methods overrides the app-wide RouteOptions defaults for that individual generated link. Describe this as useful when a specific link must follow a legacy API convention that differs from the application's normal URL style.
Why it matters: Per-link overrides let an application retain consistent defaults while still interoperating with exceptional or legacy URL formats.
Key terms: routing, LinkGenerator, route template, case-insensitive comparison, RouteOptions, Configure<T>, WebApplicationBuilder.Services, LowercaseUrls, LowercaseQueryStrings, AppendTrailingSlash
6.5 Summary
This summary recaps how ASP.NET Core routing matches request URLs to endpoints and generates maintainable URLs from endpoint routes.
Where this is used later
- Routing in ASP.NET Core (chapter 14) · Reuses the same routing concepts for Razor Pages.
- Routing requests to Razor Pages (chapter 14) · Razor Pages routing applies the same handler-selection concept to pages.
- Attribute routing: Linking action methods to URLs (chapter 20) · Attribute routing connects controller action methods to URL patterns.
- Binding simple types to a request (chapter 7) · Model binding extracts simple request values, including query-string values, after handler selection.
- Convention-based routing vs. explicit routing (chapter 14) · The comparison of convention-based and explicit routing relies on the distinction between file-oriented and explicitly configured URLs.
- Customizing Razor Page route templates (chapter 14) · Razor Page route templates are customized independently of page locations.
- (chapter intro) (chapter 14) · The general purpose of routing in ASP.NET Core.
- Choosing a binding source (chapter 7) · Minimal API request handling relies on the endpoint selected by routing.
Concepts explained in this chapter
- route dataRoute data is a collection of named values supplied to an endpoint route during URL generation.
- routingRouting is the mechanism that maps incoming requests to application endpoints or handlers.
- route templateA route template is a URL pattern containing fixed values and optional placeholders that determines which request URLs an endpoint matches.
- endpoint middlewareEndpoint middleware is the ASP.NET Core middleware component that executes the endpoint selected for an incoming request.
- LinkGeneratorLinkGenerator is the ASP.NET Core service that generates URL paths and URLs from route information.
- route parameterA route parameter is a named variable embedded in a URL pattern whose value is extracted from a matching request path.
- route constraintA route constraint is a rule attached to a route parameter that determines whether a URL value satisfies the requirements for matching a route template.
- routing middlewareUseRouting is an ASP.NET Core extension method that adds routing middleware to a web application's request pipeline.
- endpointAn endpoint is an addressable application operation associated with a URL pattern that receives a dispatched request and returns a response.
- IEndpointRouteBuilderIEndpointRouteBuilder is the ASP.NET Core interface for registering route endpoints and creating endpoint-specific application builders.
- endpoint routingEndpoint routing is the ASP.NET Core routing system that separates request endpoint selection from endpoint execution in middleware.
- RouteOptionsRouteOptions is an ASP.NET Core options class that configures default rules for generated route URLs, including casing and trailing slashes.
- handlerA handler is an application component that receives a framework-dispatched request or event and performs the corresponding processing.
- overlapping route templateAn overlapping route template is a route template whose matching rules also match one or more other route templates for at least one URL.
- default valueA default parameter value is a value specified in a method signature that is supplied when an argument is omitted.
- url generationURL generation is the process of constructing endpoint URLs from routing metadata and route parameter values.
- WithNameWithName is an ASP.NET Core endpoint-mapping method that assigns a name to an endpoint as metadata.
- optional function argumentAn optional parameter is a handler or method parameter that may receive no corresponding input and instead accept a null or default value.
- 302 foundThe 302 status code is an HTTP response status that temporarily directs a client to retrieve a resource from another location.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
