参照文档指引,准备用.NET 8的Blazor和LiteDB撸个小项目,结果引入的LiteDB相关代码一直无法访问目录中的数据库,重建了好几次项目都无果。琢磨了半天才发现自己踩了新版本Blazor的呈现模式(RenderMode)的坑。看来还是要持续学习.NET新技术,跟上时代步伐!
解决方案
先给出我琢磨出来的解决方案,有两种办法
- 在引用LiteDB数据库的Razor页面最上方,使用@rendermode指令声明该页面的呈现模式为InteractiveServer,即交互式SSR模式
@page "..."
@rendermode InteractiveServer
- 在应用的App.razor页面Routes标签内,声明应用整体的呈现模式为InteractiveServer
<body>
<Routes @rendermode="RenderMode.InteractiveServer" />
</body>
问题原理
问题的根源在于.NET 8版本之后,新的Blazor框架集成了之前的Blazor Server和Blazor Wasm两种托管模型,并且使用“渲染模式”定制整个应用乃至具体页面的呈现方式。根据文档,渲染模式共有四种:
名称 | 描述 | 呈现位置 | 交互 |
---|---|---|---|
静态服务器(Static Server) | 静态服务器端呈现(静态 SSR) | 服务器 | ❌否 |
交互式服务器(InteractiveServer) | 使用 Blazor Server 的交互式服务器端呈现(交互式 SSR)。 | 服务器 | ✔️是 |
交互式 WebAssembly(Interactive WebAssembly) | 使用 Blazor WebAssembly 的客户端呈现 (CSR)†。 | 客户端 | ✔️是 |
交互式自动(Interactive Auto) | 下载 Blazor 捆绑包后,在后续访问时先使用 Blazor Server 然后使用 CSR 的交互式 SSR。 | 服务器,然后客户端 | ✔️ |
四种模式里,Static Server即静态托管按下不表,InteractiveServer对应的就是之前的Blazor Server,Interactive WebAssembly对应Blazor Wasm,这都没问题。问题出在新增的Interactive Auto上。
按照微软设想,Interactive Auto可以实现应用模式的灵活切换。理想状态下应用初次加载或网络条件优良时在该模式下启用SSR服务端渲染,网络不佳或再次加载时切换到Wasm模式。应用的切换逻辑则由页面上的@rendermode指令或整个应用的Routes组件决定。
那么,如果没有指定页面的@rendermode指令怎么办呢?如果父级有指定过呈现模式,那么组件会继承其呈现模式,这就对应了上面解决方案里的方法二:通过为应用的路由组件指定呈现模式,让子页面继承。但如果父组件没有指定过呈现模式,组件自己也没有指定过呈现模式,运行时就默认会对该页面使用Static Server呈现模式。该模式下无法运行事件处理程序,当然也无法读写数据库,所以我们需要手动为应用指定呈现模式,这是解决方法一背后的原理。
参考资料:
- https://chrissainty.com/blazor-in-dotnet-8-full-stack-web-ui/
- https://learn.microsoft.com/zh-cn/aspnet/core/blazor/components/render-modes?view=aspnetcore-8.0