Chapter 14: Mapping URLs to Razor Pages using routing
This chapter introduces how ASP.NET Core routing selects Razor Pages, how their routes can be customized, and how URLs can be generated for them.
After this chapter you will be able to
- Routing role in Razor Pages. Explain that routing selects the Razor Page to handle an incoming request and connects the middleware pipeline to Razor Pages and the MVC framework.
- Two-stage endpoint routing. Explain the two middleware stages of endpoint routing: RoutingMiddleware selects an endpoint for an incoming request, and EndpointMiddleware executes the selected endpoint.
- Razor Pages endpoint registration. Describe how MapRazorPages() registers all Razor Pages as endpoints when the application starts, alongside other endpoint types such as minimal APIs and MVC controllers.
- Routing style distinctions. Distinguish convention-based routing from explicit routing in ASP.NET Core, including how each maps URLs to endpoints.
- Explicit routing recommendation. Justify why the section recommends explicit routing for most applications, including APIs and Razor Pages or MVC-controller applications.
- Razor Pages routing model. Describe how Razor Pages combine conventions with explicit routing: conventions generate an explicit route template for each page, and that template can be changed page by page.
- Convention-derived Razor Page routes. Explain how calling MapRazorPages() creates a route template for every Razor Page at application startup. Describe how the template comes from the page's path relative to the Pages root, with the .cshtml extension removed.
- Request routing and handler execution. Trace what happens after a request such as /products/view matches a Razor Page route: RoutingMiddleware selects the Razor Page endpoint, and EndpointMiddleware executes a handler on an instance of its PageModel. Distinguish selecting a Razor Page from selecting one of that page's possible handlers.
- Razor Page route customization. Explain that a Razor Page route template normally comes from its file path, but can be customized or completely replaced for an individual page.
- Appended Razor Page segments. Describe how to append an extra segment to a Razor Page route template by placing a route template after the @page directive. State that the @page directive must be the first content in the .cshtml file and that the added template is appended to the page’s convention-based default route.
- Route parameters on pages. Explain that appended route segments commonly contain route parameters, allowing one Razor Page to match URLs such as Products/{category}/{name}. Describe that Razor Pages can use the same optional parameters, default values, and constraints available in ASP.NET Core routing.
- Absolute custom route templates. Describe how prefixing a Razor Page route template with / in the @page directive creates an absolute custom route instead of adding segments to the convention-based route. Explain that the resulting template applies regardless of the page’s location in the Pages folder.
- Default route replacement. State that customizing a Razor Page route with the @page directive replaces its default convention-based template, so the former default URL no longer reaches that page. Distinguish replacement from adding additional routes, which is addressed later with Razor Pages conventions.
- Routing-based URL generation. Explain why Razor Pages should generate URLs through the routing infrastructure instead of hard-coding them in HTML or HTTP responses. Relate this to preventing broken links when convention-based routes change.
- IUrlHelper Page URL generation. Describe how the PageModel's Url property exposes IUrlHelper and how calling its Page() method generates a URL for a referenced Razor Page from that page's route template.
- Page paths and route values. Explain that Page() accepts a relative page path or an absolute path starting with '/' relative to the Pages folder, plus an anonymous object of route values. Describe that a value matching a route parameter is placed in the URL path, while an unmatched value is appended to the query string.
- MVC action URL generation. Describe how to generate a URL to an MVC action by calling IUrlHelper.Action with an action name and controller name, rather than a Razor Page path.
- Destination-based helper selection. Distinguish when to use IUrlHelper.Page and when to use IUrlHelper.Action: choose Page() for a Razor Page destination and Action() for an MVC action destination, regardless of whether the calling code is in a Razor Page or controller.
- LinkGenerator scope and requirements. Explain that LinkGenerator can be used anywhere in an ASP.NET Core application, unlike IUrlHelper, which should be used only in the context of a request. Describe how LinkGenerator requires enough arguments to uniquely identify the URL, making it more verbose but more consistent.
- Frontend knowledge in business logic. Justify keeping URLs and other knowledge of frontend application design out of business and domain logic where possible. Explain that this separation lets business logic be reused or changed independently, such as when the same logic is used by a mobile application.
- Background URL generation. Describe the case for injecting and using LinkGenerator when code outside a request genuinely must create an application link, such as a background service composing an email. State that its generated URL automatically follows route changes, but that missing required route values or an incorrect path can produce null.
- Global URL formatting conventions. Describe how RouteOptions can globally lowercase generated URLs and append trailing slashes, and how a custom parameter transformer can convert PascalCase route values to kebab-case.
- Custom route model conventions. Describe how an IPageRouteModelConvention can rewrite or add route templates for all Razor Pages, such as adding a fixed "page" prefix, and that it is registered as a Razor Pages convention.
- Convention-first route design. Justify relying on Razor Pages file-based conventions and global conventions where possible: add route parameters with @page when routes must be dynamic, but avoid absolute replacement paths, literal segments, and unnecessary extra routes because overlapping templates cause runtime ambiguity exceptions.
What it builds on
- Combining middleware in a pipeline (chapter 4) · The middleware pipeline that processes requests.
- What is routing? (chapter 6) · The general purpose of routing in ASP.NET Core.
- Applying the MVC design pattern to Razor Pages (chapter 13) · How Razor Pages participate in the MVC-style request flow.
- Exploring the route template syntax (chapter 6) · Route-template syntax and features.
- Generating URLs from route parameters (chapter 6) · Generating URLs from route parameters.
- Endpoint routing in ASP.NET Core (chapter 6) · The endpoint-routing infrastructure and its two-step request-processing model.
- Adding and configuring services (chapter 13) · Adding and configuring the services needed by a Razor Pages application.
- Directing a request to a Razor Page and building a binding model (chapter 13) · The role of Razor Pages in directing a request to a page and building a binding model.
Section by section
Introduction
This chapter introduces how ASP.NET Core routing selects Razor Pages, how their routes can be customized, and how URLs can be generated for them.
- Routing role in Razor Pages: Explain that routing selects the Razor Page to handle an incoming request and connects the middleware pipeline to Razor Pages and the MVC framework.
Why it matters: Routing determines which page responds to a URL, so it is the link between an incoming request and the UI code that handles it. - Razor Page routing customization: Describe the chapter's routing customization options: default Razor Page routing, explicit route-template changes, and globally customized conventions such as lowercase URLs.
Why it matters: These options let an application control the public URLs that lead to its Razor Pages. - Razor Page URL generation: Describe that routing can generate URLs for Razor Pages, and that Razor Pages provide helper methods that simplify this compared with minimal APIs.
Why it matters: Generating URLs through routing avoids treating links as unrelated hard-coded strings and uses Razor Pages-specific helpers.
Key terms: routing, Razor Pages, middleware pipeline, MVC framework, endpoint routing, default routing behavior, route templates, explicit route templates, conventions, Razor Pages conventions
14.1 Routing in ASP.NET Core
This section explains how ASP.NET Core endpoint routing registers Razor Page endpoints, selects a matching endpoint for each request, and then executes it.
- Two-stage endpoint routing: Explain the two middleware stages of endpoint routing: RoutingMiddleware selects an endpoint for an incoming request, and EndpointMiddleware executes the selected endpoint.
Why it matters: Understanding the split lets you see how ASP.NET Core decides what should handle a URL before it runs that handler. - Razor Pages endpoint registration: Describe how MapRazorPages() registers all Razor Pages as endpoints when the application starts, alongside other endpoint types such as minimal APIs and MVC controllers.
Why it matters: Registering Razor Pages makes their routes available for endpoint routing to match at runtime. - Route template matching: Describe how every endpoint has a route template defining the URLs it matches, how EndpointMiddleware stores templates and endpoints in a shared dictionary, and how RoutingMiddleware uses that information to select a match.
Why it matters: Route templates are the link between a requested URL and the endpoint that should handle it. - Endpoint-aware middleware placement: Explain that middleware placed after RoutingMiddleware can inspect the endpoint selected for the request before EndpointMiddleware executes it, which enables scenarios such as authorization.
Why it matters: This ordering is why middleware such as authorization can make decisions based on the destination endpoint before its code runs.
Key terms: RoutingMiddleware, EndpointMiddleware, endpoint routing, endpoint, MapRazorPages(), Razor Pages, endpoints, route template, URL, dictionary
14.2 Convention-based routing vs. explicit routing
This section contrasts global convention-based routing with endpoint-specific explicit routing and recommends explicit routing, including Razor Pages' convention-generated explicit routes, for most applications.
- Routing style distinctions: Distinguish convention-based routing from explicit routing in ASP.NET Core, including how each maps URLs to endpoints.
Why it matters: Choosing a routing style determines how easily you can understand and customize an application's URLs. - Explicit routing recommendation: Justify why the section recommends explicit routing for most applications, including APIs and Razor Pages or MVC-controller applications.
Why it matters: The recommendation helps you select a consistent routing approach that remains practical when URLs need customization. - Razor Pages routing model: Describe how Razor Pages combine conventions with explicit routing: conventions generate an explicit route template for each page, and that template can be changed page by page.
Why it matters: This model gives Razor Pages predictable default URLs without making unusual URLs difficult to customize.
Key terms: convention-based routing, explicit routing, route template, endpoint, attribute routing, [Route], minimal APIs, MVC controllers, Razor Pages, conventions
14.3 Routing requests to Razor Pages
This section explains how ASP.NET Core conventionally derives routes from Razor Page file paths and routes matching requests to their page handlers.
- Convention-derived Razor Page routes: Explain how calling MapRazorPages() creates a route template for every Razor Page at application startup. Describe how the template comes from the page's path relative to the Pages root, with the .cshtml extension removed.
Why it matters: These conventions let a website acquire predictable URLs without manually declaring a route for every page. - Request routing and handler execution: Trace what happens after a request such as /products/view matches a Razor Page route: RoutingMiddleware selects the Razor Page endpoint, and EndpointMiddleware executes a handler on an instance of its PageModel. Distinguish selecting a Razor Page from selecting one of that page's possible handlers.
Why it matters: A matched URL chooses a page first, while handler selection is a separate step needed to understand Razor Page request processing. - Index page route aliases: Describe the special default routing rule for Index.cshtml pages: they create both a route ending in Index and a second route without that suffix. Explain that both routes select the same page and that a conflicting sibling page route can cause a runtime exception.
Why it matters: Index aliases provide convenient directory URLs, but they can accidentally create overlapping routes. - Case-insensitive route matching: State that Razor Page route matching is not case-sensitive, so URL casing need not exactly match the casing of the route template.
Why it matters: This explains why a request such as /products/view can match a template written as Products/View.
Key terms: MapRazorPages(), route template, Razor Pages root directory, Pages/, RoutingMiddleware, EndpointMiddleware, endpoint, PageModel, page handler, OnGet
14.4 Customizing Razor Page route templates
This section introduces customizing individual Razor Page route templates to control application URLs and map multiple URLs to one page.
- Razor Page route customization: Explain that a Razor Page route template normally comes from its file path, but can be customized or completely replaced for an individual page.
Why it matters: Custom routes let an application expose URLs that fit its intended design instead of being limited to page file paths. - Route template components: Describe route templates as combinations of literal segments and route parameters, and identify that default Razor Page URLs such as "ToDo/Index" consist of literal segments.
Why it matters: Recognizing the pieces of a route template makes it possible to understand the URL patterns customized in the following subsections. - Multiple URLs per page: Explain that customized routing can map multiple URLs to a single Razor Page.
Why it matters: This flexibility allows URL design to be separated from the physical organization of page files.
Key terms: Razor Page, route template, file path, literal segment, route parameter, map multiple URLs
14.4.1 Adding a segment to a Razor Page route template
This section shows how to append route segments, especially route parameters, to a Razor Page’s default URL by editing its @page directive.
- Appended Razor Page segments: Describe how to append an extra segment to a Razor Page route template by placing a route template after the @page directive. State that the @page directive must be the first content in the .cshtml file and that the added template is appended to the page’s convention-based default route.
Why it matters: Adding segments lets a page keep its conventional route while accepting a more useful URL shape. - Route parameters on pages: Explain that appended route segments commonly contain route parameters, allowing one Razor Page to match URLs such as Products/{category}/{name}. Describe that Razor Pages can use the same optional parameters, default values, and constraints available in ASP.NET Core routing.
Why it matters: Route parameters allow one page, such as a product page, to serve many resource-specific URLs.
Key terms: @page directive, route template, route segment, default route template, route parameter, optional parameters, default parameters, constraints, Products/{category}/{name}
14.4.2 Replacing a Razor Page route template completely
This section explains how a leading slash in a Razor Page @page directive completely replaces the convention-based route derived from the page’s location.
- Absolute custom route templates: Describe how prefixing a Razor Page route template with / in the @page directive creates an absolute custom route instead of adding segments to the convention-based route. Explain that the resulting template applies regardless of the page’s location in the Pages folder.
Why it matters: Absolute templates let you give important pages precise, location-independent public URLs. - Static checkout route: Explain how an @page directive containing a leading slash and only literal segments can give a page a fixed URL, such as the checkout route template matching /checkout.
Why it matters: A fixed, memorable URL is useful for prominent pages whose public address should not reflect their file placement. - Default route replacement: State that customizing a Razor Page route with the @page directive replaces its default convention-based template, so the former default URL no longer reaches that page. Distinguish replacement from adding additional routes, which is addressed later with Razor Pages conventions.
Why it matters: Knowing that the original URL stops working prevents broken links and unexpected routing behavior after a route change.
Key terms: @page directive, custom route template, absolute route template, literal segments, route template, static custom template, checkout, default route template, Razor Pages conventions
14.5 Generating URLs for Razor Pages
This section introduces routing-based URL generation for Razor Pages and MVC so links remain correct when convention-based page URLs change.
- Routing-based URL generation: Explain why Razor Pages should generate URLs through the routing infrastructure instead of hard-coding them in HTML or HTTP responses. Relate this to preventing broken links when convention-based routes change.
Why it matters: Routing-generated links keep your application resilient when you reorganize or rename pages. - Convention-driven page URL changes: Describe how convention-based routing derives a Razor Page URL from its location and name, using the change from Pages/Cart.cshtml at /Cart to Pages/Basket/View.cshtml at /Basket/View as the example.
Why it matters: Understanding that page locations affect their URLs explains why generated links are safer than fixed path strings. - URL generation tools: State that Razor Page PageModel types provide IUrlHelper for generating Razor Page URLs, and that the LinkGenerator service can also generate URLs; describe MVC controller URL generation as virtually identical to the Razor Pages mechanism.
Why it matters: These tools let you create route-aware URLs across Razor Pages, MVC controllers, and the broader application.
Key terms: routing infrastructure, convention-based routing, Razor Pages, Pages/Cart.cshtml, Pages/Basket/View.cshtml, IUrlHelper, PageModel, LinkGenerator, MVC controllers
14.5.1 Generating URLs for a Razor Page
This section shows how Razor Pages and MVC code generate links to Razor Pages through IUrlHelper.Page using page paths and route values.
- IUrlHelper Page URL generation: Describe how the PageModel's Url property exposes IUrlHelper and how calling its Page() method generates a URL for a referenced Razor Page from that page's route template.
Why it matters: Generating a link from the page you want to run avoids hard-coding a URL that may change with its route. - Page paths and route values: Explain that Page() accepts a relative page path or an absolute path starting with '/' relative to the Pages folder, plus an anonymous object of route values. Describe that a value matching a route parameter is placed in the URL path, while an unmatched value is appended to the query string.
Why it matters: Passing route values lets generated links carry the values the target Razor Page needs without manually constructing path or query-string text. - Page method overloads: State that IUrlHelper provides Page() overloads for selecting a specific page handler, generating an absolute rather than relative URL, and supplying additional route values.
Why it matters: The overloads let a generated link target the needed handler and URL form rather than only the default page URL.
Key terms: IUrlHelper, Url, Page(), PageModel, route template, Razor Page, relative file path, absolute file path, Pages folder, route values
14.5.2 Generating URLs for an MVC controller
This section explains how MVC controllers generate URLs with IUrlHelper and how helper choice, ambient route values, and LinkGenerator affect URL generation.
- MVC action URL generation: Describe how to generate a URL to an MVC action by calling IUrlHelper.Action with an action name and controller name, rather than a Razor Page path.
Why it matters: Correct URL generation lets controller actions link to other application destinations without hard-coding URL strings. - Destination-based helper selection: Distinguish when to use IUrlHelper.Page and when to use IUrlHelper.Action: choose Page() for a Razor Page destination and Action() for an MVC action destination, regardless of whether the calling code is in a Razor Page or controller.
Why it matters: The destination type, not the source of the link, determines the correct URL-generation helper. - Ambient route value reuse: Explain that IUrlHelper can reuse ambient values—route values from the current request—and that Action() can omit the controller name for an action in the same controller because supplied values override ambient values.
Why it matters: Ambient values reduce repeated route information but can make identical helper arguments produce different URLs in different request contexts. - Refactor-safe action names: State that nameof can be used instead of a string literal for an action method name, such as nameof(View), so URL-generation code is safer when methods are renamed.
Why it matters: Using nameof avoids leaving stale string-based action names behind after refactoring.
Key terms: IUrlHelper, Action(), controller name, action name, Url helper, Page(), Razor Page, MVC action, ambient values, route values
14.5.3 Generating URLs with LinkGenerator
This section explains when and why to use LinkGenerator to generate Razor Pages and MVC URLs, especially from application code outside an HTTP request.
- LinkGenerator scope and requirements: Explain that LinkGenerator can be used anywhere in an ASP.NET Core application, unlike IUrlHelper, which should be used only in the context of a request. Describe how LinkGenerator requires enough arguments to uniquely identify the URL, making it more verbose but more consistent.
Why it matters: This distinction helps you choose a URL-generation service that works in the code location where you need it. - Frontend knowledge in business logic: Justify keeping URLs and other knowledge of frontend application design out of business and domain logic where possible. Explain that this separation lets business logic be reused or changed independently, such as when the same logic is used by a mobile application.
Why it matters: Keeping domain code independent of web URLs makes the application easier to evolve and reuse outside its current frontend. - Background URL generation: Describe the case for injecting and using LinkGenerator when code outside a request genuinely must create an application link, such as a background service composing an email. State that its generated URL automatically follows route changes, but that missing required route values or an incorrect path can produce null.
Why it matters: This lets non-request code send correct application links without hard-coding routes that may later change.
Key terms: LinkGenerator, IUrlHelper, request context, business logic, domain logic, frontend application design, Dependency Inversion principle, background service, GetPathByPage(), GetPathByAction()
14.6 Customizing conventions with Razor Pages
This section explains how to customize Razor Pages routing conventions globally while preserving convention-based URLs and avoiding ambiguous routes.
- Global URL formatting conventions: Describe how RouteOptions can globally lowercase generated URLs and append trailing slashes, and how a custom parameter transformer can convert PascalCase route values to kebab-case.
Why it matters: Global formatting conventions give an application consistent, human-friendly URLs without editing every page. - Razor Pages options registration: Explain that AddRazorPagesOptions(), chained after AddRazorPages() in Program.cs, configures Razor Pages conventions, including registering a parameter transformer and other page-route conventions.
Why it matters: Knowing the configuration point lets you apply route behavior consistently instead of configuring pages one at a time. - Alternative page route templates: Explain that AddPageRoute() adds an additional route template for one Razor Page rather than replacing that page's default route template.
Why it matters: Extra routes can be useful, but they also create multiple URLs for the same page and can make an application harder to understand. - Custom route model conventions: Describe how an IPageRouteModelConvention can rewrite or add route templates for all Razor Pages, such as adding a fixed "page" prefix, and that it is registered as a Razor Pages convention.
Why it matters: A custom route-model convention provides centralized control when every page needs a common URL rule or multiple localized routes. - Convention-first route design: Justify relying on Razor Pages file-based conventions and global conventions where possible: add route parameters with @page when routes must be dynamic, but avoid absolute replacement paths, literal segments, and unnecessary extra routes because overlapping templates cause runtime ambiguity exceptions.
Why it matters: Sticking to conventions keeps URLs predictable and prevents requests from matching multiple Razor Pages at runtime.
Key terms: RouteOptions, LowercaseUrls, AppendTrailingSlash, parameter transformer, kebab-case, AddRazorPages, AddRazorPagesOptions, RazorPagesOptions, Program.cs, AddPageRoute
14.7 Summary
Summarizes how Razor Pages map URLs through convention-generated routes, how those routes can be customized, and how URLs can be generated and configured.
Where this is used later
- Generating links with the Anchor Tag Helper (chapter 18) · The Anchor Tag Helper generates links in Razor Pages views.
- Authorization in ASP.NET Core (chapter 24) · Authorization can inspect the endpoint selected by routing before that endpoint executes.
- Choosing between Razor Pages and MVC controllers (chapter 19) · Choosing Razor Pages or MVC controllers for websites informs the routing approach.
- Razor Pages and page handlers (chapter 15) · Page handlers are the units of Razor Pages behavior that execute after a page is selected.
- Selecting a page handler to invoke (chapter 15) · The later section explains how the framework chooses among multiple handlers on the selected page.
- Accepting parameters to page handlers (chapter 15) · Page handlers accept values supplied by route parameters.
- Choosing a binding source (chapter 16) · Binding models can obtain values from route data.
- The Form Tag Helper (chapter 18) · URL generation for Razor Pages and routes.
Concepts explained in this chapter
- route templateA route template is a URL pattern containing fixed values and optional placeholders that determines which request URLs an endpoint matches.
- Razor PagesA Razor Page is an independently addressable ASP.NET Core page endpoint typically composed of a .cshtml view file and an associated PageModel class.
- routingRouting is the mechanism that maps incoming requests to application endpoints or handlers.
- route conventionA Razor Pages convention is a framework rule that derives or configures page behavior and routes from application structure or centralized settings.
- 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.
- AddRazorPagesOptionsAddRazorPagesOptions is an ASP.NET Core extension method that configures Razor Pages options and conventions during service registration.
- IUrlHelperIUrlHelper is an ASP.NET Core interface that provides methods for generating URLs from routing information within web application components.
- url generationURL generation is the process of constructing endpoint URLs from routing metadata and route parameter values.
- source generatorA source generator is a compiler extension that inspects program code during compilation and emits additional source files included in that compilation.
- AddPageRouteAddPageRoute is a Razor Pages configuration method that associates an additional route template with a specified page.
- IPageRouteModelConventionIPageRouteModelConvention is an ASP.NET Core interface for modifying route templates and route metadata while Razor Page models are being constructed.
- parameter transformerA parameter transformer is a routing component that transforms route parameter or token text when generating route templates or URLs.
- explicit routingAttribute routing is ASP.NET Core routing in which route templates are declared directly on controller classes and action methods through attributes.
- LinkGeneratorLinkGenerator is the ASP.NET Core service that generates URL paths and URLs from route information.
- MapRazorPagesMapRazorPages is an ASP.NET Core endpoint-mapping method that registers endpoints for an application's Razor Pages.
- endpoint middlewareEndpoint middleware is the ASP.NET Core middleware component that executes the endpoint selected for an incoming request.
- routing middlewareUseRouting is an ASP.NET Core extension method that adds routing middleware to a web application's request pipeline.
- page directiveThe @page directive is a Razor directive that marks a .cshtml file as a routable Razor Page.
- handlerA handler is an application component that receives a framework-dispatched request or event and performs the corresponding processing.
- route parameterA route parameter is a named variable embedded in a URL pattern whose value is extracted from a matching request path.
- endpoint routingEndpoint routing is the ASP.NET Core routing system that separates request endpoint selection from endpoint execution in middleware.
- endpointAn endpoint is an addressable application operation associated with a URL pattern that receives a dispatched request and returns a response.
- middlewareMiddleware is a request-processing component that can inspect, modify, or handle HTTP requests and responses within an ASP.NET Core pipeline.
- PageModelA PageModel code-behind file is the C# source file containing the handler methods and state for a Razor Page.
- pages folderThe Pages folder is the application directory containing Razor Pages files that define independently addressable web pages.
- RouteOptionsRouteOptions is an ASP.NET Core options class that configures default rules for generated route URLs, including casing and trailing slashes.
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.
