获取 Blazor 应用程序的所有连接用户的列表

Foi*_*itn 11 c# signalr blazor blazor-server-side

因此,我的 blazor 应用程序目前正在生产中。

我确实需要在某些时候发布新版本。我想知道当时是否有人在使用该应用程序。为此,我可以询问每个人(大约 20 名同事)是否有人在使用该应用程序。

我觉得应该有一种更简单的方法来做到这一点。现在我知道 blazor 应用程序使用 SignalR 来执行服务器和客户端之间的通信,并且当我重新启动 docker 容器时,所有连接都会重置。所以我觉得应该有一种方法可以从 SignalR Hub 请求是否有人连接到应用程序,但我还没有找到方法。

有谁知道有什么方法可以检查是否(以及谁)在 x 点及时使用该应用程序?

dan*_*era 7

最简单的方法是使用依赖注入。在 Blazor 服务器上,scoped几乎意味着“通过连接实现一个实例”

Blazor Server 托管模型支持跨 HTTP 请求的范围生命周期,但不支持跨客户端加载的组件之间的 SignalR 连接/电路消息。应用程序的 Razor Pages 或 MVC 部分正常处理作用域服务,并在页面或视图之间导航或从页面或视图导航到组件时在每个 HTTP 请求上重新创建服务。在客户端上的组件之间导航时,不会重构作用域服务,其中与服务器的通信通过用户电路的 SignalR 连接进行,而不是通过 HTTP 请求。在客户端的以下组件场景中,由于为用户创建了新的线路,因此会重构作用域服务:

  • 用户关闭浏览器窗口。用户打开一个新窗口并导航回应用程序。
  • 用户在浏览器窗口中关闭应用程序的选项卡。用户打开一个新选项卡并导航回应用程序。
  • 用户选择浏览器的重新加载/刷新按钮。

如果您可以接受将整个 SignalR 连接/电路视为“已连接用户”,则该过程非常简单。我一步步解释这个过程:

1 - 创建结构来存储已连接用户的列表

创建类来存储ConnectedUser数据和ConnectedUserList

public class ConnectedUser
{
    public string Name { get; set; } = Guid.NewGuid().ToString();
}
public class ConnectedUserList
{
    public List<ConnectedUser> Users { get; set; } = new();
}
Run Code Online (Sandbox Code Playgroud)

2 - 注入具有正确范围的类

program.cs服务上注入两个类:(ConnectedUser作用域)和ConnectedUserList(单例)将包含ConnectedUser.

// Program.cs
builder.Services.AddScoped<ConnectedUser>();
builder.Services.AddSingleton<ConnectedUserList>();
Run Code Online (Sandbox Code Playgroud)

3 - 捕获连接的用户并添加到全局列表

在 上Shared/MainLayout.razor,通过注入获取两个对象并添加到ConnectedUserConnectedUserList在登录过程或事件中,您可以更新ConnectedUser.Username为记录的用户名)

@implements IDisposable
@inject ConnectedUser _ConnectedUser
@inject ConnectedUserList _ConnectedUserList

@code {

    protected override void OnInitialized()
    {
         _ConnectedUserList.Add(_ConnectedUser )
    }

    // Don't forget to remove `ConnectedUser` from 
    // `ConnectedUserList` on dispose.
    public void Dispose()
    {
         _ConnectedUserList.Remove(_ConnectedUser )
    }
Run Code Online (Sandbox Code Playgroud)

4 - 显示所有已连接的用户

您可以随时获取ConnectedUserList并检查该列表。例如index.razor

@page "/"

@inject ConnectedUser _ConnectedUser
@inject ConnectedUserList _ConnectedUserList

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

@foreach (var user in _ConnectedUserList.Users)
{
    <p>@user.Name</p>
}
Run Code Online (Sandbox Code Playgroud)

笔记

  • 为了使答案简单,我使用了一个List结构来存储连接的用户,但List不是线程安全的。