简体   繁体   English

SignalR - 发送消息OnConnected

[英]SignalR - Send message OnConnected

I've been experimenting with SignalR today and It's really neat. 我今天一直在尝试使用SignalR,它非常整洁。 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. 如果有超过1个连接的设备,我想发送两条消息。 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. 当我将它放在自定义API控制器中并且基本上调用动作时,我一直使用的代码非常完美,但这不是我想要的。

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. 我希望一旦设备在OnConnected内连接而没有任何用户交互就发送消息,但是当我将我的代码放在OnConnected覆盖内时它停止工作。 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();
    }

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. 而不是试图了解自己谁是最后一个连接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行做你需要的,它们在OnConnected内部工作。

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. 我首先订阅了'hello'函数,之后我启动了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();
    }

Since you haven't established a connection yet, trying to call your client .hello() function within OnConnected is not possible at this point. 由于您尚未建立连接,因此此时无法在OnConnected尝试调用客户端.hello()函数。 However, we can define a server hub method and immediately call that upon our connection .done callback. 但是,我们可以定义服务器中心方法,并在我们的连接.done回调时立即调用它。 Then, in our new server method we can reallocate the logic you currently have in OnConnected . 然后,在我们的新服务器方法中,我们可以重新分配您当前在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() { ... }); Connect => .done(function() { ... });
  2. Call server.afterConnected() 调用server.afterConnected()
  3. Execute logic within that method 在该方法中执行逻辑
  4. If we're satisfied with conditions call our .hello() client function 如果我们对条件满意,请调用我们的.hello()客户端函数

Note - this implementation is for a JavaScript client - but the same idea can be translated to a .net client. 注意 - 此实现适用于JavaScript客户端 - 但同样的想法可以转换为.net客户端。 This is mostly an architectural issue. 这主要是一个架构问题。

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... 嗯...你正在返回一个任务...所以我认为这可能是问题......你应该首先执行你的代码,然后返回任务......或者把一个ContinueWith ...像......

    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.. 我没有测试过......它只是猜测..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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