web-dev-qa-db-ja.com

SignalR +アクションメソッドを介してハブにメッセージを投稿する

SignalRのハブ機能( https://github.com/SignalR/SignalR )を使用して、購読しているすべてのクライアントにメッセージを公開しています。

public class NewsFeedHub : Hub
public void Send(string channel, string content)
{
    Clients[channel].addMessage(content);
}

これは、Javascriptを介して「送信」を呼び出すときに正常に機能しますが、Webアプリケーションがメッセージを(ASP.NET MVCアクションメソッド内から)公開することも望んでいます。 NewsFeedHubで新しいオブジェクトをインスタンス化し、Sendメソッドを呼び出してみましたが、エラーが発生します(ハブの基になる「接続」が設定されていないため)。接続せずにハブを使用する方法はありますか?

62
ollifant

SignalR APIは、この質問が尋ねられてから何度も変更されていることに注意してください。一部の回答が古くなる可能性があります。これは、執筆時点で正しかったため、彼らがダウン投票されるべきであることを意味しません

SignalR Wiki に見られるように、これに対する別の更新された回答があります。

c#

Public ActionResult MyControllerMethod()
{
    var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
    context.Clients.All.methodInJavascript("hello world");
    // or
    context.Clients.Group("groupname").methodInJavascript("hello world");
}

vb.net

Public Function MyControllerMethod() As ActionResult
    Dim context = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
    context.Clients.All.methodInJavascript("hello world")
    '' or
    context.Clients.Group("groupname").methodInJavascript("hello world")
End Function

更新

このコードは更新されました。 http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server に従って変更します。

DIコンテナを使用している場合

DIコンテナーを使用してハブを接続する場合は、コンテナーからIConnectionManagerを取得し、そのconnectionManagerでGetHubContextを呼び出します。

92
Tim B James

2018年2月、簡潔でシンプルなソリューション

これを解決するために、私は通常、次のようにハブを設計します。

public class NewsFeedHub : Hub 
{
    private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<NewsFeedHub>();

    // Call this from JS: hub.client.send(channel, content)
    public void Send(string channel, string content)
    {
        Clients.Group(channel).addMessage(content);
    }

    // Call this from C#: NewsFeedHub.Static_Send(channel, content)
    public static void Static_Send(string channel, string content)
    {
        hubContext.Clients.Group(channel).addMessage(content);
    }

}

そのため、Javascriptやバックエンドコードからも簡単に呼び出すことができます。 2つのメソッドは、クライアントで同じイベントになります。

55
DDan

更新2012この答えも古い! SignalRのパブリックAPIは絶えず変化しています。 Tim B Jamesは、2012年7月現在、新しい適切なAPIを使用しています。

更新2019この回答を使用しないでください。 AspNetCoreで動作する新しいバージョンのSignalRは、Tim B Jamesが承認した回答、または他の投票済みの回答を参照する必要があります。歴史のためにこの回答を残しておきます。


マイクから現在受け入れられている回答は古く、SignalRの最新バージョンでは動作しません。

MVCコントローラーアクションからハブにメッセージを投稿する方法を示す更新バージョンは次のとおりです。

public ActionResult MyControllerMethod() 
{
     // Important: .Resolve is an extension method inside SignalR.Infrastructure namespace.
     var connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
     var clients = connectionManager.GetClients<MyHub>();

     // Broadcast to all clients.
     clients.MethodOnTheJavascript("Good news!");

     // Broadcast only to clients in a group.
     clients["someGroupName"].MethodOnTheJavascript("Hello, some group!");

     // Broadcast only to a particular client.
     clients["someConnectionId"].MethodOnTheJavascript("Hello, particular client!");
 } 
10

DDanの答えに続いて、オーバーロードされた静的メソッドを作成し、共通のロジックを1つのメソッドに保持できます-このパターンを使用します

public class ChatHub : Hub
{
    private static IHubConnectionContext<dynamic> GetClients(ChatHub chatHub)
    {
        if (chatHub == null)
            return GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients;
        else
            return chatHub.Clients;
    }

    // Call from JavaScript
    public void Send(string message)
    {
        Send(message, this);
    }

    // Call from C# eg: Hubs.ChatHub.Send(message, null);
    public static void Send(string message, ChatHub chatHub)
    {
        IHubConnectionContext<dynamic> clients = GetClients(chatHub);
        // common logic goes here 
        clients.All.receiveSend(message);
    }
}

次に、コントローラーから使用できます

Hubs.ChatHub.Send(arg1, null);
2
J45