I'm a newb to SignalR. I'm trying to set up a Asp.Net Core WebAPI so that other clients can connect to it using SignalR and get real-time data. My Hub class is:
public class TimeHub : Hub
{
public async Task UpdateTime(string message)
{
await Clients.All.SendAsync("ReceiveMessage", message);
}
}
I have a relay class as follows:
public class TimeRelay : ITimeRelay
{
private readonly IHubContext<TimeHub> _timeHubContext;
public TimeRelay(IHubContext<TimeHub> context)
{
_timeHubContext = context;
Task.Factory.StartNew(async () =>
{
while (true)
{
await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());
Thread.Sleep(2000);
}
});
}
}
Startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseSignalR((x) =>
{
x.MapHub<TimeHub>("/timeHub");
});
app.UseMvc();
}
The client is a console application and the code is:
class Program
{
static Action<string> OnReceivedAction = OnReceived;
static void Main(string[] args)
{
Connect();
Console.ReadLine();
}
private static async void Connect()
{
var hubConnectionBuilder = new HubConnectionBuilder();
var hubConnection = hubConnectionBuilder.WithUrl("http://localhost:60211/timeHub").Build();
await hubConnection.StartAsync();
var on = hubConnection.On("ReceiveMessage", OnReceivedAction);
Console.ReadLine();
on.Dispose();
await hubConnection.StopAsync();
}
static void OnReceived(string message)
{
System.Console.WriteLine($"{message}");
}
}
I tried debugging the application. The client got connected to the TimeHub
succesfully. The no of connections in Clients.All
changed from 0 to 1, when the client got connected. But, when await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());
is executed, the UpdateTime
function in TimeHub
is not getting executed and the client is not getting any message.
I tried using "UpdateTime"
, "SendMessage"
, and "ReceiveMessage"
as method in Clients.All.SendAsync
in TimeRelay
class. Nothing worked. Could someone point out my mistake in this.
For Clients
, it will be null if there is no client connecting to server. For starting Asp.Net Core SignalR
and Console App
at the same time, the Clients
may be null since Index
may be called before Console App connects the signalR server.
Try steps below:
Change TimeHub
public class TimeHub: Hub
{
public async Task UpdateTime(string message)
{
if (Clients != null)
{
await Clients.All.SendAsync("ReceiveMessage", message);
}
}
}
Register TimeHub
services.AddSingleton<TimeHub>();
Controller
public class HomeController : Controller
{
private readonly TimeHub _timeHub;
public HomeController(TimeHub timeHub)
{
_timeHub = timeHub;
}
public IActionResult Index()
{
Task.Factory.StartNew(async () =>
{
while (true)
{
try
{
await _timeHub.UpdateTime(DateTime.Now.ToShortDateString());
Thread.Sleep(2000);
}
catch (Exception ex)
{
}
}
});
return View();
}
I got it to work and thought I will answer it here. Thanks @TaoZhou for the tip.
My mistake was sending "UpdateTime" from server and waiting on "ReceiveMessage" at the client.
Ideally the code should look like the following:
SignalR Server:await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());
SignalR Client:var on = hubConnection.On("UpdateTime", OnReceivedAction);
In this case any message send from the server would be received at the client instantly.
Please refer the code provided in the question for more info.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With