Blazor Web App(.NET 8):如何在WebAssembly渲染页面中使用服务端渲染组件?
场景与代码示例
你在.NET 8 Blazor Web App中创建了以下内容:
WebAssembly交互渲染页面 (/counter)
@page "/counter" @rendermode InteractiveWebAssembly <PageTitle>Counter</PageTitle> <h1>Counter</h1> <p role="status">Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> <ServerSideComponent></ServerSideComponent> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
服务端交互渲染组件 (ServerSideComponent)
@rendermode InteractiveServer <p role="status">Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
尝试运行时触发了以下异常:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Cannot create a component of type 'BlazorApp4.Client.ServerSideComponent' because its render mode 'Microsoft.AspNetCore.Components.Web.InteractiveServerRenderMode' is not supported by WebAssembly rendering. System.NotSupportedException: Cannot create a component of type 'BlazorApp4.Client.ServerSideComponent' because its render mode 'Microsoft.AspNetCore.Components.Web.InteractiveServerRenderMode' is not supported by WebAssembly rendering.
问题解答
核心结论
不能直接在WebAssembly渲染的组件/页面中嵌套使用标记为InteractiveServer渲染模式的组件。WebAssembly渲染器运行在客户端浏览器环境中,无法实例化需要依赖服务器SignalR连接的服务端交互组件,这就是触发NotSupportedException的原因。
可行解决方案
要实现「页面主体用WebAssembly渲染,局部用服务端交互组件」的需求,可通过以下两种方式:
1. 用iframe嵌入服务端组件页面
- 先创建一个纯服务端交互渲染的页面(比如
/server-component-host),页面中仅包含ServerSideComponent:@page "/server-component-host" @rendermode InteractiveServer <ServerSideComponent></ServerSideComponent> - 在WebAssembly渲染的
/counter页面中,通过<iframe>嵌入这个页面:@page "/counter" @rendermode InteractiveWebAssembly <PageTitle>Counter</PageTitle> <h1>Counter</h1> <p role="status">Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> <!-- 嵌入服务端组件页面 --> <iframe src="/server-component-host" width="100%" height="120" frameborder="0"></iframe> @code { private int currentCount = 0; private void IncrementCount() => currentCount++; }
2. 利用页面静态渲染划分组件渲染区域
调整页面整体为静态服务器渲染(SSR),再分别指定不同区域的渲染模式:
@page "/counter" <!-- 页面默认以静态SSR加载 --> <!-- WebAssembly交互渲染区域 --> <div @rendermode="InteractiveWebAssembly"> <h1>Counter (Wasm)</h1> <p role="status">Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me (Wasm)</button> </div> <!-- 服务端交互渲染区域 --> <ServerSideComponent></ServerSideComponent> @code { private int currentCount = 0; private void IncrementCount() => currentCount++; }
这种方式下,页面初始由服务器静态渲染,WebAssembly区域会在客户端加载后接管交互逻辑,服务端组件则保持与服务器的SignalR连接,两者独立运行、互不干扰。
内容的提问来源于stack exchange,提问作者Steffan Pallesen

