🔖

セッションの終了を正しく検出する (Blazor Server)

2025/02/06に公開

はじめに

この記事は、以下を下敷きにしています。

https://zenn.dev/tetr4lab/articles/6b1a70ca7800ed

以下に実装例があります。

https://github.com/tetr4lab/ExLibris10

https://github.com/tetr4lab/Prices

やりたいこと

セッションの終了を検出したい場合があります。
例えば、セッション数を知りたい場合に、開始で数を増やし、終了で減らす方法が考えられます。

試行1 IDispose

IDisposeを実装することで、コンポーネントの終了を検出していました。

Xxxxx.razor
@inherits IDispose

@code {
    public void Dispose () {
        // コンポーネントが終了した際の処理
    }
}

PCのブラウザでは問題なく機能したのですが、モバイルでアプリが強制終了された際に検出できないようです。

試行2 CircuitHandler

CircuitHandlerをカスタマイズすることで、タイムアウトを含むセッションの終了を検出できました。

https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.components.server.circuits?view=aspnetcore-8.0

Program.cs
using Microsoft.AspNetCore.Components.Server.Circuits;

builder.Services.AddScoped<CircuitHandler, CircuitClosureDetector> ();
CircuitClosureDetector.cs
public class CircuitClosureDetector : CircuitHandler {
    public event Action<string>? Disconnected;
    public override Task OnCircuitClosedAsync (Circuit circuit, CancellationToken cancellationToken) {
        Disconnected?.Invoke (circuit.Id);
        if (Disconnected is not null) {
            foreach (Action<string> e in Disconnected.GetInvocationList ()) {
                Disconnected -= e;
            }
        }
        return base.OnCircuitClosedAsync (circuit, cancellationToken);
    }
}

Xxxxx.razor.cs
    [Inject] protected CircuitHandler CircuitHandler { get; set; } = null!;

    protected override async Task OnInitializedAsync () {
        await base.OnInitializedAsync ();
        if (CircuitHandler is CircuitClosureDetector handler) {
            handler.Disconnected += id => {
                // セッションが終了した際の処理
            };
        }
    }

留意点

  • ページでCircuitHandlerをインジェクトしなくても、OnCircuitClosedAsyncは呼ばれるようです。
  • ページで例外が投げられると呼ばれない場合があるので、例外への対応は別途必要です。

おわりに

お読みいただきありがとうございました。
執筆者は、Blazor、ASP.NETなど諸々において初学者ですので、誤りもあるかと思います。
お気づきの際は、是非コメントや編集リクエストにてご指摘ください。
あるいは、「それでも解らない」、「自分はこう捉えている」などといった、ご意見、ご感想も歓迎いたします。

Discussion