On a single-page website, you change what the user sees by showing or hiding portions of the display that correspond to particular components, rather than going out to the server to get a new page. As users perform application tasks, they need to move between the different Razor Components that you have defined.
Download the example for a working example containing the code snippets in this guide.
Before creating a route, you should be familiar with the following:
Blazor Server was built on top of ASP.NET and Razor Pages. When you create a Blazor Server website, there will be a pre-configuration code at Startup.cs
. These are some routing pre-configuration codes for routing.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); }); }
We will go through line by line to analyze what is pre-configured. Starting at the first block:
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); }
This if statement will determine if we are in development environment or production environment and use the respective error page. You can find the error page at Pages/Error.cshtml
. the UseDeveloperExceptionPage
method is a built-in middleware to capture unhandled exceptions in detail. Detailed exception information should not be displayed publicly in the production environment for security reasons.
app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
The UseRouting
method to indicate that we will use default routing of ASP.NET. UseRouting
must be used with UseEndpoints
and are required by ASP.NET.
The MapBlazorHub
method is to open the default port for SignalR Core to interact with the frontend of Blazor Server.
The MapFallbackToPage
method to indicate the entry point of Blazor Server. The default entry point is located in Pages/_Host.cshtml
, you can change this entry point to another Razor Page. Whenever a requested url does not match any @page
directive, Blazor Server will redirect to the default entry point.
You can only use Razor Page as the entry point of Blazor Server website.
You can use @page
directive in a Razor Component to define a route to a component.
@page
directive always begins with a forward splash (/).@page
directives to have many routes.To define a route for a component, add a @page
directive to the directive section of the component.
@page "/simple-route" <h3>This is a simple page</h3>
In the example, we set the route host/simple-route
for the component. When the user navigates to that route, the component will be rendered.
Index.razor
component but you can move it to another component.MapFallbackToPage
to select the Razor Page.Often, as a user navigates your website, you want to pass information from one component to another. For example, consider a website that displays a list of books. Each book on the list has a unique id. To edit a book, users click the Edit button, which opens a EditBook
component. You want that component to retrieve the id for the book so it can display the right information to the user.
You can use a route to pass this type of information to your website components. To do so, you use the [Parameter]
attribute.
To get information from a route:
Type in route | Example data | Type in C# |
---|---|---|
bool | true , FALSE |
bool |
datetime | 2021-12-31 , 2021-12-31 8:40pm |
DateTime |
decimal | 99.99 , -1,00 |
decimal |
float | 1.234 , -1,001.01e8 |
float |
guid | CD2C1638-1638-72D5-1638-DEADBEEF1638 , {CD2C1638-1638-72D5-1638-DEADBEEF1638} |
Guid |
int | 123456789 , -123456789 |
int, Int32 |
long | 123456789 , -123456789 |
long, Int64 |
short | 123456789 , -123456789 |
short, Int16 |
double | 1.234 , -1,001.01e8 |
double, Double |
BlazorSchool, blazorschool.com | string, String |
@code{}
section with the matching type in C#. Example:@page "/route-parameters/{number:double}" <h3>Number: @Number</h3> @code{ [Parameter] public double Number { get; set; } }
A route can have multiple parameters with optional parameters, for optional parameters, add question mark (?) after the route type.
@page "/route-parameters/{number:double}/{firstName?}/{isGraduate:bool?}"
The {firstName?}
is to indicate that there will be an optional string FirstName
property. String is a special type in route parameter that does not have a route type. The {isGraduate:bool?}
is to indicate that there will be an optional bool IsGraduate
property.
When there is more than one optional parameter, the former must be provided before the latter. In the previous example, you could not fill IsGraduate
without filling FirstName
first.
The optional parameters must be the last parameter specified in the route.
There are several types of numbers, in some cultures, the decimal symbol are different. A common problem is the dot (.) symbol could be a decimal symbol, a file extension symbol or it can appears on string parameter. Blazor Server cannot distinguish between these. By default, Blazor Server will assume the dot symbol is a request for a file and will emit a 404 error. You have to tell Blazor Server that for this specific case, the dot is a part of parameter by going to Startup.cs
and modifying the Configure
method as follows.
app.UseEndpoints(endpoints => { ... endpoints.MapFallbackToPage("/route-parameters/{number:double}/{firstName?}/{isGraduate:bool?}","/_Host"); ... });
Blazor Server has a pre-built 404 page, and you can customize it. You can see the pre-built 404 page at App.razor
.
<NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>Sorry, there's nothing at this address.</p> </LayoutView> </NotFound>
Create a new component in Pages
folder called NotFound.razor
.
<h1>404 page not found.</h1>
Update the App.razor
to use the NotFound
component.
@using RoutingExample.Pages ... <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <NotFound></NotFound> </LayoutView> </NotFound> ...
<a>
tag or use <NavLink>
pre-built component.<NavLink>
component<NavLink>
, as the name suggested, is usually used in the navigation bar. <NavLink>
is a pre-built component that automatically toggling its 'active' class based on whether its href
matches the current URL. Refer to Navigation.razor
in our example.
@page "/navigation" <NavLink class="page-link" href="navigation">Link 1</NavLink>
This is a basic nav link example, it will render the following HTML.
<a href="navigation" class="page-link active">Link 1</a>
Declare a css style to toggling the <NavLink>
in site.css
.
.active-link { color: white; background-color: #7b3cc3 }
You cannot use isolated CSS for this .active-link
class because the rendered HTML has no scope attribute.
Add a parameter ActiveClass
to use the class with the <NavLink>
component.
<NavLink class="page-link" href="navigation" ActiveClass="active-link">Link 1</NavLink>
The following HTML is rendered.
<a href="navigation" class="page-link active-link">Link 1</a>
The link has now been highlighted because the current URL matches to the href
in <NavLink>
. Also, the active
class in the first rendered HTML has been changed to active-link
.
In some cases, you have a nested route like "host/navigation/link-2" and you want to highlight only the link of this particular route. This is where Matches
parameter comes in. Add another link to the example.
@page "/navigation" @page "/navigation/link-2" <NavLink class="page-link" href="navigation" ActiveClass="active-link">Link 1</NavLink> <NavLink class="page-link" href="navigation/link-2" ActiveClass="active-link">Link 2</NavLink>
When you navigate to "/navigation/link-2", you will see that 2 links are activated.
To activate only Link 2, you need to add Match
parameter to both <NavLink>
components. NavLinkMatch.All
is to indicate that the only link to the extractive URL will be highlighted.
<NavLink class="page-link" href="navigation" ActiveClass="active-link" Match="NavLinkMatch.All">Link 1</NavLink> <NavLink class="page-link" href="navigation/link-2" ActiveClass="active-link" Match="NavLinkMatch.All">Link 2</NavLink>
Navigate to "/navigation/link-2" and you will only see Link 2 activated.
Link 1 and Link 2 are siblings so highlighting both Link 1 and Link 2 is something you don't want to. But in some cases, you have parent and child links and you want to highlight the parent whenever a child is selected. Add Link 3, Link 3.1 and Link 3.2 to the example.
... @page "/navigation/link-3" @page "/navigation/link-3/child-1" @page "/navigation/link-3/child-2" ... <NavLink class="page-link" href="navigation/link-3" ActiveClass="active-link" Match="NavLinkMatch.Prefix">Link 3</NavLink> <NavLink class="page-link" href="navigation/link-3/child-1" ActiveClass="active-link" Match="NavLinkMatch.All">Link 3.1</NavLink> <NavLink class="page-link" href="navigation/link-3/child-2" ActiveClass="active-link" Match="NavLinkMatch.All">Link 3.2</NavLink>
Use the NavLinkMatch.Prefix
for the parent link and use NavLinkMatch.All
for the children. By using NavLinkMatch.Prefix
on the parent link you are telling <NavLink>
to highlight every URL that starts with "/navigation/link-3", that's including the "/navigation/link-3/child-1" and "/navigation/link-3/child-2".
NavigationManager
NavigationManager
is a good way to navigate to a page without user interaction with the UI. For example, if you want to redirect a user to a page in 5 seconds you will need to use NavigationManager
because the user will not interact with the UI.
To use NavigationManager, you need to inject it first. If you are in Razor Component, you can inject NavigationManager like this:
@inject NavigationManager NavigationManager
Or if you are in a service class, you can inject it as follows:
public class <Class Name> { private readonly NavigationManager _navigationManager; public <Class Name>(NavigationManager navigationManager) { _navigationManager = navigationManager; } }
NavigationManager
can redirect users to other pages inside the website or even outside the website.
In case of inside redirection, pass a related url to the first parameter, the second parameter indicates Blazor Server should make a reload in between. By default, Blazor Server does not reload page on navigating.
NavigationManager.NavigateTo("/", false);
In case of external redirection, pass an absolute url to the first parameter, the second parameter is useless in this case because you are leaving Blazor Server.
NavigationManager.NavigateTo("https://blazorschool.com", false);