将 ASP.NET Core Razor 组件与 MVC 或 Razor Pages 集成

注意

此版本不是本文的最新版本。 有关当前版本,请参阅本文.NET 9 版本。

警告

此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 有关当前版本,请参阅本文.NET 9 版本。

重要

此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。

有关当前版本,请参阅本文.NET 9 版本。

Razor 组件可以集成到 Razor Pages 或 MVC 应用中。 呈现页面或视图时,可以同时预呈现组件。

重要

各 ASP.NET Core 版本中的框架更改导致本文提供了多组不同的说明。 在使用本文的指导之前,请确认本文顶部的文档版本选择器与要用于应用的 ASP.NET Core 版本匹配。

预呈现通过呈现搜索引擎可用来计算网页排名的初始 HTTP 响应的内容,可以改进搜索引擎优化 (SEO)

配置项目后,根据项目的要求按照下列部分中的指南操作:

配置

使用以下指南将组件集成到 Razor 现有 Razor Pages 或 MVC 应用的页面或视图中。

  1. 将具有以下内容的导入文件添加到项目的根文件夹。 将 {APP NAMESPACE} 占位符更改为项目的命名空间。

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.AspNetCore.Components.Web.Virtualization
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  2. 在项目的布局文件(Razor Pages 应用中的 Pages/Shared/_Layout.cshtml 或 MVC 应用中的 Views/Shared/_Layout.cshtml)中:

    • 将以下 <base> 标记和 HeadOutlet 组件标记帮助程序添加到 <head> 元素:

      <base href="~/" />
      <component type="typeof(Microsoft.AspNetCore.Components.Web.HeadOutlet)" 
          render-mode="ServerPrerendered" />
      

      前面示例中的 href 值(应用基路径)假设应用驻留在根 URL 路径 (/) 处。 如果应用是子应用程序,请按照托管和部署 ASP.NET Core Blazor 一文的“应用基路径”部分中的指导进行操作。

      HeadOutlet 组件用于呈现页面标题(PageTitle 组件)的头 (<head>) 内容和由 Razor 组件设置的其他头元素(HeadContent 组件)。 有关详细信息,请参阅在 ASP.NET Core Blazor 应用中控制头内容

    • 在紧接着 Scripts 呈现部分 (@await RenderSectionAsync(...)) 的前方为 blazor.server.js 脚本添加 <script> 标记:

      <script src="_framework/blazor.server.js"></script>
      

      框架会将 blazor.server.js 脚本添加到应用。 无需手动将 blazor.server.js 脚本文件添加到应用。

    注意

    通常,布局通过 _ViewStart.cshtml 文件加载。

  3. 在注册服务的 Program.cs 中注册 Blazor Server 服务:

    builder.Services.AddServerSideBlazor();
    
  4. 将 Blazor 中心终结点添加到映射路由的 Program.cs 的终结点。 在调用 MapRazorPages (RazorPages) 或 MapControllerRoute (MVC) 后放置以下行:

    app.MapBlazorHub();
    
  5. 将组件集成到任何页面或视图。 例如,将 Counter 组件添加到项目的 Shared 文件夹。

    Pages/Shared/Counter.razor (Razor Pages) 或 Views/Shared/Counter.razor (MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor Pages:

    在 Razor Pages 应用的项目 Index 页中,添加 Counter 组件的命名空间,并将组件嵌入到页面中。 加载 Index 页面时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

    MVC:

    在 MVC 应用的项目 Index 视图中,添加 Counter 组件的命名空间,并将组件嵌入到视图中。 加载 Index 视图时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

有关详细信息,请参阅从页面或视图呈现组件部分。

在 Razor Pages 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 Razor Pages 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 将具有以下内容的 _Host 页面添加到项目。 使用应用的命名空间替换 {APP NAMESPACE} 占位符。

    Pages/_Host.cshtml:

    @page
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    注意

    前面的示例假定 HeadOutlet 组件和 Blazor 脚本 (_framework/blazor.server.js) 由应用的布局呈现。 有关详细信息,请参阅配置部分。

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. Program.cs 终结点中,将 _Host 页面的低优先级路由添加为最后一个终结点:

    app.MapFallbackToPage("/_Host");
    
  5. 将可路由组件添加到项目。 以下示例是 RoutableCounter 组件,它基于 Blazor 项目模板中的 Counter 组件。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

在 MVC 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 MVC 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 将具有以下内容的 _Host 视图添加到项目。 使用应用的命名空间替换 {APP NAMESPACE} 占位符。

    Views/Home/_Host.cshtml:

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    注意

    前面的示例假定 HeadOutlet 组件和 Blazor 脚本 (_framework/blazor.server.js) 由应用的布局呈现。 有关详细信息,请参阅配置部分。

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. 向 Home 控制器添加操作。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Program.cs 终结点中,为返回 _Host 视图的控制器操作添加一个低优先级路由:

    app.MapFallbackToController("Blazor", "Home");
    
  6. 在 MVC 应用中创建一个 Pages 文件夹,并添加可路由的组件。 以下示例是 RoutableCounter 组件,它基于 Blazor 项目模板中的 Counter 组件。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

从页面或视图呈现组件

本部分介绍如何在无法从用户请求直接路由组件的情况下,将组件添加到页面或视图。

若要从页面或视图呈现组件,请使用组件标记帮助程序

呈现有状态交互式组件

可以将有状态的交互式组件添加到 Razor 页面或视图。

呈现页面或视图时:

  • 该组件通过页面或视图预呈现。
  • 用于预呈现的初始组件状态丢失。
  • 建立 SignalR 连接时,将创建新的组件状态。

以下 Razor 页面将呈现 Counter 组件:

<h1>Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

呈现非交互式组件

在以下 Razor 页面中,使用以下格式通过指定的初始值静态呈现 Counter 组件。 由于该组件是以静态方式呈现的,因此它不是交互式组件:

<h1>Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

组件命名空间

使用自定义文件夹保存项目的 Razor 组件时,将表示文件夹的命名空间添加到页面/视图或 _ViewImports.cshtml 文件。 如下示例中:

  • 组件存储在项目的 Components 文件夹中。
  • {APP NAMESPACE} 占位符是项目的文件夹。 Components 表示文件夹的名称。
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 文件位于 Razor Pages 应用的 Pages 文件夹中,或是 MVC 应用的 Views 文件夹中。

有关详细信息,请参阅 ASP.NET Core Razor 组件

保留预呈现状态

在不保留预呈现状态的情况下,在预呈现期间使用的状态将丢失,并且在完全加载应用时必须重新创建。 如果任何状态都是异步设置的,则 UI 可能会闪烁,因为预呈现 UI 将替换为临时占位符,然后再次完全呈现。

要保留预呈现组件的状态,请使用“保留组件状态”标记帮助程序参考源)。 在预呈现组件的应用的 _Host 页面的结束 </body> 标记内添加标记帮助程序的标记 <persist-component-state />

