如何在 Blazor Server 中获取访客数和连接数

在使用Blazor Server开发的时候,在一些特定场景下,我们可能需要获取访客的连接数(一个访客打开多个页面产生的连接数)或者访客数量

先看看最终效果

879de4492b3028c86ed2bbc435195bef.jpeg


首先我们需要创建一个自定义的CircuitHandler,Circuit表示的是服务器上ASP.NET Core组件与客户端之间的链接,CircuitHandler则是类似拦截器,在建立链接时会触发

//Circuit客户端的基本信息
public class CircuitClientInfo
{
    public string CircuitId { get; set; } = "";
    public DateTimeOffset JoinDateTime { get; set; } = DateTimeOffset.Now;
}

//使用静态方法记录Circuit连接的客户端,全局的,并且线程安全的
public static class CircuitTrackerGlobalInfo
{
    public static ConcurrentDictionary<string, CircuitClientInfo> CircuitClients { get; set; } = new();
    public static ConcurrentDictionary<string, string> VisitorClients { get; set; } = new();
}

public class CircuitTracker : CircuitHandler
{
    private CircuitClientInfo _circuitInfo = new();
    private string _visitorId = "";

    public int ConnectionCount => CircuitTrackerGlobalInfo.CircuitClients.Count;
    public int VisitorCount => CircuitTrackerGlobalInfo.VisitorClients.GroupBy(x => x.Value).Count();

    public string CircuitId => _circuitInfo.CircuitId;
    public string VisitorId => _visitorId;

    public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        _circuitInfo.CircuitId = circuit.Id;
        _circuitInfo.JoinDateTime = DateTimeOffset.Now;
        CircuitTrackerGlobalInfo.CircuitClients.TryAdd(circuit.Id, _circuitInfo);
        return Task.CompletedTask;
    }

    public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        CircuitTrackerGlobalInfo.CircuitClients.TryRemove(circuit.Id, out _);
        CircuitTrackerGlobalInfo.VisitorClients.TryRemove(circuit.Id, out _);
        return Task.CompletedTask;
    }

    public void VisitorRegister(string visitorId)
    {
        _visitorId = visitorId;
        CircuitTrackerGlobalInfo.VisitorClients.TryAdd(CircuitId, visitorId);
    }
}

然后在Program.cs以Scoped生命周期注入,给每个连接的客户端都分配一个Circuit跟踪器

builder.Services.AddScoped<CircuitHandler, CircuitTracker>();

然后在App.razor或者index.html的head部分加入以下js代码,用于获取浏览器指纹,判断唯一访客

<script>
    function getVisitorId() {
        return import('https://openfpcdn.io/fingerprintjs/v4')
            .then(FingerprintJS => FingerprintJS.load())
            .then(fp => fp.get())
            .then(result => {
                return result.visitorId;
            });
    }
</script>

然后在你想要的页面按下面的例子实现就可以啦

@page "/counter"
@using Microsoft.AspNetCore.Components.Server.Circuits
@rendermode InteractiveServer //这个很重要,需要在服务端渲染
@inject CircuitHandler CircuitTracker
@inject IJSRuntime _jSRuntime

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @circuitTracker.ConnectionCount</p>
<p role="status">Visitor count: @circuitTracker.VisitorCount</p>
<p role="status">CircuitId: @circuitTracker.CircuitId</p>
<p role="status">VisitorId: @circuitTracker.VisitorId</p>

@code{
    private CircuitTracker circuitTracker;

    protected override void OnInitialized()
    {
        circuitTracker = (CircuitTracker)CircuitTracker;
        base.OnInitialized();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            var visitorId = await _jSRuntime.InvokeAsync<string>("getVisitorId");
            //因为获取访客ID是通过js获取的,所以需要在页面渲染了后调用,并且注册到跟踪器
            (CircuitTracker as CircuitTracker)!.VisitorRegister(visitorId);
            StateHasChanged();
        }
        await base.OnAfterRenderAsync(firstRender);
    }
}

源码例子可以查看原文,或者访问(https://gitee.com/imxcstar/blazor-server-visitor-demo.git)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值