2017-07-21 40 views
2

コードの背後にある特定のユーザーにメッセージを送信することはできません。 Clients.Allが動作しますが、Clients.AllExcept(userId)は動作しますが、Client.User(userId)は動作しません。SignalRを使用して特定のユーザーにメッセージを送信できません

マイハブ:

public class MessagingHub : Hub 
{ 
    public override Task OnConnected() 
    { 
     var signalRConnectionId = Context.ConnectionId; 
     // for testing purpose, I collect the userId from the VS Debug window 
     System.Diagnostics.Debug.WriteLine("OnConnected --> " + signalRConnectionId); 
     return base.OnConnected(); 
    } 
} 

背後にあるコードからメッセージを送信するために私のコントローラ:私のハブはJSに初期化されている方法

public void PostMessageToUser(string ConnectionId) 
{ 
    var mappingHub = GlobalHost.ConnectionManager.GetHubContext<MessagingHub>(); 

    // doesn't works 
    mappingHub.Clients.User(ConnectionId).onMessageRecorded(); 

    // doesn't works 
    mappingHub.Clients.Users(new List<string>() { ConnectionId }).onMessageRecorded(); 

    // works 
    mappingHub.Clients.All.onMessageRecorded(); 

    // works (?!) 
    mappingHub.Clients.AllExcept(ConnectionId).onMessageRecorded(); 

} 

var con, hub; 
function StartRealtimeMessaging() 
{ 
    con = $.hubConnection(); 
    hub = con.createHubProxy('MessagingHub'); 

    hub.on('onMessageRecorded', function() { 
     $(".MessageContainer").append("<div>I've received a message!!</div>"); 
    }); 
    con.start(); 
} 

そして最後に、私はハブに(nは空の)メッセージを送信する方法:

function TestSendToUser(connectionId) 
{ 
    $.ajax({ 
     url: '/Default/PostMessageToUser', 
     type: "POST", 
     data: { ConnectionId: connectionId},// contains the user I want to send the message to 
    }); 
} 

だから、それはmappingHub.Clients.User(ConnectionId).onMessageRecorded();mappingHub.Clients.Users(new List<string>() { ConnectionId}).onMessageRecorded();と完全にmappingHub.Clients.All.onMessageRecorded();ではなく動作します。すべてのユーザーは、ユーザーIDが良い意味指定したユーザID、以外メッセージを受け取る接続されており、ユーザーがよく識別されます。興味深いことに

しかしは、それがmappingHub.Clients.AllExcept(ConnectionId).onMessageRecorded();で動作します。だから、Clients.User(ConnectionId)はなぜ機能しないのですか?

答えて

1

あなたは、ある特定の接続にメッセージを送りたいとあなたがConnectionIdを使用したい場合、あなたはClients.Client、このようにしないClients.User

使用していることを確認した場合:

public void PostMessageToUser(string connectionId) 
{ 
    var mappingHub = GlobalHost.ConnectionManager.GetHubContext<MessagingHub>(); 

    // Like this 
    mappingHub.Clients.Client(connectionId).onMessageRecorded(); 

    // or this 
    mappingHub.Clients.Clients(new List<string>() { connectionId }).onMessageRecorded(); 
} 
2

私は同じ問題を抱えていました。私は.User(ConnectionId)を動作させることができませんでした。

私はSignalRが長時間の処理ジョブの進捗状況をジョブを要求したクライアントに報告するように努力しました。つまり、ほとんどの例で説明しているチャットアプリではありません。

「長い処理進捗報告」の例私はハブ内のジョブのシムしか見つけられませんでした。私は実際の作業を行っているコントローラを持っていて、ハブではなくコントローラからメッセージを送信する必要があります。

私はこの回答をhttps://stackoverflow.com/a/21222303/3251300としました。あなたの記載された問題の回避策として、私は長時間の処理の仕事に使用するすべてのコードスニペットが含まれている場合は、この答えにつまずく人に便利です。

回避策は、.Group()機能を使用するという点で優雅さがあります。各groupIDをinternal userIDに設定することで、SignalRの外部でuserID/connectionID関係のリストを個別に管理することなく、.Group(userID)を使用してメッセージを送信することができます。

.Group()機能を使用せずにSignalRの関係を維持する方法があるかもしれませんが、まだ見つかりませんでした。

隠し型を使用してビューにuserIDを渡します。これにより、jsで使用できるようになります。

<input type="hidden" value="@ViewBag.UserID" id="userID" /> 

は、その後のjsハブスクリプトでハブ接続の起動時にハブにユーザIDを送信するために、以下を使用します。

$.connection.hub.start() 
    .done(function() { 
    var userID = document.getElementById('userID').value; 
    $.connection.myHub.server.announce(userID); 
    }) 
    .fail(function() { alert("Hub failed to start.") }); 

ハブには、userIDとconnectionIDをgroupID(ユーザーIDと同じ文字列)に関連付ける1つのステートメントがあります。

public class MyHub : Hub 
    { 
     public void Announce(string userID) 
     { 
      Groups.Add(Context.ConnectionId, userID); 
     } 
    } 

使用し、ハブ・コンテキストを設定した後(この場合もやはり、この場合、ハブは、メッセージがコントローラで実行されている長い処理要求にクライアントに進捗状況を報告していない)コントローラからメッセージを送信する.Group ()と内部のユーザーID。

var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>(); 
string fileMessage = "Some message"; 
hubContext.Clients.Group(userID).hubMessage(fileMessage); 

次いで、これ

$.connection.myHub.client.hubMessage = function (message) { 
    $("#hubMessages").html(message); 
} 

「#hubMessages」はビューでこのDIVを指すDIVにメッセージを配置するJSを使用して、ビューに表示されます。例では、.appendを使用すると、メッセージを送信するたびにdivが大きくなり、divにあるものはすべて新しいメッセージに置き換えられます。

<div id="hubMessages"></div> 

この回答に来るとMVCとSignalRに新しく追加され、この答えを見つけSignalR https://youtu.be/kr8uHeNjOKw誰のためのイントロ分割動画の偉大なシリーズがありカレブに出て大きな叫びに行くを取得しようとしている誰でもSignalR私はこれらを見て1時間を過ごすことをお勧めします。

+0

+1の回答ですが、1人のユーザーだけのグループを作成することは回避策であり、実際の解決策ではありません。私は 'Clients.User(srUserId)'が動作しないと信じられません... –

+0

まあ、私は最終的に答えを見つけました。私の答えを見てください。 (それもあなたを助けることを望みます;)) –

+0

あなたは正しいです、私は '回避策'を使用すべきでした - 私は答えを修正しました。本当の答えを見いだす素晴らしい仕事。 .Group()の回避策は、SignalRが内部のuserID/ConnectionIDリレーションシップを管理するという点で優雅さがあります。つまり、メッセージIDにuserIDを直接使用することはできません。そのためのテスト回避策として、userIDテーブルにconnectionIDを追加しました。私はライブDBでそれをする必要はありませんでした。 –

関連する問題