web-dev-qa-db-ja.com

SignalR-メッセージを送信OnConnected

今日、SignalRを試してみましたが、本当にすてきです。基本的に私が達成したかったのは次のとおりです。

デバイスが接続するとすぐに、最初のデバイスにメッセージを送信する必要があります。接続されているデバイスが複数ある場合は、2つのメッセージを送信したいと思います。 1対すべて除く最後に接続されたクライアント。そして、最後に接続されたクライアントへの1つのメッセージのみ

私が使用しているコードは、カスタムAPIコントローラーに配置して基本的にアクションを呼び出すと完璧に機能しますが、それは私が望んでいることではありません。

ユーザーの操作なしでデバイスがOnConnected内に接続したらすぐにメッセージを送信したいのですが、コードをOnConnectedオーバーライド内に配置すると、機能しなくなります。特定のクライアント(最初に接続されたものと最後に接続されたもの)には送信されなくなります。

私は数時間頭を叩いているので、誰かがこれを手伝ってくれることを願っています。

    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();
    }
10
Mittchel

すべての助けをありがとう(みんなに賛成)。実際に問題を見つけました..それは私のクライアントの内部にありました。最初に「hello」関数をサブスクライブし、その後、HubConnectionを開始しました。この順序を変更するとすぐに、すべてが正常に機能しました。

次のクライアントコードで動作しました。

    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();
    }
5
Mittchel

私があなたの質問から何かを見逃さない限り、解決策は私にはかなり単純に見えます、あなたはただ使用に切り替える必要があります

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

最後に接続されたIDが誰であるかを理解しようとする代わりに。他のものと同じように、あなたは使うことができます:

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

セットアップするすべてのロジックは必要ありません。これらの2行は必要なことを実行し、OnConnected内で機能します。

11
Wasp

まだ接続を確立していないため、現時点では、OnConnected内でクライアントの.hello()関数を呼び出そうとすることはできません。ただし、サーバーハブメソッドを定義し、接続_.done_コールバックですぐに呼び出すことができます。次に、新しいサーバーメソッドで、現在OnConnectedにあるロジックを再割り当てできます。

これにより、セットアップが大幅に変更され、いくつかの追加手順が導入されますが、次の例を確認してください...

_// 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
});
_

したがって、ここでの基本的な考え方は、最初に

  1. 接続=> .done(function() { ... });
  2. server.afterConnected()を呼び出します
  3. そのメソッド内でロジックを実行する
  4. 条件に満足したら、.hello()クライアント関数を呼び出します

-この実装はJavaScriptクライアント用です-しかし、同じアイデアを.netクライアントに変換できます。これは主にアーキテクチャ上の問題です。

3
scniro

ええと...あなたはタスクを返しています...だから私はそれが問題かもしれないと思います...あなたは最初にあなたのコードを実行してからタスクを返すべきです...または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;
    }

私はそれをテストしていません...それはただの推測です...

1