注意

指向 .NET 参考源的文档链接通常会加载存储库的默认分支,该分支表示针对下一个 .NET 版本的当前开发。 若要为特定版本选择标记,请使用“切换分支或标记”下拉列表。 有关详细信息,请参阅如何选择 ASP.NET Core 源代码的版本标记 (dotnet/AspNetCore.Docs #26205)

Blazor在Pages/_Host.cshtml应用中ServerPrerendered的应用中Blazor Server:

<body>
    ...

    <persist-component-state />
</body>

决定要使用 PersistentComponentState 服务保留的状态。 PersistentComponentState.RegisterOnPersisting 注册回调以在暂停应用之前保留组件状态。 在应用程序恢复时检索状态。

如下示例中:

  • {TYPE} 占位符表示要持久保存的数据类型(例如 WeatherForecast[])。
  • {TOKEN} 占位符是状态标识符字符串(例如 fetchdata)。
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
    private {TYPE} data;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistData);

        if (!ApplicationState.TryTakeFromJson<{TYPE}>(
            "{TOKEN}", out var restored))
        {
            data = await ...;
        }
        else
        {
            data = restored!;
        }
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson("{TOKEN}", data);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

以下示例是基于Blazor项目模板的FetchData组件的更新版本。 WeatherForecastPreserveState 组件在预呈现期间保留天气预报状态,然后检索状态以初始化组件。 保留组件状态标记帮助程序在所有组件调用之后保留组件状态。

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistForecasts);

        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            "fetchdata", out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
        }
        else
        {
            forecasts = restored!;
        }
    }

    private Task PersistForecasts()
    {
        ApplicationState.PersistAsJson("fetchdata", forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

通过使用在预呈现期间使用的相同状态来初始化组件,将只执行一次成本高昂的初始化步骤。 呈现的 UI 也与预呈现 UI 相匹配,因此浏览器不会闪烁。

持久预呈现状态将传输到客户端,用于还原组件状态。 ASP.NET 核心数据保护 可确保在应用中安全地 Blazor Server 传输数据。

预呈现状态大小和 SignalR 消息大小限制

大型预呈现状态大小可能超过 Blazor线路 SignalR 消息大小限制,这会导致以下结果:

  • SignalR 线路初始化失败,客户端上出现错误:Circuit host not initialized.
  • 当线路发生故障时,客户端上显示重新连接 UI。 无法进行恢复。

若要解决此问题,请使用以下任一方法

  • 减少要置于预呈现状态的数据量。
  • 增加 SignalR 消息大小限制。 警告:增加限制可能会增加拒绝服务 (DoS) 攻击风险

其他 Blazor Server 资源

预呈现通过呈现搜索引擎可用来计算网页排名的初始 HTTP 响应的内容,可以改进搜索引擎优化 (SEO)

配置项目后,根据项目的要求按照下列部分中的指南操作:

配置

使用以下指南将组件集成到 Razor 现有 Razor Pages 或 MVC 应用的页面或视图中。

重要

需要将布局页 (_Layout.cshtml) 和 HeadOutlet 组件的组件标记帮助程序一起使用来控制 <head> 内容,例如页面标题(PageTitle 组件)和其他头元素(HeadContent 组件)。 有关详细信息,请参阅在 ASP.NET Core Blazor 应用中控制头内容

  1. 在项目的布局文件中:

    • 将以下 <base> 标记和 HeadOutlet 组件标记帮助程序添加到 Pages/Shared/_Layout.cshtml (Razor Pages) 或 Views/Shared/_Layout.cshtml (MVC) 中的 <head> 元素:

      <base href="~/" />
      <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
      

      前面示例中的 href 值(应用基路径)假设应用驻留在根 URL 路径 (/) 处。 如果应用是子应用程序,请按照托管和部署 ASP.NET Core Blazor 一文的“应用基路径”部分中的指导进行操作。

      HeadOutlet 组件用于呈现页面标题(PageTitle 组件)的头 (<head>) 内容和由 Razor 组件设置的其他头元素(HeadContent 组件)。 有关详细信息,请参阅在 ASP.NET Core Blazor 应用中控制头内容

    • 在紧接着应用布局的 Scripts 呈现部分 (@await RenderSectionAsync(...)) 的前方为 blazor.server.js 脚本添加 <script> 标记。

      Pages/Shared/_Layout.cshtml (Razor Pages) 或 Views/Shared/_Layout.cshtml (MVC):

      <script src="_framework/blazor.server.js"></script>
      

      框架会将 blazor.server.js 脚本添加到应用。 无需手动将 blazor.server.js 脚本文件添加到应用。

  2. 将具有以下内容的导入文件添加到项目的根文件夹。 将 {APP NAMESPACE} 占位符更改为项目的命名空间。

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.AspNetCore.Components.Web.Virtualization
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  3. 在注册服务的 Program.cs 中注册 Blazor Server 服务:

    builder.Services.AddServerSideBlazor();
    
  4. 将 Blazor 中心终结点添加到映射路由的 Program.cs 的终结点。

    在调用 MapRazorPages (RazorPages) 或 MapControllerRoute (MVC) 后放置以下行:

    app.MapBlazorHub();
    
  5. 将组件集成到任何页面或视图。 例如,将 Counter 组件添加到项目的 Shared 文件夹。

    Pages/Shared/Counter.razor (Razor Pages) 或 Views/Shared/Counter.razor (MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor Pages:

    在 Razor Pages 应用的项目 Index 页中,添加 Counter 组件的命名空间,并将组件嵌入到页面中。 加载 Index 页面时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

    MVC:

    在 MVC 应用的项目 Index 视图中,添加 Counter 组件的命名空间,并将组件嵌入到视图中。 加载 Index 视图时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

有关详细信息,请参阅从页面或视图呈现组件部分。

在 Razor Pages 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 Razor Pages 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 将具有以下内容的 _Host 页面添加到项目。

    Pages/_Host.cshtml:

    @page "/blazor"
    @namespace {APP NAMESPACE}.Pages.Shared
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @{
        Layout = "_Layout";
    }
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    在此场景中,组件将共享 _Layout.cshtml 文件用于布局。

    重要

    需要将布局页 (_Layout.cshtml) 和 HeadOutlet 组件的组件标记帮助程序一起使用来控制 <head> 内容,例如页面标题(PageTitle 组件)和其他头元素(HeadContent 组件)。 有关详细信息,请参阅在 ASP.NET Core Blazor 应用中控制头内容

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. Program.cs 终结点中,将 _Host 页面的低优先级路由添加为最后一个终结点:

    app.MapFallbackToPage("/_Host");
    
  5. 将可路由组件添加到项目。 以下示例是 RoutableCounter 组件,它基于 Blazor 项目模板中的 Counter 组件。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

在 MVC 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 MVC 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 将具有以下内容的 _Host 视图添加到项目。

    Views/Home/_Host.cshtml:

    @namespace {APP NAMESPACE}.Views.Shared
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @{
        Layout = "_Layout";
    }
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    组件将共享 _Layout.cshtml 文件用于布局。

    重要

    需要将布局页 (_Layout.cshtml) 和 HeadOutlet 组件的组件标记帮助程序一起使用来控制 <head> 内容,例如页面标题(PageTitle 组件)和其他头元素(HeadContent 组件)。 有关详细信息,请参阅在 ASP.NET Core Blazor 应用中控制头内容

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. 向 Home 控制器添加操作。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Program.cs 终结点中,为返回 _Host 视图的控制器操作添加一个低优先级路由:

    app.MapFallbackToController("Blazor", "Home");
    
  6. 在 MVC 应用中创建一个 Pages 文件夹,并添加可路由的组件。 以下示例是 RoutableCounter 组件,它基于 Blazor 项目模板中的 Counter 组件。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

从页面或视图呈现组件

本部分介绍如何在无法从用户请求直接路由组件的情况下,将组件添加到页面或视图。

若要从页面或视图呈现组件,请使用组件标记帮助程序

呈现有状态交互式组件

可以将有状态的交互式组件添加到 Razor 页面或视图。

呈现页面或视图时:

  • 该组件通过页面或视图预呈现。
  • 用于预呈现的初始组件状态丢失。
  • 建立 SignalR 连接时,将创建新的组件状态。

以下 Razor 页面将呈现 Counter 组件:

<h1>Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

重要

需要将布局页 (_Layout.cshtml) 和 HeadOutlet 组件的组件标记帮助程序一起使用来控制 <head> 内容,例如页面标题(PageTitle 组件)和其他头元素(HeadContent 组件)。 有关详细信息,请参阅在 ASP.NET Core Blazor 应用中控制头内容

呈现非交互式组件

在以下 Razor 页面中,使用以下格式通过指定的初始值静态呈现 Counter 组件。 由于该组件是以静态方式呈现的,因此它不是交互式组件:

<h1>Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

重要

需要将布局页 (_Layout.cshtml) 和 HeadOutlet 组件的组件标记帮助程序一起使用来控制 <head> 内容,例如页面标题(PageTitle 组件)和其他头元素(HeadContent 组件)。 有关详细信息,请参阅在 ASP.NET Core Blazor 应用中控制头内容

组件命名空间

使用自定义文件夹保存项目的 Razor 组件时,将表示文件夹的命名空间添加到页面/视图或 _ViewImports.cshtml 文件。 如下示例中:

  • 组件存储在项目的 Components 文件夹中。
  • {APP NAMESPACE} 占位符是项目的文件夹。 Components 表示文件夹的名称。
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 文件位于 Razor Pages 应用的 Pages 文件夹中,或是 MVC 应用的 Views 文件夹中。

有关详细信息,请参阅 ASP.NET Core Razor 组件

保留预呈现状态

在不保留预呈现状态的情况下,在预呈现期间使用的状态将丢失,并且在完全加载应用时必须重新创建。 如果任何状态都是异步设置的,则 UI 可能会闪烁,因为预呈现 UI 将替换为临时占位符,然后再次完全呈现。

为了解决这些问题,Blazor 使用预留组件状态标记帮助程序在预呈现页面中支持持久化状态。 在结束 </body> 标记中添加标记帮助程序的标记 <persist-component-state />

Pages/_Layout.cshtml:

<body>
    ...

    <persist-component-state />
</body>

决定要使用 PersistentComponentState 服务保留的状态。 PersistentComponentState.RegisterOnPersisting 注册回调以在暂停应用之前保留组件状态。 在应用程序恢复时检索状态。

以下示例是基于Blazor项目模板的FetchData组件的更新版本。 WeatherForecastPreserveState 组件在预呈现期间保留天气预报状态,然后检索状态以初始化组件。 保留组件状态标记帮助程序在所有组件调用之后保留组件状态。

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistForecasts);

        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            "fetchdata", out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateTime.Now);
        }
        else
        {
            forecasts = restored!;
        }
    }

    private Task PersistForecasts()
    {
        ApplicationState.PersistAsJson("fetchdata", forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

通过使用在预呈现期间使用的相同状态来初始化组件,将只执行一次成本高昂的初始化步骤。 呈现的 UI 也与预呈现 UI 相匹配,因此浏览器不会闪烁。

持久预呈现状态将传输到客户端,用于还原组件状态。 ASP.NET 核心数据保护 可确保在应用中安全地 Blazor Server 传输数据。

预呈现状态大小和 SignalR 消息大小限制

大型预呈现状态大小可能超过 Blazor线路 SignalR 消息大小限制,这会导致以下结果:

  • SignalR 线路初始化失败,客户端上出现错误:Circuit host not initialized.
  • 当线路发生故障时,客户端上显示重新连接 UI。 无法进行恢复。

若要解决此问题,请使用以下任一方法

  • 减少要置于预呈现状态的数据量。
  • 增加 SignalR 消息大小限制。 警告:增加限制可能会增加拒绝服务 (DoS) 攻击风险

其他 Blazor Server 资源

预呈现通过呈现搜索引擎可用来计算网页排名的初始 HTTP 响应的内容,可以改进搜索引擎优化 (SEO)

配置项目后,根据项目的要求按照下列部分中的指南操作:

配置

现有 Razor Pages 或 MVC 应用可以将组件集成到 Razor 页面或视图中:

  1. 在项目的布局文件中:

    • 将以下 <base> 标记添加到 Pages/Shared/_Layout.cshtml (Razor Pages) 或 Views/Shared/_Layout.cshtml (MVC) 中的 <head> 元素:

      <base href="~/" />
      

      前面示例中的 href 值(应用基路径)假设应用驻留在根 URL 路径 (/) 处。 如果应用是子应用程序,请按照托管和部署 ASP.NET Core Blazor 一文的“应用基路径”部分中的指导进行操作。

    • 在紧接着 Scripts 呈现部分的前方为 blazor.server.js 脚本添加 <script> 标记。

      Pages/Shared/_Layout.cshtml (Razor Pages) 或 Views/Shared/_Layout.cshtml (MVC):

          ...
          <script src="_framework/blazor.server.js"></script>
      
          @await RenderSectionAsync("Scripts", required: false)
      </body>
      

      框架会将 blazor.server.js 脚本添加到应用。 无需手动将 blazor.server.js 脚本文件添加到应用。

  2. 将具有以下内容的导入文件添加到项目的根文件夹。 将 {APP NAMESPACE} 占位符更改为项目的命名空间。

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  3. Startup.ConfigureServices 中注册 Blazor Server 服务。

    Startup.cs中:

    services.AddServerSideBlazor();
    
  4. 将 Blazor 中心终结点添加到 Startup.Configure 的终结点 (app.UseEndpoints)。

    Startup.cs:

    endpoints.MapBlazorHub();
    
  5. 将组件集成到任何页面或视图。 例如,将 Counter 组件添加到项目的 Shared 文件夹。

    Pages/Shared/Counter.razor (Razor Pages) 或 Views/Shared/Counter.razor (MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor Pages:

    在 Razor Pages 应用的项目 Index 页中,添加 Counter 组件的命名空间,并将组件嵌入到页面中。 加载 Index 页面时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

    在上面的示例中,将 {APP NAMESPACE} 占位符替换为应用的命名空间。

    MVC:

    在 MVC 应用的项目 Index 视图中,添加 Counter 组件的命名空间,并将组件嵌入到视图中。 加载 Index 视图时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

有关详细信息,请参阅从页面或视图呈现组件部分。

在 Razor Pages 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 Razor Pages 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    

    注意

    随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。 有关详细信息,请参阅从 ASP.NET Core 3.1 迁移到 5.0

  3. 将具有以下内容的 _Host 页面添加到项目。

    Pages/_Host.cshtml:

    @page "/blazor"
    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    组件将共享 _Layout.cshtml 文件用于布局。

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. Startup.csStartup.Configure 终结点中,将 _Host 页面的低优先级路由添加为最后一个终结点:

    endpoints.MapFallbackToPage("/_Host");
    

    以下示例显示了典型应用的终结点配置中添加的行:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
    
  5. 将可路由组件添加到项目。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

在 MVC 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 MVC 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    

    注意

    随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。 有关详细信息,请参阅从 ASP.NET Core 3.1 迁移到 5.0

  3. 将具有以下内容的 _Host 视图添加到项目。

    Views/Home/_Host.cshtml:

    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    组件将共享 _Layout.cshtml 文件用于布局。

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. 向 Home 控制器添加操作。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Startup.csStartup.Configure 终结点中,添加返回 _Host 视图的控制器操作的低优先级路由:

    endpoints.MapFallbackToController("Blazor", "Home");
    

    以下示例显示了典型应用的终结点配置中添加的行:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToController("Blazor", "Home");
    });
    
  6. 将可路由组件添加到项目。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

从页面或视图呈现组件

本部分介绍如何在无法从用户请求直接路由组件的情况下,将组件添加到页面或视图。

若要从页面或视图呈现组件,请使用组件标记帮助程序

呈现有状态交互式组件

可以将有状态的交互式组件添加到 Razor 页面或视图。

呈现页面或视图时:

  • 该组件通过页面或视图预呈现。
  • 用于预呈现的初始组件状态丢失。
  • 建立 SignalR 连接时,将创建新的组件状态。

以下 Razor 页面将呈现 Counter 组件:

<h1>My Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

呈现非交互式组件

在以下 Razor 页面中,使用以下格式通过指定的初始值静态呈现 Counter 组件。 由于该组件是以静态方式呈现的,因此它不是交互式组件:

<h1>My Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

组件命名空间

使用自定义文件夹保存项目的 Razor 组件时,将表示文件夹的命名空间添加到页面/视图或 _ViewImports.cshtml 文件。 如下示例中:

  • 组件存储在项目的 Components 文件夹中。
  • {APP NAMESPACE} 占位符是项目的文件夹。 Components 表示文件夹的名称。
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 文件位于 Razor Pages 应用的 Pages 文件夹中,或是 MVC 应用的 Views 文件夹中。

有关详细信息,请参阅 ASP.NET Core Razor 组件

预呈现状态大小和 SignalR 消息大小限制

大型预呈现状态大小可能超过 Blazor线路 SignalR 消息大小限制,这会导致以下结果:

  • SignalR 线路初始化失败,客户端上出现错误:Circuit host not initialized.
  • 当线路发生故障时,客户端上显示重新连接 UI。 无法进行恢复。

若要解决此问题,请使用以下任一方法

  • 减少要置于预呈现状态的数据量。
  • 增加 SignalR 消息大小限制。 警告:增加限制可能会增加拒绝服务 (DoS) 攻击风险

其他 Blazor Server 资源

Razor 组件可以集成到 Razor Pages 或 MVC 应用中。 呈现页面或视图时,可以同时预呈现组件。

预呈现通过呈现搜索引擎可用来计算网页排名的初始 HTTP 响应的内容,可以改进搜索引擎优化 (SEO)

配置项目后,根据项目的要求按照下列部分中的指南操作:

配置

现有 Razor Pages 或 MVC 应用可以将组件集成到 Razor 页面或视图中:

  1. 在项目的布局文件中:

    • 将以下 <base> 标记添加到 Pages/Shared/_Layout.cshtml (Razor Pages) 或 Views/Shared/_Layout.cshtml (MVC) 中的 <head> 元素:

      + <base href="~/" />
      

      前面示例中的 href 值(应用基路径)假设应用驻留在根 URL 路径 (/) 处。 如果应用是子应用程序,请按照托管和部署 ASP.NET Core Blazor 一文的“应用基路径”部分中的指导进行操作。

    • 在紧接着 Scripts 呈现部分的前方为 blazor.server.js 脚本添加 <script> 标记。

      Pages/Shared/_Layout.cshtml (Razor Pages) 或 Views/Shared/_Layout.cshtml (MVC):

          ...
          <script src="_framework/blazor.server.js"></script>
      
          @await RenderSectionAsync("Scripts", required: false)
      </body>
      

      框架会将 blazor.server.js 脚本添加到应用。 无需手动将 blazor.server.js 脚本文件添加到应用。

  2. 将具有以下内容的导入文件添加到项目的根文件夹。 将 {APP NAMESPACE} 占位符更改为项目的命名空间。

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  3. Startup.ConfigureServices 中注册 Blazor Server 服务。

    Startup.cs:

    services.AddServerSideBlazor();
    
  4. 将 Blazor 中心终结点添加到 Startup.Configure 的终结点 (app.UseEndpoints)。

    Startup.cs:

    endpoints.MapBlazorHub();
    
  5. 将组件集成到任何页面或视图。 例如,将 Counter 组件添加到项目的 Shared 文件夹。

    Pages/Shared/Counter.razor (Razor Pages) 或 Views/Shared/Counter.razor (MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor Pages:

    在 Razor Pages 应用的项目 Index 页中,添加 Counter 组件的命名空间,并将组件嵌入到页面中。 加载 Index 页面时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

    在上面的示例中,将 {APP NAMESPACE} 占位符替换为应用的命名空间。

    MVC:

    在 MVC 应用的项目 Index 视图中,添加 Counter 组件的命名空间,并将组件嵌入到视图中。 加载 Index 视图时,将在页面中预呈现 Counter 组件。 在下面的示例中,将 {APP NAMESPACE} 占位符替换为项目的命名空间。

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

有关详细信息,请参阅从页面或视图呈现组件部分。

在 Razor Pages 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 Razor Pages 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    
  3. 将具有以下内容的 _Host 页面添加到项目。

    Pages/_Host.cshtml:

    @page "/blazor"
    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    组件将共享 _Layout.cshtml 文件用于布局。

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. Startup.csStartup.Configure 终结点中,将 _Host 页面的低优先级路由添加为最后一个终结点:

    endpoints.MapFallbackToPage("/_Host");
    

    以下示例显示了典型应用的终结点配置中添加的行:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
    
  5. 将可路由组件添加到项目。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

在 MVC 应用中使用可路由组件

本部分介绍如何添加可直接从用户请求路由的组件。

在 MVC 应用中支持可路由 Razor 组件:

  1. 按照配置部分中的指南操作。

  2. 将具有以下内容的 App 组件添加到项目根。

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    
  3. 将具有以下内容的 _Host 视图添加到项目。

    Views/Home/_Host.cshtml:

    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    组件将共享 _Layout.cshtml 文件用于布局。

    RenderMode 会配置 App 组件是否:

    • 在页面中预呈现。
    • 在页面上呈现为静态 HTML,或者包含从用户代理启动 Blazor 应用所需的信息。

    有关组件标记帮助程序的详细信息(包括传递参数和 RenderMode 配置),请参阅 ASP.NET Core 中的组件标记帮助程序

  4. 向 Home 控制器添加操作。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Startup.csStartup.Configure 终结点中,添加返回 _Host 视图的控制器操作的低优先级路由:

    endpoints.MapFallbackToController("Blazor", "Home");
    

    以下示例显示了典型应用的终结点配置中添加的行:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToController("Blazor", "Home");
    });
    
  6. 将可路由组件添加到项目。

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 运行项目并导航到 /routable-counter 中的可路由 RoutableCounter 组件。

