You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Razor Pages中单个CSHTML页面托管多页Blazor WASM SPA?

在Razor Pages中托管多页Blazor SPA的实现方案

一、项目基础搭建

  1. 创建.NET 7 Razor Pages项目
    使用命令行或Visual Studio生成项目:
    dotnet new razor -n BlazorRazorPagesDemo
    
  2. 集成Blazor WebAssembly支持
    安装必要包:
    dotnet add package Microsoft.AspNetCore.Components.WebAssembly.Server
    
    修改Program.cs,添加Blazor服务与中间件,同时做好路由隔离:
    var builder = WebApplication.CreateBuilder(args);
    
    // 注册Razor Pages服务
    builder.Services.AddRazorPages();
    // 注册Blazor WebAssembly服务
    builder.Services.AddBlazorWebAssembly();
    
    var app = builder.Build();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    
    // 启用Blazor信号量集线器
    app.MapBlazorHub();
    // 配置Blazor路由回退,所有/blazor/前缀的请求交由Blazor处理
    app.MapFallbackToFile("blazor/{*path}", "blazor/index.html");
    // 映射Razor Pages路由
    app.MapRazorPages();
    
    app.Run();
    

二、创建Blazor SPA的宿主Razor页面

在Pages目录下新建BlazorHost.cshtml,作为Blazor SPA的托管入口:

@page "/blazor-host"
@{
    Layout = "_Layout";
}

<h1>托管Blazor SPA的Razor页面</h1>

<!-- Blazor应用容器 -->
<div id="blazor-app">
    <app>加载中...</app>
</div>

<!-- 引入Blazor启动脚本 -->
<script src="_framework/blazor.webassembly.js"></script>

在wwwroot下创建blazor目录,添加Blazor SPA的入口页面index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blazor SPA</title>
    <!-- 设置Blazor路由基础前缀,避免与Razor Pages路由冲突 -->
    <base href="/blazor/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
</head>
<body>
    <div id="app">加载中...</div>

    <div id="blazor-error-ui">
        发生未处理错误。
        <a href="" class="reload">重新加载</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
</body>
</html>

三、实现Blazor内部多页路由

在项目中创建Components目录,存放Blazor组件与页面:

  1. 创建布局组件MainLayout.razor:
@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <!-- 跳回Razor Pages时指定target="_top",避免在Blazor容器内打开 -->
            <a href="/blazor-host" target="_top">返回Razor页面</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>
  1. 创建导航菜单NavMenu.razor:
<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">Blazor SPA</a>
    </div>
</div>

<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> 首页
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> 计数器
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> 获取数据
            </NavLink>
        </div>
    </nav>
</div>
  1. 创建Blazor页面组件,比如Counter.razor:
@page "/counter"

<h1>计数器</h1>

<p>当前计数: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">点击计数</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

四、路由冲突解决要点

  1. 前缀隔离:通过index.html中的<base href="/blazor/" />,让Blazor所有内部路由都带上/blazor/前缀,与Razor Pages的路由彻底分隔。
  2. 回退路由:Program.cs中的MapFallbackToFile确保所有/blazor/开头的请求都交由Blazor处理,不会触发Razor Pages的404。
  3. 跨路由跳转:从Blazor跳回Razor Pages时,必须使用target="_top"或通过NavigationManager修改跳转目标,避免在Blazor容器内加载Razor页面。

可行性说明

这种方案完全可行。通过路由前缀隔离、回退规则配置,能够让Razor Pages的多页特性与Blazor SPA的单页能力共存,既保留Razor Pages对传统多页场景的支持,又能在单个CSHTML页面中完整托管具备多页路由的Blazor应用,两者的路由系统不会互相干扰。

内容的提问来源于stack exchange,提问作者sanepete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:23:21