Blazorサーバーサイドでチャットルームアプリを作っています。各ユーザーのオンライン状態を表示したい。
私はページを閉じるときにイベントを取得する方法について質問しました ブレザーサーバー側でページを閉じるときにイベントを取得するにはどうすればよいですか?
現在、CircuitHandler
がこれに最適な選択です。
ユーザーがページを閉じたときに、データベースでユーザーの状態をオンラインからオフラインに設定したいと考えています。また、各ユーザーの主キーは、一時的に_index.razor
_に格納されます。
しかし、OnCircuitClosedAsync(Circuit, CancellationToken)
の実行後、これを達成するためのメソッドを呼び出す方法がわかりません(Blazorフロントエンドの変数を取得したり、フロントエンドのBlazorメソッドを呼び出すことができません)。
PS:これがバックエンドのコードです:
_using Microsoft.AspNetCore.Components.Server.Circuits;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace BlazorCircuitHandler.Services
{
public class CircuitHandlerService : CircuitHandler
{
public ConcurrentDictionary<string, Circuit> Circuits { get; set; }
public CircuitHandlerService()
{
Circuits = new ConcurrentDictionary<string, Circuit>();
}
public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuits[circuit.Id] = circuit;
return base.OnCircuitOpenedAsync(circuit, cancellationToken);
}
public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuit circuitRemoved;
Circuits.TryRemove(circuit.Id, out circuitRemoved);
return base.OnCircuitClosedAsync(circuit, cancellationToken);
}
public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionDownAsync(circuit, cancellationToken);
}
public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionUpAsync(circuit, cancellationToken);
}
}
}
_
そして、これがフロントエンドです:
_@page "/"
@using Microsoft.AspNetCore.Components.Server.Circuits
@inject CircuitHandler CircuitHandlerService
<h1>Hello, world!</h1>
Welcome to your new app.
<p>
Number of Circuits: @((CircuitHandlerService as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits.Count)
<ul>
@foreach (var circuit in (CircuitHandlerService as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits)
{
<li>@circuit.Key</li>
}
</ul>
@{
var PrimaryKey = "abcdefg";
}
</p>
_
手伝ってくれませんか?ありがとうございました。
回路ハンドラー内でイベントを公開するだけです。
public class CircuitHandlerService : CircuitHandler
{
public event EventHandler CircuitsChanged;
protected virtual void OnCircuitsChanged()
=> CircuitsChanged?.Invoke(this, EventArgs.Empty);
public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuits[circuit.Id] = circuit;
OnCircuitsChanged();
return Task.CompletedTask;
}
public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuits.TryRemove(circuit.Id, out var circuitRemoved);
OnCircuitsChanged();
return Task.CompletedTask;
}
}
次に、Razorコンポーネントで、そのイベントをサブスクライブし、必要に応じてUIを更新できます。
@implements IDisposable
@inject CircuitHandler circuitHandler
<ul>
@foreach (var circuit in Circuits)
{
<li>@circuit.Key</li>
}
</ul>
@code {
private IDictionary<string, Circuit> Circuits
=> (circuitHandler as CircuitHandlerService).Circuits;
protected override void OnInitialized()
{
// register event handler
(circuitHandler as CircuitHandlerService).CircuitsChanged += HandleCircuitsChanged;
}
public void Dispose()
{
// unregister the event handler when the component is destroyed
(circuitHandler as CircuitHandlerService).CircuitsChanged -= HandleCircuitsChanged;
}
public void HandleCircuitsChanged(object sender, EventArgs args)
{
// notify the UI that the state has changed
StateHasChanged();
}
}