有关命名空间的详细信息,请参阅组件命名空间部分。

从页面或视图呈现组件

本部分介绍如何在无法从用户请求直接路由组件的情况下,将组件添加到页面或视图。

若要从页面或视图呈现组件,请使用组件标记帮助程序

呈现有状态交互式组件

可以将有状态的交互式组件添加到 Razor 页面或视图。

呈现页面或视图时:

  • 该组件通过页面或视图预呈现。
  • 用于预呈现的初始组件状态丢失。
  • 建立 SignalR 连接时,将创建新的组件状态。

以下 Razor 页面将呈现 Counter 组件:

<h1>My Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

呈现非交互式组件

在以下 Razor 页面中,使用以下格式通过指定的初始值静态呈现 Counter 组件。 由于该组件是以静态方式呈现的,因此它不是交互式组件:

<h1>My Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

有关详细信息,请参阅 ASP.NET Core 中的组件标记帮助程序

组件命名空间

使用自定义文件夹保存项目的 Razor 组件时,将表示文件夹的命名空间添加到页面/视图或 _ViewImports.cshtml 文件。 如下示例中:

  • 组件存储在项目的 Components 文件夹中。
  • {APP NAMESPACE} 占位符是项目的文件夹。 Components 表示文件夹的名称。
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 文件位于 Razor Pages 应用的 Pages 文件夹中,或是 MVC 应用的 Views 文件夹中。

有关详细信息,请参阅 ASP.NET Core Razor 组件

预呈现状态大小和 SignalR 消息大小限制

大型预呈现状态大小可能超过 Blazor线路 SignalR 消息大小限制,这会导致以下结果:

  • SignalR 线路初始化失败,客户端上出现错误:Circuit host not initialized.
  • 当线路发生故障时,客户端上显示重新连接 UI。 无法进行恢复。

若要解决此问题,请使用以下任一方法

  • 减少要置于预呈现状态的数据量。
  • 增加 SignalR 消息大小限制。 警告:增加限制可能会增加拒绝服务 (DoS) 攻击风险

其他 Blazor Server 资源