如何在 Blazor 服务器端的 CircuitHandler 中调用方法? [英] How can I invoke method in CircuitHandler of Blazor server-side?
问题描述
我正在通过 Blazor 服务器端制作聊天室应用程序.我想显示每个用户的在线状态.
I am making a chatroom application by Blazor server-side. I want to show the online state of each user.
现在看来 CircuitHandler
是最好的选择.
Now it seems the CircuitHandler
is the best choice for this.
当用户关闭页面时,我想在数据库中设置一个用户状态从在线到离线.而且,每个用户的主键临时存储在 index.razor
中.
When the user closes the page, I want to set a user state from online to offline in the database. And also, the primary key of each user is temporarily storing in the index.razor
.
但是现在OnCircuitClosedAsync(Circuit, CancellationToken)
运行后,我不知道如何调用一个方法来实现这一点(我无法获取Blazor前端的变量或调用前端的 Blazor 方法).
But now after the OnCircuitClosedAsync(Circuit, CancellationToken)
runs, I don't know how to invoke a method to achieve this (I can't get the variable of Blazor front-end or invoke the Blazor method of front-end).
附注:这是后端的代码:
PS: Here is the code of the back-end:
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>
你能帮我吗?谢谢.
推荐答案
这应该有效,我猜 ;)
This should be working, I guess ;)
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());
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
}
注意:要验证它是否正常运行,请运行该应用程序.然后再打开两个标签.现在,关闭您打开的第一个选项卡(从左到右),然后关闭第二个选项卡.注意活动回路数的显示...
Note: To verify that it is working run the app. Then open another two tabs. Now, close the first tab you open (left to right), then the second. Notice the display of the number of active circuits...
这篇关于如何在 Blazor 服务器端的 CircuitHandler 中调用方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!