Blazor поддерживает механизм маршрутизации, благодаря которому можно переходить от между страницам. Только в случае Blazor в качестве страниц выступают отдельные компоненты Blazor, которые устанавливают какое содержимое мы видим в браузере при переходе по определенному маршруту. Для определения маршрутизации в приложении Blazor нам нужны два элемента: компоненты, которые обрабатывают конкретные маршруты, и встроенный компонент Router из пространства имен "Microsoft.AspNetCore.Components.Routing", который собственно и позволяет выполнять маршрутизацию между компонентами.
Чтобы компонент мог участвовать в маршрутизации, в его коде должна быть определена директива @page, после которой идет обрабатываемый маршрут:
@page "маршрут"
КлассRouter
позволяет настроить маршрутизацию между подобными компонентами с помощью следующих свойств:
AppAssembly: представляет сборку, в которой будет идти поиск компонентов для сопоставления с маршрутами
AdditionalAssemblies: представляет коллекцию дополнительных сборок, где будет идти поиск компонентов для сопоставления с маршрутами
Found: представляет содержимое, которое отображается, если для определенного маршрута найден соответствующий компонент
NotFound: представляет содержимое, которое отображается, если для определенного маршрута НЕ найден соответствующий компонент
Navigating: представляет содержимое, которое отображается в процессе асинхронной навигации
OnNavigateAsync: представляет обработчик, который вызывается перед переходом на новую страницу
При определении компонента Router
необходимо прежде всего определить параметр AppAssembly - сборку, где искать компоненты, которые будут сопоставляться с маршрутами.
Когда приложение запускается впервые, роутер с помощью рефлексии просматривает сборки приложения (свойства AppAssembly и AdditionalAssemblies) на наличие любых маршрутизируемых компонентов.
Затем информацию о подобных компонентах сохраняется в таблице маршрутизации. И когда нажимается ссылка или навигация запускается программно,
роутер получает запрошенный маршрут и пытается найти соответствие в таблице маршрутизации. Если совпадение найдено, он загрузит содержимое из свойства Found
(обычно это компонент, который соответствует маршруту). Если совпадение не найдено, то загружается содержимое из свойства NotFound
.
Посмотрим на примере. Пусть у нас есть следующий проект с тремя компонентами
Компонент Home имеет следующий код:
@page "/" <h1>Home Page</h1>
То есть данный компонент будет сопоставляться с запросами по пути "/", то есть запросы к корню приложения.
В компоненте About определим следующий код:
@page "/about" <h1>About Page</h1>
Такой компонент будет сопоставляться с запросами по пути "/about".
Теперь определим главный компонент App:
@using Microsoft.AspNetCore.Components.Routing <!DOCTYPE html> <html> <head> <title>METANIT.COM</title> <meta charset="utf-8" /> <base href="/" /> <!-- для работы маршрутизации--> </head> <body> <Router AppAssembly="@typeof(Program).Assembly"> <Found> <p>Page Found</p> </Found> </Router> <script src="_framework/blazor.web.js"></script> </body> </html>
Чтобы передать компоненту Router текущую сборку, используется выражение @typeof(Program).Assembly
. То есть получаем тип класса Program, а затем его сборку.
В самом компоненте свойство-компонент Found определяет содержимое, отображаемое, если в приложении есть компонент для обработки текущего запроса. Мы можем запустить приложение и увидеть, что по запросам "/" и "/about" отображается содержимое компонента
Found
, а по всем остальным запросам отображается стандартное сообщение об ошибке:
Стоит отметить, что на веб-странице или на странице Razor, которая хостирует приложение, для корректной работы маршрутизации в пределах элемента <head>
необходимо указать тег <base>:
<head> <meta charset="utf-8" /> <title>METANIT.COM</title> <base href="/" /> <!-- для работы маршрутизации--> </head>
Хотя пример выше прекрасно работает, но было бы неплохо, если бы браузер отображал содержимое компонентов, которые сопоставляются с маршрутами. И для этого нам нужен
другой встроенный компонент - RouteView. Через свойство RouteData он принимает данные маршрутизации в виде одноименного
объекта RouteData
и на основании этих данных рендерит определенный компонент, который соответствует маршруту запроса. Так, изменим компонент App
следующим образом:
@using Microsoft.AspNetCore.Components.Routing <!DOCTYPE html> <html> <head> <title>METANIT.COM</title> <meta charset="utf-8" /> <base href="/" /> </head> <body> <Router AppAssembly="@typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> </Router> <script src="_framework/blazor.web.js"></script> </body> </html>
У компонента Found
устанавливается свойство Context
, которое представляет объект RouteData и привязано к переменной routeData
. И компонент
RouteView
через свойство RouteData
получает данные маршрутизации из переменной routeData. На основании этих данных RouteView будет использовать определенный компонент для установки содержимого.
Один компонент может сопоставляться с несколькими маршрутами. Например, изменим код компонента Home следующим образом:
@page "/" @page "/index" @page "/home" <h2>Home Page</h2>
Теперь компонент Home может сопоставляться с тремя маршрутами:
Если в приложении нет компонента, который мог бы сопоставлен с путем запроса, то возвращается стандартная ошибка 404. В зависимости от конфигурации проекта это может быть сообщение браузера или сервера. Тем не менее возможно мы захотим сами как-то управлять ошибкой и ее сообщением. Для этого добавим в проект новый компонент, который назовем 404.razor:
Определим в этом файле следующий код:
@page "/404" <h1>Resource Not Found</h1>
Данный компонент будет обрабатывать запросы по пути "/404".
И чтобы задействовать данный компонент, изменим файл Program.cs:
using BlazorApp.Components; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); var app = builder.Build(); app.UseStatusCodePagesWithReExecute("/404"); app.UseAntiforgery(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.Run();
Здесь благодаря вызову
app.UseStatusCodePagesWithReExecute("/404");
при возникновении ошибки 404 будет выполняться фактически ресурс по пути "/404", а это компонент 404.razor. В итоге при обращении к несуществующему пути пользователь получит ошибку
Это один из способов обработки ошибки. Здесь также можно использовать стандартные способы в ASP.NET Core, можно вместо отправки статусного кода 404 просто перенаправлять на определенный путь. Вообщем здесь есть различные сценарии.