Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disconnect client from IHubContext<THub>

I can call InvokeAsync from server code using the IHubContext interface, but sometimes I want to force these clients to disconnect.

So, is there any way to disconnect clients from server code that references the IHubContext interface?

like image 672
Carlos Beppler Avatar asked Oct 10 '17 18:10

Carlos Beppler


1 Answers

Step 1:

using Microsoft.AspNetCore.Connections.Features;
using System.Collections.Generic;
using Microsoft.AspNetCore.SignalR;

public class ErrorService
{
    readonly HashSet<string> PendingConnections = new HashSet<string>();
    readonly object PendingConnectionsLock = new object();

    public void KickClient(string ConnectionId)
    {
        //TODO: log
        if (!PendingConnections.Contains(ConnectionId))
        {
            lock (PendingConnectionsLock)
            {
                PendingConnections.Add(ConnectionId);
            }
        }
    }

    public void InitConnectionMonitoring(HubCallerContext Context)
    {
        var feature = Context.Features.Get<IConnectionHeartbeatFeature>();

        feature.OnHeartbeat(state =>
        {
            if (PendingConnections.Contains(Context.ConnectionId))
            {
                Context.Abort();
                lock (PendingConnectionsLock)
                {
                    PendingConnections.Remove(Context.ConnectionId);
                }
            }

        }, Context.ConnectionId);
    }
}

Step 2:

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddSingleton<ErrorService>();
        ...
    }

Step 3:

[Authorize(Policy = "Client")]
public class ClientHub : Hub
{
    ErrorService errorService;

    public ClientHub(ErrorService errorService)
    {
        this.errorService = errorService;
    }

    public async override Task OnConnectedAsync()
    {
        errorService.InitConnectionMonitoring(Context);
        await base.OnConnectedAsync();
    }
....

Disconnecting without Abort() method:

public class TestService
{
    public TestService(..., ErrorService errorService)
    {
        string ConnectionId = ...;
        errorService.KickClient(ConnectionId);
like image 194
Petr Tripolsky Avatar answered Dec 04 '22 06:12

Petr Tripolsky