Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Parameterise (somehow) the connection process so the client can pass some information to the hub #961

Closed
williamBurgeson opened this issue Sep 28, 2017 · 9 comments
Milestone

Comments

@williamBurgeson
Copy link

Feature request

This is to some extent a continuation of #788, which I've just closed.

We're building a scoreboard app, whereby the displays (all build using angular) register with signalr upon start-up in order to receive periodic score (and other data) updates.

Using the older jquery based code we were grabbing the connection id and registering that with our own data store to determine which message from the external system should be registered to which scoreboard(s).

As connection id is no longer publicly exposed (and therefore by definition not supported) we need a way for the client to actively tell SignalR (or at least the server code in general) who it is.

The only way offered seems to be to authenticate and connect as a "user", which in our case is quite significant overkill.

Is there a way, for example a URL param or similar, to connect with a parameter, e.g. /hubs/target/455aef9f-be8e-4384-94bd-52eeb175d074, where I'm passing the guid as a param which my code can then say "OK, you're connection X, I will register you as required", in a similar way to how standard mvc endpoints work.

Otherwise, would it be necessary to write code within the hub to filter "registration" messages ("hello, I am 455aef9f-be8e-4384-94bd-52eeb175d074") as opposed to other normal application messages.

Looking for guidance as much as making a change really...

@davidfowl
Copy link
Member

  • Pass that guid on the query string from the client
  • Grab the query string in OnConnectedAsync and add the client to a group with that guid
  • Send to that group
  • profit!

Client

let connection = new signalR.HubConnection('/chat?sessionId=455aef9f-be8e-4384-94bd-52eeb175d074');

Server

public class MyHub : Hub
{
    public override Task OnConnectedAsync()
    {
        var sessionId = Context.Connection.GetHttpContext().Request.Query["sessionId"];

        return Groups.AddAsync(Context.ConnectionId, sessionId);
    }
}

Other code:

Clients.Group(sessionId).InvokeAsync("Whatever", args);

@KPixel
Copy link

KPixel commented Sep 28, 2017

We could use this technique with #684 to pass a connectionId directly.
But I think that letting the client choses its own connectionId could pose some potential problems...

What do you think?

@davidfowl
Copy link
Member

I think the connection id needs to be tightly controlled by signalr and treated as internal. I'm fine introducing a user controlled surrogate though (which honestly today is the "userId"). We just need to expose some extensibility (#604) so that it's possible to replace the existing hard coded logic.

@KPixel
Copy link

KPixel commented Sep 28, 2017

The UserId extensibility would be a great feature for some scenarios.
However, it can't be a surrogate for the ConnectionId since a user could have many devices connected, so you can't use the UserId if you want to target a specific device.

I am fine with the ConnectionId being internal at the SignalR layer, but I would hope that it isn't required to be as tightly controlled when using the Sockets layer.
Would there ever be a future where the ConnectionId ceases to exist (at the Sockets layer)?

@davidfowl And I see you closed #684 but, on top of what we are discussing here, that API is meant to enable a lot more features (like the cluster system that I described).
Can you reconsider it?

@davidfowl
Copy link
Member

@KPixel nobody is using the sockets layer today but SignalR and yourself (and it's going to change a lot because it's the least fleshed out thing that exists today). That bug doesn't call out the sockets layer at all, and also mentions JWT. If you're looking to replace the connection id at the sockets layer then file another issue because in the real implementation, that ID will be controlled at a much lower level and there's no way to plug in that low today.

If you're just looking at storing your own unique ID outside of SignalR then just stash a guid in the connection metadata.

@KPixel
Copy link

KPixel commented Sep 28, 2017

@davidfowl I am fine with the Sockets layer changing a lot, with the hope that I don't lose the features that I am currently relying on.

#684 discusses ConnectionManager.MakeNewConnectionId() which is part of the Sockets layer.
But I guess I shouldn't have used the name "SignalR Cluster" after that (it should be "Sockets Cluster" or just "cluster").
Anyway, I am fine with recreating the issue...

The main question is: When you say "there's no way to plug in that low today", I don't understand why not. It seems that we can configure all kind of services in Startup or even in Program.Main().

@davidfowl
Copy link
Member

@KPixel Why you need your connection id to replace the existing one instead of just using another metadata entry?

@KPixel
Copy link

KPixel commented Sep 28, 2017

@davidfowl I just finished refactoring my code, and it turned out to be quite painless to use a custom key to identify connections.

And I think the other scenarios discussed in #684 could be handled with this technique.

Thank you for your time :)

@williamBurgeson Feel free to close this issue if you are happy.

@williamBurgeson
Copy link
Author

williamBurgeson commented Sep 28, 2017

My set up is a little bit more complex, however that's our issue rather than with signalr - I'm happy to allow the team to close this issue as it does seem to answer everything.

@davidfowl This scenario (or a related one) will be a very good example for the docs :)

#signalrNetCore #signalrCustomConnectionId

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants