我正在Blazor服务器端制作一个聊天室应用程序。我想显示每个用户的在线状态。
我问了一个问题,有关如何在How can I get the event while page close in blazor server-side?中关闭页面的同时获取活动
现在看来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>
你能帮我吗?谢谢。
答案 0 :(得分:5)
这应该是有效的,我想;)
using Microsoft.AspNetCore.Components.Server.Circuits;
using System;
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 event EventHandler CircuitsChanged;
protected virtual void OnCircuitsChanged()
=> CircuitsChanged?.Invoke(this, EventArgs.Empty);
public CircuitHandlerService()
{
Circuits = new ConcurrentDictionary<string, Circuit>();
}
public override Task OnCircuitOpenedAsync(Circuit circuit,
CancellationToken cancellationToken)
{
Circuits[circuit.Id] = circuit;
OnCircuitsChanged();
return base.OnCircuitOpenedAsync(circuit,
cancellationToken);
}
public override Task OnCircuitClosedAsync(Circuit circuit,
CancellationToken cancellationToken)
{
Circuit circuitRemoved;
Circuits.TryRemove(circuit.Id, out circuitRemoved);
OnCircuitsChanged();
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
@using BlazorCircuitHandler.Services
@inject CircuitHandler circuitHandler
@implements IDisposable
<h1>Hello, world!</h1>
Welcome to your new app.
<p>
Number of Circuits: @((circuitHandler as
BlazorCircuitHandler.Services.CircuitHandlerService).Circuits.Count)
<ul>
@foreach (var circuit in (circuitHandler as
BlazorCircuitHandler.Services.CircuitHandlerService).Circuits)
{
<li>@circuit.Key</li>
}
</ul>
</p>
@code {
protected override void OnInitialized()
{
// Subscribe to the event handler
(circuitHandler as CircuitHandlerService).CircuitsChanged +=
HandleCircuitsChanged;
}
public void Dispose()
{
// Unsubscribe the event handler when the component is disposed
(circuitHandler as CircuitHandlerService).CircuitsChanged -=
HandleCircuitsChanged;
}
public void HandleCircuitsChanged(object sender, EventArgs args)
{
// notify the component that its state has changed
// Important: You must use InvokeAsync
InvokeAsync(() => StateHasChanged());
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
}
注意:要验证其是否正常运行,请运行该应用程序。然后打开另外两个标签。现在,关闭打开的第一个选项卡(从左到右),然后关闭第二个选项卡。注意显示的活动电路数...
答案 1 :(得分:0)
您可以在电路处理程序中公开一个事件:
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();
}
}