I am trying to use ASP NET Core signal r to push notifications to a specific client based on if an update has been made to the database. I am mostly there but my issue is the function isn't running.
SignalR is set up in Startup.cs. I have the following:
services.AddSignalR();
services.AddHostedService<UpdateService>();
endpoints.MapHub<NotificationManager>("/public");
In my javascript where the connection is made I just simply have:
connection.start().then(function () {
console.log("Connection started")
}).catch(function (err) {
return console.error(err.toString());
});
My UpdateService.cs
public class UpdateService : BackgroundService
{
private readonly IHubContext<NotificationManager, INotificationManager> _hubContext;
public UpdateService(IHubContext<NotificationManager, INotificationManager> hubContext)
{
_hubContext = hubContext;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
Console.WriteLine($"UpdateService Ran at: {DateTime.Now}");
await _hubContext.Clients.All.CheckForUpdates();
await Task.Delay(10000, stoppingToken);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
Then my NotificationManager.cs and interface class:
public interface INotificationManager
{
Task CheckForUpdates();
Task EntityUpdated(string entityReferenceNumber);
Task NoChangesFound(string getLabel);
}
public class NotificationManager : Hub<INotificationManager>
{
...
public async Task CheckForUpdates()
{
var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var connectionId = _userConnectionManager.GetConnectionsForUser(userId);
if (connectionId != null)
{
var lastCheckedTime = await GetLastCheckedTimeAsync();
var updatedEntities = _db.Table
.Where(e => e.EditedDate > lastCheckedTime).ToList();
if (updatedEntities.Any())
{
foreach (var entity in updatedEntities)
{
//await Clients.All.SendAsync("EntityUpdated", entity.ReferenceNumber);
await Clients.User(userId).EntityUpdated(entity.ReferenceNumber);
}
await UpdateLastCheckedTimeAsync(DateTime.UtcNow);
}
else
{
var getLabel = "Stringval"
await Clients.User(userId).NoChangesFound(getLabel);
}
}
}
}
I'm unsure as to why the CheckForUpdates
isn't being called or working. My UpdateService is being hit because the timestamps are being logged. It does step over the await _hubContext.Clients.All.CheckForUpdates();
but just doesn't carry out the functionality. Am i missing something? I was using https://learn.microsoft.com/en-us/aspnet/core/signalr/background-services?view=aspnetcore-7.0 as a reference but at a blocked point right now.
After checking the code you provided, I think you are missing some code in your javascript client side.
You can try to add below code first, to check the background service works well or not.
connection.on("CheckForUpdates", function (user, message) {
console.log(new Date().toUTCString()+ " ========= Triggered by the background service");
});
In the Console window inside the Browser Developer Tools, please the output message, it should be has some message like below.
Mon, 17 Apr 2023 08:12:13 GMT ========= Triggered by the background service
Mon, 17 Apr 2023 09:12:13 GMT ========= Triggered by the background service
It means the background job works well, and the signalr server invoke the method CheckForUpdates
successfully.
// Monitor the server call
connection.on("CheckForUpdates", function (user, message) {
console.log(new Date().toUTCString()+ " ========= Triggered by the background service");
// invoke the server side method
connection.invoke("CheckForUpdates").catch(function (err) {
return console.error(err.toString());
});
});