ASP.NET Core Blazor 路由ASP.NET Core Blazor routing

本文内容

作者:Luke Latham

重要

Blazor WebAssembly 为预览版状态

ASP.NET Core 3.0 支持 Blazor Server。Blazor WebAssembly 在 ASP.NET Core 3.1 中为预览版。

了解如何路由请求以及如何使用 NavLink 组件在 Blazor 应用中创建导航链接。

ASP.NET Core 终结点路由集成ASP.NET Core endpoint routing integration

Blazor Server 已集成到 ASP.NET Core 终结点路由中。ASP.NET Core 应用配置为接受 Startup.Configure 中带有 MapBlazorHub 的交互式组件的传入连接:

  1. app.UseRouting();
  2. app.UseEndpoints(endpoints =>
  3. {
  4. endpoints.MapBlazorHub();
  5. endpoints.MapFallbackToPage("/_Host");
  6. });

最典型的配置是将所有请求路由到 Razor 页面,该页面充当 Blazor Server 应用服务器端部分的主机。按照约定,主机页通常命名为 _Host.cshtml主机文件中指定的路由称为回退路由,因为它在路由匹配中以较低的优先级运行。其他路由不匹配时,会考虑回退路由。这让应用能够使用其他控制器和页面,而不会干扰 Blazor Server 应用。

路由模板Route templates

Router 组件可实现到具有指定路由的每个组件的路由。Router 组件出现在 App.razor 文件中:

  1. <Router AppAssembly="typeof(Startup).Assembly">
  2. <Found Context="routeData">
  3. <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
  4. </Found>
  5. <NotFound>
  6. <p>Sorry, there's nothing at this address.</p>
  7. </NotFound>
  8. </Router>

编译带有 @page 指令的 .razor 文件时,将为生成的类提供指定路由模板的 RouteAttribute

在运行时,RouteView 组件:

  • Router 接收 RouteData 以及任何所需的参数。
  • 通过指定参数使用指定组件的布局(或可选的默认布局)呈现该组件。

可选择使用布局类指定 DefaultLayout 参数,以用于未指定布局的组件。默认的 Blazor 模板指定 MainLayout 组件。MainLayout.razor 在模板项目的 Shared 文件夹中。有关布局的详细信息,请参阅 ASP.NET Core Blazor 布局

可将多个路由模板应用于一个组件。以下组件响应对 /BlazorRoute/DifferentBlazorRoute 的请求:

  1. @page "/BlazorRoute"
  2. @page "/DifferentBlazorRoute"
  3. <h1>Blazor routing</h1>

重要

若要正确解析 URL,应用必须在其 wwwroot/index.html 文件 (Blazor WebAssembly) 或 Pages/_Host.cshtml 文件 (Blazor Server) 中包括 <base> 标记,并使用 href 属性 (<base href="/">) 中指定的应用基路径。有关详细信息,请参阅 托管和部署 ASP.NET Core Blazor

在找不到内容时提供自定义内容Provide custom content when content isn't found

如果找不到所请求路由的内容,则 Router 组件允许应用指定自定义内容。

App.razor 文件中,在 Router 组件的 NotFound 模板参数中设置自定义内容:

  1. <Router AppAssembly="typeof(Startup).Assembly">
  2. <Found Context="routeData">
  3. <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
  4. </Found>
  5. <NotFound>
  6. <h1>Sorry</h1>
  7. <p>Sorry, there's nothing at this address.</p> b
  8. </NotFound>
  9. </Router>

<NotFound> 标记的内容可以包括任意项,例如其他交互式组件。若要将默认布局应用于 NotFound 内容,请参阅 ASP.NET Core Blazor 布局

从多个程序集路由到组件Route to components from multiple assemblies

使用 AdditionalAssemblies 参数为 Router 组件指定搜索可路由组件时要考虑的其他程序集。AppAssembly 指定的程序集外,还要考虑指定的程序集。在以下示例中,Component1 是在引用的类库中定义的可路由组件。以下 AdditionalAssemblies 示例为 Component1 提供路由支持:

  1. <Router
  2. AppAssembly="typeof(Program).Assembly"
  3. AdditionalAssemblies="new[] { typeof(Component1).Assembly }">
  4. ...
  5. </Router>

路由参数Route parameters

路由器使用路由参数以相同的名称填充相应的组件参数(不区分大小写):

  1. @page "/RouteParameter"
  2. @page "/RouteParameter/{text}"
  3. <h1>Blazor is @Text!</h1>
  4. @code {
  5. [Parameter]
  6. public string Text { get; set; }
  7. protected override void OnInitialized()
  8. {
  9. Text = Text ?? "fantastic";
  10. }
  11. }

不支持可选参数。上一个示例中应用了两个 @page 指令。第一个指令允许导航到没有参数的组件。第二个 @page 指令采用 {text} 路由参数,并将值赋予 Text 属性。

路由约束Route constraints

路由约束强制在路由段和组件之间进行类型匹配。

在以下示例中,到 Users 组件的路由仅在以下情况下匹配:

  • 请求 URL 上存在 Id 路由段。
  • Id 段是整数 (int)。
  1. @page "/Users/{Id:int}"
  2. <h1>The user Id is @Id!</h1>
  3. @code {
  4. [Parameter]
  5. public int Id { get; set; }
  6. }

