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

.NET 8中如何实现Blazor Server与Blazor WebAssembly共存运行?

.NET 8中Blazor WebAssembly与服务器端渲染共存的解决方案

针对你遇到的WASM入口无法初始化、客户端专属服务报错的问题,下面是几种可行的实现方案:

方案1:按路由拆分渲染逻辑

在Server项目的App.razor里,根据访问路径判断是用SSR还是WASM模式,分别加载对应程序集的路由:

@using Client
@using Server
@inject NavigationManager NavigationManager

@{
    var currentPath = NavigationManager.Uri;
    // 定义需要SSR的路径,比如登录、重定向页
    var useServerRender = currentPath.Contains("/login") || currentPath.Contains("/redirect");
}

@if (useServerRender)
{
    <Router AppAssembly="@typeof(Server.Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(Server.Shared.MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(Server.Shared.MainLayout)">
                <p>服务器端页面未找到</p>
            </LayoutView>
        </NotFound>
    </Router>
}
else
{
    <Router AppAssembly="@typeof(Client.Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(Client.Shared.MainLayout)" 
                       @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(Client.Shared.MainLayout)">
                <p>客户端页面未找到</p>
            </LayoutView>
        </NotFound>
    </Router>
}

注意:Server项目必须引用Client项目,才能访问客户端的布局和组件。

方案2:通过端点配置区分渲染模式

在Server项目的Program.cs中,针对不同路径配置不同的根组件和渲染模式:

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

var app = builder.Build();

// 配置SSR专属路径(登录、重定向)
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/login") || ctx.Request.Path.StartsWithSegments("/redirect"), subApp =>
{
    subApp.MapRazorComponents<Server.App>()
        .AddInteractiveServerRenderMode()
        .AddAdditionalAssemblies(typeof(Server.Program).Assembly);
});

// 配置WASM应用的默认路径
app.MapRazorComponents<Client.App>()
    .AddInteractiveWebAssemblyRenderMode(prerender: false)
    .AddAdditionalAssemblies(typeof(Client.Program).Assembly);

这种方式需要给Server和Client分别创建独立的App.razor,各自管理对应模式下的路由规则。

方案3:组件级指定渲染模式(混合页面场景)

如果只是部分页面需要SSR,其余保持WASM,可以在统一使用Client路由的基础上,给特定页面标记SSR模式:

  1. 保持Server项目App.razor指向Client程序集:
<Router AppAssembly="@typeof(Client.Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(Client.Shared.MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(Client.Shared.MainLayout)">
            <p>页面未找到</p>
        </LayoutView>
    </NotFound>
</Router>
  1. 在需要SSR的页面(比如Login.razor)顶部添加渲染模式标记:
@page "/login"
@rendermode InteractiveServerRenderMode

<h1>登录页(SSR)</h1>
<!-- 登录表单内容 -->
  1. 在Server项目Program.cs中同时注册两种渲染模式:
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

app.MapRazorComponents<Client.App>()
    .AddInteractiveWebAssemblyRenderMode(prerender: false)
    .AddInteractiveServerRenderMode()
    .AddAdditionalAssemblies(typeof(Server.Program).Assembly);

这种方案下,WASM的Program.cs会正常初始化,只有标记了SSR的页面会在服务器端渲染,避免客户端专属服务在服务器端执行报错。

核心注意事项

  • 客户端专属操作(比如localStorage、IJSRuntime调用)必须放到OnAfterRenderAsync生命周期里,或者用OperatingSystem.IsBrowser()判断环境后再执行,防止服务器端渲染时触发错误:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender && OperatingSystem.IsBrowser())
    {
        // 仅在浏览器环境执行客户端逻辑
        var storedValue = await localStorage.GetItemAsync<string>("user_token");
    }
}
  • 确保Server项目正确引用Client项目,共享组件和服务要保证两端都能访问。
  • SSR页面里不要引用仅客户端可用的组件或服务,避免服务器端实例化失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:17:08