SignalR - Send message OnConnected

橙三吉。 提交于 2019-12-12 07:49:52

问题


I've been experimenting with SignalR today and It's really neat. Basically what I wanted to achieve is the following:

As soon as a device connects it should send a message to the first one. If there are more devices than 1 connected I would like to send two messages. One to all except the last connected client. And one message to only the last connected client.

The code I've been using works perfect when I place it in a custom API controller and basically call the action, but that's not what I want.

I would like to send the messages as soon as a device connects within OnConnected without any user interaction, but when I place my code inside the OnConnected override it stops working. It doesn't send to the specific clients anymore (first connected and last connected).

I hope someone is able to help me out with this, because I've been banging my head for a few hours now.

    public override System.Threading.Tasks.Task OnConnected()
    {
        UserHandler.ConnectedIds.Add(Context.ConnectionId, UserHandler.ConnectedIds.Count + 1);

        int amountOfConnections = UserHandler.ConnectedIds.Count;
        var lastConnection = UserHandler.ConnectedIds.OrderBy(x => x.Value).LastOrDefault();
        var allExceptLast = UserHandler.ConnectedIds.Take(amountOfConnections - 1).Select(x => x.Key).ToList();

        if (amountOfConnections == 1)
        {
            Clients.Client(UserHandler.ConnectedIds.First().Key).hello("Send to only(also first) one");
        }
        else
        {
            Clients.Clients(allExceptLast).hello("Send to everyone except last");
            Clients.Client(lastConnection.Key).hello("Send to only the last one");
        }

        return base.OnConnected();
    }

回答1:


Unless I miss something from your question, the solution looks pretty simple to me, you just need to switch to using

Clients.Caller.hello("Send to only the last one");

instead of trying to understand yourself who's the last connected id. Same for the other ones, you can use:

Clients.Others.hello("Send to everyone except last");

You do not need all the logic you setup, those 2 lines do what you need, and they work inside OnConnected.




回答2:


Thanks for all the help (upvoted you guys). Actually found the problem.. it was inside my client. I first subscribed to the 'hello' function and after that I started the HubConnection. As soon as I changed this order everything worked fine.

It worked with the following client code:

    private async Task ConnectToSignalR()
    {
        var hubConnection = new HubConnection("url");
        hubConnection.Headers["x-zumo-application"] = "clientapikey";

        IHubProxy proxy = hubConnection.CreateHubProxy("ChatHub");

        proxy.On<string>("hello", async (msg) =>
        {
            Console.WriteLine(msg);
        });

        await hubConnection.Start();
    }



回答3:


Since you haven't established a connection yet, trying to call your client .hello() function within OnConnected is not possible at this point. However, we can define a server hub method and immediately call that upon our connection .done callback. Then, in our new server method we can reallocate the logic you currently have in OnConnected.

This will change our setup quite a bit and introduce some additional steps, but observe the following example...

// WhateverHub
public override Task OnConnected()
{
    return base.OnConnected()
}

public void AfterConnected()
{
    // if(stuff) -- whatever if/else first user/last user logic
    // {
        Clients.Caller.hello("message")
    // }
}

var proxy= $.connection.whateverHub;

proxy.client.hello = function(message) {
    // last step in event chain
}

$.connection.hub.start().done(function () {
    proxy.server.afterConnected() // call AfterConnected() on hub
});

So the basic idea here is to first

  1. Connect => .done(function() { ... });
  2. Call server.afterConnected()
  3. Execute logic within that method
  4. If we're satisfied with conditions call our .hello() client function

Note - this implementation is for a JavaScript client - but the same idea can be translated to a .net client. This is mostly an architectural issue.




回答4:


well... you are returning a task... so i think that may be the issue... you should first execute your code and then return the task... or put a ContinueWith... like...

    public override Task OnConnected()
    {
        Task task = new Task(() =>
            {
                UserHandler.ConnectedIds.Add(Context.ConnectionId, UserHandler.ConnectedIds.Count + 1);

                int amountOfConnections = UserHandler.ConnectedIds.Count;
                var lastConnection = UserHandler.ConnectedIds.OrderBy(x => x.Value).LastOrDefault();
                var allExceptLast = UserHandler.ConnectedIds.Take(amountOfConnections - 1).Select(x => x.Key).ToList();

                if (amountOfConnections == 1)
                {
                    Clients.Client(UserHandler.ConnectedIds.First().Key).hello("Send to only(also first) one");
                }
                else
                {
                    Clients.Clients(allExceptLast).hello("Send to everyone except last");
                    Clients.Client(lastConnection.Key).hello("Send to only the last one");
                }
            });

        task.ContinueWith(base.OnConnected());

        return task;
    }

I haven't tested that... its just a guess..



来源:https://stackoverflow.com/questions/30361524/signalr-send-message-onconnected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!