Search code examples
c#asp.net-web-apisignalrsignalr-hub

How to send a periodic message from the server in SignalR


I've created a new ASP.NET 6 web app. I want to periodically broadcast a message through a SignalR hub, from the server. How can I access the hub from the server? Other answers suggest using GlobalHost but it belongs to a deprecated version of SignalR

Example code from web app Program.cs:

app.MapHub<SiteLayoutHub>("hubs/site");

app.Run();

Task.Factory.StartNew(async () =>
{
    var hub = GetSiteLayoutHub(); // How can I get this hub?
    while (true)
    {
        var uiState = GetUIState();
        await hub.SendUIUpdateMessage(uiState);
        Thread.Sleep(500);
    }
});

SiteLayoutHub.cs:

public class SiteLayoutHub : Hub
{
    public async Task SendUIUpdateMessage(UIState uiState)
    {
        await Clients.All.SendAsync("UIUpdateMessage", uiState);
    }
}

Solution

  • These are all of the pieces required:

    using Microsoft.AspNetCore.SignalR;
    
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    builder.Services.AddHostedService<UIUpdateService>();
    
    var app = builder.Build();
    
    app.MapHub<SiteLayoutHub>("hubs/site");
    
    app.Run();
    
    public class SiteLayoutHub : Hub { }
    
    public class UIUpdateService : BackgroundService
    {
        private readonly IHubContext<SiteLayoutHub> _hubContext;
        public UIUpdateService(IHubContext<SiteLayoutHub> hubContext)
        {
            _hubContext = hubContext;
        }
    
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
    
            while (await timer.WaitForNextTickAsync(stoppingToken))
            {
                var uiState = GetUiState();
                await _hubContext.Clients.All.SendAsync("UIState", uiState);
            }
        }
    
        private object GetUiState()
        {
            throw new NotImplementedException();
        }
    }