Appearance
Are you an LLM? You can read better optimized documentation at /reference/routing.md for this page in Markdown format
Routing reference
This document provides a complete technical reference for the URL routing implementation in TheExampleApp. It covers how incoming requests are mapped to Razor Pages, the conventions used for defining routes, and the role of query parameters in modifying application behavior.
The application is built on ASP.NET Core 2.1 and primarily uses the Razor Pages framework. Routing is configured in the Startup.cs file.
URL routing
The application's routing is a combination of convention-based routing inherent to Razor Pages and explicit route definitions. While Razor Pages typically map URLs directly to the file path under the /Pages directory, this application uses custom conventions to create more user-friendly and SEO-optimized URLs.
The primary configuration for these custom routes is located in the ConfigureServices method within Startup.cs. Additionally, URL rewriting and redirection rules are defined in the Configure method to handle specific edge cases and legacy URL patterns.
Page routes
The following table details the main application routes, the corresponding Razor Page that handles the request, and a description of its function.
| Route Pattern | Razor Page File | Description - |
|---|---|---|
/ | /Pages/Index.cshtml | The application home page. - |
/courses | /Pages/Courses.cshtml | Displays a list of all available courses. Also serves as the base page for category filtering. - |
/courses/categories/{category?} | /Pages/Courses.cshtml | Filters the course list by a specific category slug. The {category} segment is optional. If present, the OnGet method in Courses.cshtml.cs filters the courses fetched from Contentful. If the category is not found, it returns a 404 error. - |
/courses/{slug}/lessons | /Pages/Courses/Index.cshtml | Note: This route is redirected by the rewrite rule (see below) to /courses/{slug} before reaching the routing system. The effective route pattern is /courses/{slug}, which displays the overview page for a specific course. The OnGet method in Courses/Index.cshtml.cs fetches the course from Contentful using the provided slug with an include depth of 5 levels. The locale is determined from the user's session or current culture. Returns a 404 if the course is not found. The page also tracks visited lessons in session state and updates breadcrumb navigation by replacing the slug-based label with the course title. - |
/courses/{slug}/lessons/{lessonSlug} | /Pages/Courses/Lessons.cshtml | Displays a specific lesson within a course. The OnGet method in Courses/Lessons.cshtml.cs takes both a course {slug} and a {lessonSlug}. It first fetches the course and then finds the matching lesson within that course's lesson collection. It returns a 404 if either the course or the lesson is not found. - |
/settings | /Pages/Settings.cshtml | A page for configuring Contentful API credentials, including space ID, delivery API key, and preview API key. The page provides multiple handlers: OnGet displays the settings form, OnPost validates and saves credentials to session, OnPostResetCredentials clears custom credentials to restore defaults, and OnPostSwitchApi toggles between preview and delivery APIs. Settings are validated against the Contentful API before being saved. The page also manages editorial features toggle state via session. - |
/imprint | /Pages/Imprint.cshtml | A static page for legal information (Impressum). - |
Route conventions
The application deviates from the standard file-based routing of Razor Pages by defining explicit route mappings. This is achieved using AddPageRoute and URL rewriting. For more information on the underlying framework, see the Razor Pages documentation.
AddPageRoute Configuration
The core of the routing logic is defined in Startup.cs using options.Conventions.AddPageRoute. This method maps a custom URL route to a specific Razor Page file. This allows for clean, hierarchical URLs that are decoupled from the physical file structure.
csharp
// File: TheExampleApp/Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// ... other services
services.AddMvc().AddRazorPagesOptions(
options => {
// Maps /courses/categories/{category?} to the /Pages/Courses.cshtml page
options.Conventions.AddPageRoute("/Courses", "Courses/Categories/{category?}");
// Maps /courses/{slug}/lessons to the /Pages/Courses/Index.cshtml page
options.Conventions.AddPageRoute("/Courses/Index", "Courses/{slug}/lessons");
// Maps /courses/{slug}/lessons/{lessonSlug} to the /Pages/Courses/Lessons.cshtml page
options.Conventions.AddPageRoute("/Courses/Lessons", "Courses/{slug}/lessons/{lessonSlug}");
});
// ... other services
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Key Mappings:
AddPageRoute("/Courses", "Courses/Categories/{category?}"): This maps the URL/courses/categories/(with an optional category) to the/Pages/Courses.cshtmlpage. This allows a single page model to handle both the general course listing and the filtered category view.AddPageRoute("/Courses/Index", "Courses/{slug}/lessons"): This maps the URL for a course overview,/courses/{slug}/lessons, to the/Pages/Courses/Index.cshtmlpage. This is a non-intuitive mapping, so developers should be aware thatCourses/Index.cshtmlis not the course listing, but the individual course overview.AddPageRoute("/Courses/Lessons", "Courses/{slug}/lessons/{lessonSlug}"): This maps the URL for a specific lesson view to the/Pages/Courses/Lessons.cshtmlpage, which is a more direct mapping.
Custom Routing and Redirection
A URL rewrite rule is configured in Startup.cs to handle a specific navigation case.
csharp
// File: TheExampleApp/Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var options = new RewriteOptions();
// ... other rules
// Redirects any URL ending in /lessons to its parent URL.
// Example: /courses/hello-world/lessons -> /courses/hello-world
options.AddRedirect("courses/(.*)/lessons$", "/courses/$1");
app.UseRewriter(options);
// ... other middleware
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
This rule uses a regular expression to catch requests for URLs like /courses/some-course-slug/lessons and issues a permanent (301) redirect to /courses/some-course-slug. The redirect removes the trailing /lessons segment to provide a cleaner, canonical URL for accessing course overview pages.
Developer Note: The redirect rule executes during the URL rewriting phase, which occurs before route matching. When a user navigates to
/courses/{slug}/lessons, the redirect transforms it to/courses/{slug}before the routing system processes it. Therefore, theAddPageRoutemapping for/courses/{slug}/lessonsbecomes unreachable in practice. The actual working route is/courses/{slug}, which is handled by/Pages/Courses/Index.cshtmlthrough ASP.NET Core's default Razor Pages file-based routing convention (where a page at/Pages/Courses/Index.cshtmlautomatically responds to/courses/{slug}by treating the slug as a route parameter).
Query parameters
Query parameters are used to control application state that is not part of the primary resource path, such as localization, API environment, and feature flags. This state is typically managed via the user's session.
| Parameter | Description