Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I send messages from server to client using SignalR Hubs

Tags:

I am just starting to explore signalR and I would like to able to send messages from the server to all clients.

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.

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.

Any ideas?

like image 957
David Kethel Avatar asked Aug 29 '12 23:08

David Kethel


People also ask

How do I send a message to a group in SignalR?

When user click on send button, the message to be posted to server side using signalR connection hub. Thus whenever you post any message after clicking the join group button, the message will appear to all the clients who has joined the group.

How does SignalR hub work?

What is a SignalR hub. The SignalR Hubs API enables you to call methods on connected clients from the server. In the server code, you define methods that are called by client. In the client code, you define methods that are called from the server.


2 Answers

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...

like image 101
eddo Avatar answered Sep 21 '22 17:09

eddo


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 (and similar) make heavy use of dependency injection (DI) and it's not a surprise it is used here as well. The following sample code shows how to do this. It doesn't use the class GlobalHost.

Given the ChatHub class as follows:

   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:

   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. 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( ... )

For more information see Microsoft's documentation.

like image 44
Manfred Avatar answered Sep 21 '22 17:09

Manfred