4

To set the right context, let me explain the problem. Till RC1, we used to implement GenerateConnectionIdPrefix() to prefix user Id to the connection Id. Then we could retrieve user id from the connection string anytime we need.

With RC2, we now cannot inherit IConnectionIdPrefixGenerator & implement GenerateConnectionIdPrefix anymore. So I was wondering what are other avenues available to set any property on the hub with our data, that persists throughout the lifetime of the connection.

Going through documentation, I realized setting query strings is one way, but that would mean we need to set it for every call. Setting a round trip state might be another option, but it looks like even that is persistent for a single round-trip and not entire lifetime.

So my end goal is set to property once at start on SignalR connection that can be used throughout the connection lifetime.

If there is nothing available now, are there any plans to add support to achieve something similar in next version?

[Update] As suggested below, I tried to set a state Clients.Caller.Userid in the OnConnected method, then tried to access it in the subsequent call, I found that its null. Both calls are from same connection Id.

Gourav Das
  • 67
  • 2
  • 8
  • if we look at [this thread](http://stackoverflow.com/questions/14511645/signalr-rc2-no-iconnectionidprefixgenerator-support-any-more) it says "will be added in future". If we can set peristent states from both Server/client side why is anything else required to add for setting/retrieving custom data? – Gourav Das Jan 29 '13 at 05:14

1 Answers1

9

Look at the "Round-tripping state between client and server" section on https://github.com/SignalR/SignalR/wiki/Hubs.

Basically you can read and write from dynamic properties on Clients.Caller in Hub methods such as OnConnected or anything invoked by a client. Ex:

using System;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;

namespace StateDemo
{
    public class MyHub : Hub
    {
        public override Task OnConnected()
        {
            Clients.Caller.UserId = Context.User.Identity.Name;
            Clients.Caller.initialized();
            return base.OnConnected();
        }

        public void Send(string data)
        {
            // Access the id property set from the client.
            string id = Clients.Caller.UserId;

            // ...
        }
    }
}

State that is stored this way will be persisted for the lifetime of the connection.

If you want to learn how to access this state using the SignalR JS client look at the "Round-tripping state" section of https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client-Hubs.

There are other ways to keep track of users without IConnectionIdPrefixGenerator discussed in the following SO answer: SignalR 1.0 beta connection factory

Community
  • 1
  • 1
halter73
  • 15,059
  • 3
  • 49
  • 60
  • We already are maintaining few business logic related structures. I don't want to add anything more to map Userids and connection, since that adds maintainability headache I am also concerned about the "persistent" part of setting state. Because, in the OnConnected(), I set `Clients.Called.User = somename;` but when trying to extract that value in the subsequent function that is called, it returns null. If I am able to fix this, my problem would be solved for the now. I say for now because in another thread I read that next version would have facility to extract custom data, set elsewhere. – Gourav Das Jan 29 '13 at 03:18
  • You must invoke a client-side hub method before the state will be persisted. I changed the above sample code to include a call to ```Clients.Caller.initialized()```. If the client makes any server-side hub method invocations before it receives its call ```initialized``` the state will not be available during the invocation. – halter73 Jan 29 '13 at 04:25
  • NOTE: It is not necessary to invoke methods after modifying state outside of the ```On*``` methods. – halter73 Jan 29 '13 at 04:36
  • Thanks a lot, let me try it. – Gourav Das Jan 29 '13 at 05:12