我正在使用SignalR(https://github.com/SignalR/SignalR)的hub-feature向所有订阅的客户端发布消息:
public class NewsFeedHub : Hub
public void Send(string channel, string content)
{
Clients[channel].addMessage(content);
}
这通过Javascript调用“发送”时工作正常,但我也希望Web应用程序发布消息(来自ASP.NET MVC操作方法)。我已经尝试实例化新对象ob NewsFeedHub并调用Send方法,但这会导致错误(因为未设置Hub的基础“连接”)。有没有办法在没有连接的情况下使用Hub?
答案 0 :(得分:90)
请注意,自提出此问题以来,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
。
答案 1 :(得分:54)
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 :(得分:10)
2012年更新:这个答案也很老了!看来,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!");
}
答案 3 :(得分:2)
根据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);
答案 4 :(得分:1)
我一直在寻找 .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");
// ...
}
}