如何知道我需要手动调用Dispose/DisposeAsync
- 当你的对象实现了IDispose/IDisposeAsync时,通常来说需要调用Dispose/DisposeAsync来手动释放非托管内存。
- 若你的对象是通过IoC容器管理时,通常不需要手动调用Dispose/DisposeAsync;但Factory产生的对象通常不归IoC容器管理,因此也需要手动释放。(例如:AddDbContext方式通过IoC容器管理,因此不需要手动释放;而AddDbContextFactory方式则不通过IoC容器管理,需要手动释放)
- 通过监控运行时内存,得知对象及其所属非托管内存未在必要的时候释放,也需要增加手动释放的代码。
.NET 8 Blazor四种渲染模式有什么区别
- Static:此模式不支持Blazor交互(包含wasm和server),但可以通过JavaScript来进行页面内交互(比较类似于传统MVC框架)
- Interactive Server:与以前的Blazor Server一致,通过SignalR链接进行交互,需要保持SignalR连接才能使用
- Interactive WebAssembly:与以前的Blazor WebAssembly一致,通过wasm进行交互
- Interactive Auto:是一个全新的模式,首先第一次访问会通过Server模式加载DOM,然后在后台下载wasm,第二次载入页面(Enhanced Navigation或刷新页面)时wasm已经下载完成的情况下,会使用WebAssembly模式。
可见,新的Blazor渲染模式整合了三种传统模式,并提供了较为好用的Handler。
在Static模式下,如何实现表单提交
Static模式下,若要提交表单,可以使用EditorForm。
在OnSubmit参数指定一个处理函数,提交表单时会产生一个http请求,该请求将会执行OnSubmit指定的函数,从而实现表单提交功能。
如果需要提交后跳转,不能使用NavigationManager,因为该操作需要在OnAfterRender时才能执行。可以“篡改”HttpContext.Response输出内容来实现跳转。
同时,EditorForm还支持Enhance模式,即对请求的内容进行页面增量变化。例如:
@if (_loginSuccess)
{
<div>Login Success!</div>
}
<EditForm Model="User" OnSubmit="UserLogin" Enhance>
<InputText @bind-Value="User.Username" placeholder="Username" />
<InputText type="password" @bind-Value="User.Password" placeholder="Password" />
<button type="submit">Login</button>
</EditForm>
@code {
[SupplyParameterFromForm]
private User? User { get; set; }
private bool _loginSuccess;
protected override void OnInitialized()
{
User ??= new User();
}
private void UserLogin()
{
_loginSuccess = true;
}
}
这段代码的作用是:在用户提交表单后,将“Login Success!”显示在页面上。注意,此时页面并未发生“刷新”,而是直接进行了DOM更新。这就是Blazor对Static SSR的一个优化:Enhanced Navigation,也就是以前的pjax,在不整体刷新页面的情况下更新部分内容。从结果上来说,与Server和WebAssembly的效果类似,同时也不需要SignalR和wasm,算是简单表单页面的一个最佳实践。这个方法通常用在Server模式的认证页面,例如登录、注册等,传统的方式还需要引入MVC,使用该方法可以避免引入MVC。
如何让Blazor部分页面使用不同渲染模式
有两种方法。
- App.razor中不指定渲染模式,而是在每个页面/组件中指定渲染模式
例如:在页面/组件中,使用@rendermode xxx指定渲染模式,或者在某个需要特殊指定的组件上加上属性@rendermode="xxx" - 在App.razor中指定渲染模式,但根据Path不同来指定渲染模式,例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <base href="/"/> <HeadOutlet @rendermode="RenderModeForPage"/> </head> <body> <Routes @rendermode="RenderModeForPage"/> <script src="_framework/blazor.web.js"></script> </body> </html> @code { [CascadingParameter] public required HttpContext HttpContext { get; set; } private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Auth") ? null : RenderMode.InteractiveServer; }
效果为:在/Auth开头的页面使用Static SSR,在其他页面使用InteractiveServer。
在Minimal API和Controller之间,我应该选择谁
这是一个经典的技术选型的问题,在选择前,先问自己几个问题:
- 你需要页面渲染吗(MVC架构)
- 你的端点数量有多少(即有多少个API接口/页面)
- 你需要模块化吗
把这几个问题想明白,相信答案自然呼之欲出。如果你还是没想明白,这里是几个建议:
- 如果需要MVC,那么Controller明显是最佳选择。当然,一些特殊接口,你不需要页面渲染,也可以混用Minimal API,取决于你怎么组织代码。
- 如果你的端点数量较多,那么使用Controller是一个较好的选择;反之,使用Minimal API会简化一些代码。
- Controller带来的是模块化的便利,使代码的可读性提升;Minimal API则注重于快速实现功能,减少特性声明,简化代码结构。
- 当你不知道该怎么做时,Controller永远是最佳选项!