下表中显示的路由约束可用。有关与固定区域性匹配的路由约束,请参阅表下方的警告了解详细信息。

约束示例匹配项示例固定条件区域性匹配
bool{active:bool}trueFALSE
datetime{dob:datetime}2016-12-312016-12-31 7:32pm
decimal{price:decimal}49.99-1,000.01
double{weight:double}1.234-1,001.01e8
float{weight:float}1.234-1,001.01e8
guid{id:guid}CD2C1638-1638-72D5-1638-DEADBEEF1638{CD2C1638-1638-72D5-1638-DEADBEEF1638}
int{id:int}123456789-123456789
long{ticks:long}123456789-123456789

警告

验证 URL 的路由约束并将转换为始终使用固定区域性的 CLR 类型(例如 intDateTime)。这些约束假定 URL 不可本地化。

使用包含点的 URL 进行路由Routing with URLs that contain dots

在 Blazor Server 应用中, Host.cshtml 中的默认路由为 / (@page "/")。包含点 (.) 的请求 URL 与默认路由不匹配,因为 URL 似乎在请求文件。Blazor 应用针对不存在的静态文件返回 _404 - 未找到响应。若要使用包含点的路由,请使用以下路由模板配置 Host.cshtml_:

  1. @page "/{**path}"

"/{**path}" 模板包括:

  • 双星号 catch-all 语法 (**),用于捕获跨多个文件夹边界的路径,而无需编码正斜杠 (/)。
  • path 路由参数名称。

备注

Razor 组件 ( .razor) 支持 catch-all 参数语法 (/*)。

有关详细信息,请参阅 ASP.NET Core 中的路由

NavLink 组件NavLink component

创建导航链接时,请使用 NavLink 组件代替 HTML 超链接元素 (<a>)。NavLink 组件的行为方式类似于 <a> 元素,但它根据其 href 是否与当前 URL 匹配来切换 active CSS 类。active 类可帮助用户了解所显示导航链接中的哪个页面是活动页面。

以下 NavMenu 组件创建启动导航栏,该导航栏演示如何使用 NavLink 组件:

  1. <div class="@NavMenuCssClass" @onclick="@ToggleNavMenu">
  2. <ul class="nav flex-column">
  3. <li class="nav-item px-3">
  4. <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
  5. <span class="oi oi-home" aria-hidden="true"></span> Home
  6. </NavLink>
  7. </li>
  8. <li class="nav-item px-3">
  9. <NavLink class="nav-link" href="MyComponent" Match="NavLinkMatch.Prefix">
  10. <span class="oi oi-plus" aria-hidden="true"></span> My Component
  11. </NavLink>
  12. </li>
  13. </ul>
  14. </div>

有两个 NavLinkMatch 选项可分配给 <NavLink> 元素的 Match 属性:

  • NavLinkMatch.AllNavLink 在与当前整个 URL 匹配的情况下处于活动状态。
  • NavLinkMatch.Prefix默认)– NavLink 在与当前 URL 的任何前缀匹配的情况下处于活动状态。

在前面的示例中,主页 NavLink href="" 与主页 URL 匹配,并且仅在应用的默认基路径 URL(例如,https://localhost:5001/)处接收 active CSS 类。当用户访问带有 MyComponent 前缀的任何 URL(例如,https://localhost:5001/MyComponenthttps://localhost:5001/MyComponent/AnotherSegment)时,第二个 NavLink 接收 active 类。

其他 NavLink 组件属性会传递到呈现的定位标记。在以下示例中,NavLink 组件包括 target 属性:

  1. <NavLink href="my-page" target="_blank">My page</NavLink>

呈现以下 HTML 标记:

  1. <a href="my-page" target="_blank" rel="noopener noreferrer">My page</a>

URI 和导航状态帮助程序URI and navigation state helpers

在 C# 代码中将 Microsoft.AspNetCore.Components.NavigationManager 与 URI 和导航配合使用。NavigationManager 提供下表所示的事件和方法。

成员描述
Uri获取当前绝对 URI。
BaseUri获取可在相对 URI 路径之前添加用于生成绝对 URI 的基 URI(带有尾部反斜杠)。通常,BaseUri 对应于 wwwroot/index.html (Blazor WebAssembly) 或 Pages/_Host.cshtml (Blazor Server) 中文档的 <base> 元素上的 href 属性。
NavigateTo导航到指定 URI。如果 forceLoadtrue,则:

- 客户端路由会被绕过。
- 无论 URI 是否通常由客户端路由器处理,浏览器都必须从服务器加载新页面。
LocationChanged导航位置更改时触发的事件。
ToAbsoluteUri将相对 URI 转换为绝对 URI。
ToBaseRelativePath给定基 URI(例如,之前由 GetBaseUri 返回的 URI),将绝对 URI 转换为相对于基 URI 前缀的 URI。

选择该按钮后,以下组件导航到应用的 Counter 组件:

  1. @page "/navigate"
  2. @inject NavigationManager NavigationManager
  3. <h1>Navigate in Code Example</h1>
  4. <button class="btn btn-primary" @onclick="NavigateToCounterComponent">
  5. Navigate to the Counter component
  6. </button>
  7. @code {
  8. private void NavigateToCounterComponent()
  9. {
  10. NavigationManager.NavigateTo("counter");
  11. }
  12. }