Hur Blazor matchar URL:er till komponenter, hur rutter tar parametrar, och hur du strukturerar app-skalet med layouter och NavMenu.
En komponent blir en sida genom att deklarera en eller flera @page-rutter högst upp:
@page "/"
@page "/home"
<h1>Välkommen!</h1>
Routern (definierad i Routes.razor) skannar projektet efter alla komponenter med @page och bygger upp tabellen automatiskt.
@page "/products/{Id:int}"
<h1>Produkt @Id</h1>
@code {
[Parameter] public int Id { get; set; }
}
| Constraint | Matchar |
|---|---|
{Id:int} | Heltal |
{Slug} | Sträng (default) — se förklaring nedan |
{Date:datetime} | DateTime |
{Active:bool} | true/false |
{Id:guid} | Guid |
{*Path} | Catch-all (allt återstående) |
En slug är en URL-vänlig version av en text — vanligtvis en titel. Ordet kommer från tidningsbranschen där en "slug" var ett kortnamn för en artikel.
I webbutveckling innebär det att du tar en läsbar text, gör om den till gemener, ersätter mellanslag med bindestreck och tar bort specialtecken:
| Original | Slug |
|---|---|
| Introduktion till Blazor | introduktion-till-blazor |
| Vad är en Route Parameter? | vad-ar-en-route-parameter |
| Tips & Tricks 2026 | tips-tricks-2026 |
Slugs används i stället för siffror när URL:en ska vara läsbar och SEO-vänlig:
/blogg/42 — ett ID, säger ingenting om innehållet/blogg/introduktion-till-blazor — en slug, läsbar och beskrivandeI Blazor är en slug-parameter bara en vanlig string-parameter utan constraint — därav "(default)" i tabellen. Du genererar och lagrar slugen själv i din modell.
@page "/blogg/{Slug}"
<h1>@artikel?.Titel</h1>
<p>@artikel?.Innehall</p>
@code {
[Parameter] public string Slug { get; set; } = "";
private Artikel? artikel;
protected override void OnParametersSet()
{
// Hitta artikeln vars slug matchar URL-segmentet
artikel = artikelService.HittaSlug(Slug);
if (artikel is null) Nav.NotFound();
}
}
@page "/search"
<p>Söker efter: @Query (sida @Page)</p>
@code {
[Parameter, SupplyParameterFromQuery] public string? Query { get; set; }
[Parameter, SupplyParameterFromQuery(Name = "p")] public int Page { get; set; } = 1;
}
URL: /search?Query=blazor&p=2 ger Query="blazor", Page=2.
@inject NavigationManager Nav
<button @onclick="GoToProduct">Gå till produkt 42</button>
@code {
private void GoToProduct()
=> Nav.NavigateTo("/products/42");
protected override void OnInitialized()
{
// Lyssna på navigationsändringar
Nav.LocationChanged += (sender, args) =>
{
Console.WriteLine($"Navigerade till {args.Location}");
};
}
}
NavigateTo(url) — NavigeraNavigateTo(url, forceLoad: true) — Full reload (hoppa ur SPA)ToAbsoluteUri("/path") — Få en komplett URLUri — Aktuell URL<NavLink href="/" Match="NavLinkMatch.All">Start</NavLink>
<NavLink href="/products">Produkter</NavLink>
<NavLink href="/about">Om</NavLink>
NavLink får CSS-klassen active när dess href matchar nuvarande URL. Match="NavLinkMatch.All" kräver exakt match (annars matchas alla som börjar med href).
En layout är en speciell komponent som ärver från LayoutComponentBase och innehåller @Body där sidans innehåll ska renderas.
@* Components/Layout/MainLayout.razor *@
@inherits LayoutComponentBase
<div class="app">
<header>
<h1>Min Blazor-app</h1>
<NavMenu />
</header>
<main>
@Body
</main>
<footer>© 2026 YH-kursen</footer>
</div>
@page "/print/{Id:int}"
@layout PrintLayout
<h1>Utskrift av order @Id</h1>
Du kan också sätta default-layout för en mapp via en _Imports.razor-fil:
@* Components/Pages/Admin/_Imports.razor *@
@layout AdminLayout
@* Components/Layout/NavMenu.razor *@
<nav class="sidebar">
<NavLink href="/" Match="NavLinkMatch.All">🏠 Start</NavLink>
<NavLink href="/products">📦 Produkter</NavLink>
<NavLink href="/orders">🧾 Ordrar</NavLink>
<NavLink href="/admin">⚙️ Admin</NavLink>
</nav>
I .NET 10 är 404-hanteringen helt omgjord. Det gamla <NotFound>-render fragmentet i Router är borttaget och fungerar inte längre. I stället pekar du Router på en hel komponent via NotFoundPage:
@* Routes.razor *@
<Router AppAssembly="@typeof(Program).Assembly"
NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
</Router>
@* Components/Pages/NotFound.razor *@
@page "/not-found"
<PageTitle>404</PageTitle>
<h1>404 — Sidan hittades inte</h1>
<p>Den begärda adressen finns inte.</p>
Och du kan trigga 404 från kod (t.ex. när en resurs inte finns):
@inject NavigationManager Nav
protected override async Task OnInitializedAsync()
{
product = await Api.GetAsync(Id);
if (product is null) Nav.NotFound(); // ny i .NET 10
}
Router.NotFoundPage ersätter <NotFound>-render fragment (det är borttaget).NavigationManager.NotFound() triggar 404-sidan från C#-kod.NavLinkMatch.All ignorerar numera query strings och fragment vid matchning (/products?sort=price matchar fortfarande /products).<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException> som default — NavigateTo kastar inte längre NavigationException.@page, parametrar och NavigationManager.Lös övningarna självständigt. Det finns inget facit — lärandet sker i processen.
/produkter/{id:int} som visar detaljer.
?q=...&sida=... och visar parametrarna. Lägg till en formulärknapp som ändrar URL via NavigationManager.
AdminLayout med annan färgsättning än MainLayout. Lägg minst en sida under /admin som använder den nya layouten.
NotFound-mallen så att den visar en bild, en länk tillbaka till startsidan och loggar den misslyckade URL:en i konsolen.
/blogg/{slug} som visar hela artikeln. Inkludera NavMenu och en custom 404-sida.
PublicLayout (header + footer), AdminLayout (sidebar + topbar) och PrintLayout (ingen kantbar, för utskrift). Sidor placeras under olika mappar som alla har egen layout-default.