.NET/ASP.NET/Blazor FAQ

如何知道我需要手动调用Dispose/DisposeAsync

  1. 当你的对象实现了IDispose/IDisposeAsync时,通常来说需要调用Dispose/DisposeAsync来手动释放非托管内存。
  2. 若你的对象是通过IoC容器管理时,通常不需要手动调用Dispose/DisposeAsync;但Factory产生的对象通常不归IoC容器管理,因此也需要手动释放。(例如:AddDbContext方式通过IoC容器管理,因此不需要手动释放;而AddDbContextFactory方式则不通过IoC容器管理,需要手动释放)
  3. 通过监控运行时内存,得知对象及其所属非托管内存未在必要的时候释放,也需要增加手动释放的代码。

.NET 8 Blazor四种渲染模式有什么区别 

  1. Static:此模式不支持Blazor交互(包含wasm和server),但可以通过JavaScript来进行页面内交互(比较类似于传统MVC框架)
  2. Interactive Server:与以前的Blazor Server一致,通过SignalR链接进行交互,需要保持SignalR连接才能使用
  3. Interactive WebAssembly:与以前的Blazor WebAssembly一致,通过wasm进行交互
  4. 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部分页面使用不同渲染模式

有两种方法。

  1. App.razor中不指定渲染模式,而是在每个页面/组件中指定渲染模式
    例如:在页面/组件中,使用@rendermode xxx指定渲染模式,或者在某个需要特殊指定的组件上加上属性@rendermode="xxx"
  2. 在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之间,我应该选择谁

这是一个经典的技术选型的问题,在选择前,先问自己几个问题:

  1. 你需要页面渲染吗(MVC架构)
  2. 你的端点数量有多少(即有多少个API接口/页面)
  3. 你需要模块化吗

把这几个问题想明白,相信答案自然呼之欲出。如果你还是没想明白,这里是几个建议:

  1. 如果需要MVC,那么Controller明显是最佳选择。当然,一些特殊接口,你不需要页面渲染,也可以混用Minimal API,取决于你怎么组织代码。
  2. 如果你的端点数量较多,那么使用Controller是一个较好的选择;反之,使用Minimal API会简化一些代码。
  3. Controller带来的是模块化的便利,使代码的可读性提升;Minimal API则注重于快速实现功能,减少特性声明,简化代码结构。
  4. 当你不知道该怎么做时,Controller永远是最佳选项!

发表评论