1

SignalR を使用してブラウザーにメッセージを送信するアプリを作成しています。ユーザーは複数のブラウザ インスタンスを開いている可能性があり、各メッセージが適切なブラウザに送信されるようにします。私たちの理解では、ClientId ConnectionId によってこれを行うことができます。私たちが直面している問題は、コードベースの適切なタイミングでClientId ConnectionId または SessionId にアクセスすることです。シナリオは次のとおりです。

MVC アクションが実行され、その処理の一環として、Biztalk エンドポイントへの呼び出しが行われます。Biztalk の実行はアウト プロセスであり (MVC アクションの観点から)、完了しても返されません。これは仕様によるものです。完了したことを MVC アプリケーションに通知するために、Biztalk は /myapp/signalr エンドポイントを呼び出して、MVC アプリケーションの SignalR ハブにメッセージを送信します。メッセージは SignalR によって受信され、適切なブラウザー インスタンスにルーティングされる必要があります。

SignalR へのメッセージは MVC アプリケーションではなく Biztalk によって送信されるため、SignalR への接続の ClientId は、メッセージを受信する必要があるブラウザー インスタンスを識別するものではありません。したがって、実装しようとしているのは、Biztalk へのメッセージに Biztalk 呼び出しを開始するブラウザー インスタンスのClientId ConnectionId を含めることで、Return Address パターンに似たものです。Biztalk がそのメッセージを SignalR に送信するとき、コンテンツの 1 つは元のClientId ConnectionId 値です。SignalR が Biztalk からのメッセージを処理するとき、ClientIdを使用できます。メッセージに含まれる ConnectionId を使用して、そのメッセージを適切なブラウザー インスタンスにルーティングします。(はい、ブラウザを閉じて再度開いた場合、これが機能しないことはわかっていますが、それで問題ありません。)

私たちが直面している問題は、最初に MVC アクションから Biztalk にメッセージを送信するときに、ハブのコンテキストでしか使用できないClientId ConnectionId にアクセスできないことです。MVC アクションはどのハブ コンテキストを探すべきかわからないため、これは理解できます。

その代わりに試みたのは、Biztalk メッセージを介して SessionId を渡し、それを SignalR に返すことです。これにより、ブラウザー インスタンス識別子を Biztalk メッセージに含めて SignalR に返すという問題が解決されます。これにより、クライアントがハブに接続するときに、ハブの OnConnect メソッドでセッション (したがって、SessionId) にアクセスできないという事実が生じます。

David Fowler は、読み取り専用の SessionState を Hub でアクセスできるようにする方法を示していると伝えられている要点を投稿しましたが、機能しません。( https://gist.github.com/davidfowl/4692934 ) このコードをアプリケーションに追加するとすぐに、SignalR に送信されたメッセージによって HTTP 500 エラーが発生します。これは、SignalR が次の例外をスローすることによって引き起こされます。

[ArgumentNullException: Value cannot be null.Parameter name: s]
System.IO.StringReader..ctor(String s) +10688601
Microsoft.AspNet.SignalR.Json.JsonNetSerializer.Parse(String json, Type targetType) +77
Microsoft.AspNet.SignalR.Json.JsonSerializerExtensions.Parse(IJsonSerializer serializer, String json) +184
Microsoft.AspNet.SignalR.Hubs.HubRequestParser.Parse(String data) +101
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnReceived(IRequest request, String connectionId, String data) +143
Microsoft.AspNet.SignalR.<>c__DisplayClassc.<ProcessRequest>b__7() +96
Microsoft.AspNet.SignalR.<>c__DisplayClass3c.<FromMethod>b__3b() +41
Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func) +67

SessionStateBehavior を設定したモードに関係なく (David Fowler の要点で示されているように)、ハブにメッセージを送信するときにこの例外を取得するか、ハブの OnConnect にいるときに SessionState が null になります。

では、すべての前置きの後、SignalR でこの種の切断されたメッセージングを操作するときに、人々が適切なクライアントをどのように更新するのかを尋ねています。

4

1 に答える 1

0

ハブへの通常のリクエスト以外でクライアントにデータを送信する場合は、ユーザーを管理し、それらを対応する接続​​ ID にマップする静的なコンカレント ディクショナリをハブに配置することをお勧めします。

このアプローチを使用すると、マッピングされた接続 ID に基づいて、任意の時点で任意のユーザーに送信できます。したがって、データを Biztalk に送信するときは、(自分で作成した) ユーザー ID を送信するだけでよく、データが SignalR に戻ってきたら、その特定のユーザー ID の ConnectionId (存在する場合) を検索できます。

最後に、OnConnected で同時実行辞書にユーザーを追加し、OnReconnected にユーザーが存在しない場合にのみ追加し、OnDisconnected で削除することで、ユーザー マッピングを管理できます。

于 2013-04-15T17:11:28.950 に答える