SignalR + 通过操作方法向 Hub 发布消息
Posted
技术标签:
【中文标题】SignalR + 通过操作方法向 Hub 发布消息【英文标题】:SignalR + posting a message to a Hub via an action method 【发布时间】:2011-11-24 20:07:01 【问题描述】:我正在使用 SignalR (https://github.com/SignalR/SignalR) 的 hub- 功能向所有订阅的客户端发布消息:
public class NewsFeedHub : Hub
public void Send(string channel, string content)
Clients[channel].addMessage(content);
这在通过 javascript 调用“发送”时工作正常,但我也希望 Web 应用程序发布消息(从 ASP.NET MVC 操作方法中)。我已经尝试实例化一个新对象 ob NewsFeedHub 并调用 Send 方法,但这会导致错误(因为未设置集线器的底层“连接”)。有没有办法在没有连接的情况下使用集线器?
【问题讨论】:
你找到答案了吗?我处于同样的困境。 Signalr dll 似乎初始化了集线器对象,所以我想知道是否需要访问它。 【参考方案1】:请注意,自提出此问题以来,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
。
【讨论】:
效果很好! :) 解决了我的问题。我在这里得到的一段代码遇到了严重的问题:xhroot.com/blog/2012/07/12/live-updates-using-signalr 这并不意味着它们应该被否决,因为它们在撰写本文时是正确的?如果他们不再正确,他们肯定应该被否决吗? 理想情况下,标签应该是特定于历史准确性的版本。【参考方案2】: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 和后端代码调用。这两种方法在客户端产生相同的事件。
【讨论】:
2016 年 8 月,我唯一需要做的改变是:Clients[channel] -> Clients.Group(channel) 这是我遇到过的最好和最有效的解决方案,它是可重用的代码,并且运行良好。 静态方法对我不起作用。我调试并单步执行它,它尝试发送 JavaScript,但没有任何反应。但是,常规的非静态方法可以工作,但做的事情完全相同。问题是我无法从 Web API 调用它,这是我正在尝试做的事情。想法?编辑:这可能很可怕,但是在我的非静态方法中,我将“客户端”保存到私有静态变量(IHubConnectionContext2012 年更新:这个答案也很旧! SignalR 的公共 API 似乎在不断变化。自 2012 年 7 月起,Tim B James 拥有新的、正确的 API 用法。
2019 年更新不要再使用这个答案了。在 AspNetCore 上工作的 SignalR 的新版本应参考 Tim B James 接受的答案,或其他投票赞成的答案。为了历史,我把这个答案留在这里。
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!");
【讨论】:
作为对尝试此操作的任何人的说明,这些方法似乎不再可用。向蒂姆 +1 以获取有关新方式的更新。看起来这很不稳定。 我很困惑。AspNetHost
不是 0.4 的一部分,也不是当前版本(当前为 0.5.2)。这对我不起作用
您是否阅读了顶部的更新?此 API 也已被弃用。请阅读 Tim B James 的回答。【参考方案4】:
我正在寻找.NET Core
解决方案,Google 将我发送到这里,似乎没有人提到.NET Core
解决方案,所以你去吧:
中心,这里没什么特别的:
public class MyHub : Hub
// ...
在你的controller
:
public class HomeController : Controller
readonly IHubContext<MyHub> _hub;
public HomeController(IHubContext<MyHub> hub)
_hub = hub;
public IActionResult Index()
// ...
await _hub.Clients.All.SendAsync("ReceiveMessage", "Hello from HomeController");
// ...
【讨论】:
截至 2021 年 6 月,这是唯一有效的代码。让我们希望 API 会保留一段时间。谢谢迈赫迪【参考方案5】:根据 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);
【讨论】:
以上是关于SignalR + 通过操作方法向 Hub 发布消息的主要内容,如果未能解决你的问题,请参考以下文章
从 Controller 调用 SignalR Core Hub 方法