简体   繁体   中英

.Net Core SignalR: Send to Users except caller from IHubContext (injected into controller)

in order to identify the current user only when working with an injected IHubContext in a controller, I am storing a group with the user id. However, I'm struggling to send to everyone else since I cannot figure out a way to find out which connection ID to exclude.

My Hub

public override Task OnConnectedAsync()
{

    Groups.AddAsync(Context.ConnectionId, Context.User.Identity.Name);  
    return base.OnConnectedAsync();
}

In my controller method, I can invoke methods for that user:

await _signalRHub.Clients.Group(User.Identity.Name).InvokeAsync("Send", User.Identity.Name + ": Message for you");

IHubContext.Clients.AllExcept requires a list of connection IDs. How can I obtain the connection ID for the identified user in order to only notify others?

As suggested by @Pawel, I am now de-duping on the client, which works (well, as long as all your clients are authenticated).

private async Task Identification() => await Clients.Group(Context.User.Identity.Name).InvokeAsync("Identification", Context.User.Identity.Name);
public override async Task OnConnectedAsync()
{    
    await Groups.AddAsync(Context.ConnectionId, Context.User.Identity.Name);            
    await base.OnConnectedAsync();
    await Identification();
}

The JS to go along with it (abbreviated):

var connection = new signalR.HubConnection("/theHub");            
var myIdentification;
connection.on("Identification", userId => {
    myIdentification = userId;
});

Now you can test for callerIdentification == myIdentification in addtional methods like connection.on("something", callerIdentification)

@Tester's comment makes me hopeful there'll be a better way at some point when sending through IHubContext.

In SignalR core, the connectionId is stored in the signalR connection. Assuming you have a signalrR connection defined as follows

signalrConnection = new HubConnectionBuilder()
.withUrl('/api/apphub')
...
.build();

Whenever you make a fetch request, add the signalR connectionId as a header. Eg.

        response = await fetch(url, {
        ...
        headers: {
            'x-signalr-connection': signalrConnection.connectionId,
        },
    });

Then in your controller or wherever you have access to a httpContextAccessor, you can use the following to exclude the connection referenced in the header:

    public async Task NotifyUnitSubscribersExceptCaller()
{
    //Grab callers connectionId
    var connectionId = _httpContextAccessor.HttpContext?.Request.Headers["x-signalr-connection"] ?? "";
    await _hub.Clients.GroupExcept("myGroup", connectionId).SendCoreAsync("Sample", new object[] { "Hello World!" });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM