[英]How do I send messages from server to client using SignalR Hubs
I am just starting to explore signalR and I would like to able to send messages from the server to all clients.我刚刚开始探索 signalR,我希望能够从服务器向所有客户端发送消息。
Here is my Hub这是我的集线器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SignalR;
using SignalR.Hubs;
using SignalR.Hosting.Common;
using SignalR.Hosting.AspNet;
using System.Threading.Tasks;
namespace MvcApplication1
{
public class Chat : Hub
{
public void Send(String message)
{
// Call the addMessage methods on all clients
Clients.addMessage(message);
}
}
}
Here is my client Page这是我的客户页面
<script type="text/javascript">
$(function () {
//Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function (message) {
$("#messages").append("<li>" + message + "</li>");
};
$("#broadcast").click(function () {
// call the chat method on the server
chat.send($("#msg").val());
});
$.connection.hub.start();
});
</script>
}
<input type="text" id="msg" />
<input type="button" id="broadcast" value="broadcast" />
<ul id="messages" class="round">
</ul>
This all works perfectly, I am able to "chat" between 2 different browsers.这一切都很完美,我能够在 2 个不同的浏览器之间“聊天”。
The next thing I want to do is initiate a message from the server to all clients.我要做的下一件事是从服务器向所有客户端发起一条消息。
So I tried this.所以我尝试了这个。
using SignalR;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System;
using System.Web.Routing;
using SignalR;
using SignalR.Hubs;
namespace MvcApplication1
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
var aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += aTimer_Elapsed;
aTimer.Interval = 3000;
aTimer.Enabled = true;
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
context.Clients.Send("Hello");
}
}
}
This doesn't seem to work.这似乎不起作用。 The Timer works, The "aTimer_Elapsed" event handeler runs every 3 seconds but the "Send" method on the chat hub is never run.
计时器工作,“aTimer_Elapsed”事件处理程序每 3 秒运行一次,但聊天中心上的“发送”方法从不运行。
Any ideas?有任何想法吗?
I think it should be我认为应该是
void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
context.Clients.All.addMessage("Hello");
}
instead.反而。 With Send you are calling the method used by the client to call the server...
使用 Send 您正在调用客户端使用的方法来调用服务器...
Yes you must set that line to:是的,您必须将该行设置为:
void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
context.Clients.All.addMessage("Hello");
}
However this is only half way and still wont work.然而,这只是一半,仍然行不通。
In your Js you need to write:在您的 Js 中,您需要编写:
$(function () {
//Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.client.addMessage = function (message) {
$("#messages").append("<li>" + message + "</li>");
};
$("#broadcast").click(function () {
// call the chat method on the server
chat.client.addMessage($("#msg").val());
});
$.connection.hub.start();
});
I added the chat.client
this will add a client-side hub method that the server will call.我添加了
chat.client
这将添加服务器将调用的客户端集线器方法。
In case you come across this question many years after it was asked, and you happen to use .NET 5.0 (or similar), the following may be useful as you might be using a framework that no longer offers the class GlobalHost
.如果您在被问到这个问题多年后遇到这个问题,并且您碰巧使用 .NET 5.0(或类似版本),以下内容可能会很有用,因为您可能正在使用不再提供类
GlobalHost
的框架。
.NET 5.0 (and similar) make heavy use of dependency injection (DI) and it's not a surprise it is used here as well. .NET 5.0(和类似版本)大量使用依赖注入 (DI),在这里也使用它并不奇怪。 The following sample code shows how to do this.
以下示例代码显示了如何执行此操作。 It doesn't use the class
GlobalHost
.它不使用类
GlobalHost
。
Given the ChatHub
class as follows:鉴于
ChatHub
类如下:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message).ConfigureAwait(false);
}
}
in class Startup
add a line as indicated in the following code snippet:在类
Startup
添加一行,如以下代码片段所示:
public class Startup
{
// other code omitted for brevity
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// other code omitted for brevity
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<ChatHub>("/chatHub"); // <====== add this ======
});
// other code omitted for brevity
}
}
Then in a controller where you want to send messages to SignalR message, add the ChatHub as a dependency.然后在要向 SignalR 消息发送消息的控制器中,添加 ChatHub 作为依赖项。 The following example demonstrates how to do that for constructor injection:
以下示例演示了如何为构造函数注入执行此操作:
public class WeatherForecastController : ControllerBase
{
private readonly IHubContext<ChatHub> _hubContext;
public WeatherForecastController(
IHubContext<ChatHub> hubContext, // <============ add this ==========
ILogger<WeatherForecastController> logger)
{
_hubContext = hubContext;
_logger = logger;
}
[HttpGet]
public virtual async Task<IEnumerable<WeatherForecastModel>> Get()
{
var rng = new Random();
WeatherForecastModel[] weatherForecastModels = Enumerable.Range(1, 5).Select(index => new WeatherForecastModel
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)],
}).ToArray();
// Notify connected SignalR clients with some data:
await _hubContext.Clients.All.SendAsync("ReceiveMessage", "the weatherman", $" The temperature will be {weatherForecastModels[0].TemperatureC}").ConfigureAwait(false);
return weatherForecastModels;
}
// other code omitted for brevity
}
This example also shows how to then send messages in the Get()
method by using await _hubContext.Clients.All.SendAsync( ... )
此示例还展示了如何使用
await _hubContext.Clients.All.SendAsync( ... )
在Get()
方法中发送消息
For more information see Microsoft's documentation .有关详细信息,请参阅 Microsoft 的文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.