2011-09-25 47 views
54

我使用SignalR的(https://github.com/SignalR/SignalR)的毂 - 功能来发布消息发送给所有订阅的客户端:SignalR +通过操作方法发布消息到集线器

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

打电话时能正常工作,“发送”通过Javascript,但我也希望Web应用程序发布消息(从ASP.NET MVC操作方法中)。我已经尝试实例化一个新对象ob NewsFeedHub并调用Send方法,但这会导致错误(因为未设置Hub的底层“连接”)。有没有连接使用集线器的方法?

+2

没有你找到答案呢?我处于同样的困境。 Signalr DLL似乎初始化中心对象,所以我想知道我是否需要访问该对象。 – Mike

回答

79

请注意,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

+0

工程太棒了! :)解决了我的问题。我遇到了一些我在这里得到的代码的严重问题:http://www.xhroot.com/blog/2012/07/12/live-updates-using-signalr/ –

+0

*这并不意味着它们应该是因为他们在写作时是正确的,所以被低估了?当然,如果他们不正确,他们应该被低估? – Liam

+0

理想情况下,标记应该是历史准确性的版本特定。 –

8

已更新此答案也是旧的!看来,SignalR的公共API始终在不断变化。蒂姆·B·詹姆斯截至2012年7月有新的,适当的API使用。

Mike目前接受的答案是旧的,不再适用于最新版本的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!"); 
} 
+0

作为任何人尝试这个的注意事项,它看起来像这些方法不再可用。在Tim的+1上进行新的更新。看起来这是非常不稳定的。 –

+0

我很困惑。不是'AspNetHost'部分是0.4,而不是当前版本(目前是0.5.2)。这对我不起作用 –

+0

您是否阅读过顶部的更新?这个API也被弃用。请阅读Tim B James的回答。 –

38

2018年二月,短期和简单的解决方案

为了解决这个我通常设计我中心通过以下方式:

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和后端代码调用以及。这两种方法在客户端产生相同的事件。

+1

2016年8月,我唯一需要做的变化是:客户端[channel] - > Clients.Group(channel) –

+1

这是我所遇到的最好和最有效的解决方案,它是可重用的代码,并且完美地工作。 –

+0

静态方法不适用于我。我调试并通过它,尝试发送JavaScript,但没有任何反应。然而,常规的非静态方法的工作原理完全相同。问题是我不能从Web API调用它,我正在尝试这样做。想法? 编辑:这可能是可怕的,但在我的非静态方法中,我将“客户端”保存到一个私有静态变量(IHubConnectionContext的),然后在我的静态方法中调用它。工程,但...感觉不对。 – vbullinger

1

从DDan的回答下面就可以创建一个重载的静态方法,并保持共同的逻辑,一个方法 - 我使用这个模式

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);