@code {
[Parameter]
public string? Id { get; set; }
}
```
**How it works:**
- `@page` directive makes component routable
- Parameter name in URL (`{id}`) must match parameter name in `@code` block
- Multiple `@page` directives supported (same component, multiple routes)
### Route Parameters
```csharp
@page "/product/{id}"
@code {
private string? searchQuery;
protected override void OnInitialized()
{
var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
searchQuery = query["q"];
}
}
```
**Usage:** `/search?q=blazor` → `searchQuery = "blazor"`
### Building Query Strings
```csharp
private void Search(string term)
{
Navigation.NavigateTo($"/search?q={Uri.EscapeDataString(term)}");
}
// Or use QueryHelpers (in .NET 6+)
var query = new Dictionary
{
{ "q", "blazor" },
{ "page", "1" }
};
var url = NavigationManager.GetUriWithQueryParameters("/search", query);
Navigation.NavigateTo(url);
```
### Multiple Query Parameters
```csharp
var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
var category = query["category"];
var page = int.TryParse(query["page"], out var p) ? p : 1;
var sort = query["sort"] ?? "name";
```
**Usage:** `/products?category=electronics&page=2&sort=price`
## Router Configuration
The Router component in `App.razor` configures routing:
```csharp
@pageTitle
Page not found
@code {
private List? additionalAssemblies;
private string pageTitle = "Loading...";
protected override async Task OnInitializedAsync()
{
// Load assemblies dynamically if needed
additionalAssemblies = new List
{
typeof(SomeOtherAssembly).Assembly
};
}
private async Task OnNavigateAsync(NavigationContext context)
{
// Can be used for lazy loading assemblies
// Not commonly needed
}
}
```
## Layouts
Layouts are parent components that wrap pages.
### Define a Layout
```csharp
@inherits LayoutComponentBase
@Header@Body
@code {
[Parameter]
public RenderFragment? Header { get; set; }
[Parameter]
public RenderFragment? Navigation { get; set; }
[Parameter]
public RenderFragment? Body { get; set; }
[Parameter]
public RenderFragment? Footer { get; set; }
}
```
### Apply Layout to Page
```csharp
@page "/products"
@layout MainLayout
Products
```
### Apply Layout to Multiple Pages
```csharp
@layout MainLayout
```
Add this line to `_Imports.razor` to apply layout to all components in folder and below.
### Nested Layouts
```csharp
@inherits MainLayout
@Body
```
## Page Titles
Update page title (browser tab) dynamically:
```csharp
@page "/products/{id}"
@inject NavigationManager Navigation
@title
@title
@code {
[Parameter]
public string? id { get; set; }
private string? title;
protected override async Task OnParametersSetAsync()
{
title = await LoadProductTitleAsync(id);
}
private async Task LoadProductTitleAsync(string? id)
{
// Load from service
return $"Product {id}";
}
}
```
## Common Routing Patterns
### Master-Detail Pattern
```csharp
@page "/products"
@page "/products/{id}"
```
---
**Related Resources:** See [components-lifecycle.md](components-lifecycle.md) for parameter handling. See [authentication-authorization.md](authentication-authorization.md) for route authorization.