I am working on an ASP.NET Core 8.0 Web API application and I'm trying to implement SignalR for real-time notifications for the first time. Despite successfully connecting to the SignalR hub, I am unable to receive any notifications on the client side, whether it's in Postman or a custom console application. I need help to understand why the notifications are not being delivered.
What I've Done So Far:
Installed SignalR Package: I have installed the Microsoft.AspNetCore.SignalR package and set up my hub.
Created the Hub and Interface: I created a NotificationHub class and an INotificationHub interface as shown below:
'''
public sealed class NotificationHub : Hub<INotificationHub>
{
public async Task SendNotification(string userId, ClientNotificationDto notification)
{
await Clients.User(userId).ReceiveNotification(notification);
}
public async Task SendNotificationToGroup(string groupName, string message)
{
await Clients.Group(groupName).ReceiveNotification(message);
}
public async Task AddToGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}
public async Task RemoveFromGroup(string groupName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
}
public async Task SendNotificationToAll(string message)
{
await Clients.All.ReceiveNotification(message);
}
}
public interface INotificationHub
{
Task ReceiveNotification(string message);
Task ReceiveNotification(ClientNotificationDto notification);
Task SendNotification(string userId, ClientNotificationDto notification);
Task SendNotificationToGroup(string groupName, string message);
Task AddToGroup(string groupName);
Task RemoveFromGroup(string groupName);
Task SendNotificationToAll(string message);
}
- ClientNotificationDto Model: The ClientNotificationDto model is structured as follows:
public class ClientNotificationDto
{
public long Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public bool IsRead { get; set; }
public DateTimeOffset CreateDate { get; set; }
}
- Configured SignalR in Program.cs: I added SignalR services and mapped the hub in Program.cs:
services.AddSignalR();
app.MapHub<NotificationHub>("/notificationHub");
Authorization: I am using the [Authorize] attribute because JWT token authentication is required.
Created a Test Controller: I created a test controller to simulate sending notifications:
var notificationDto = new ClientNotificationDto
{
Id = 1,
Title = "Test Title",
Content = "Test Content",
IsRead = false,
};
await _hubContext.Clients.User(clientNotification.CustomerId).ReceiveNotification(notificationDto);
// Added for testing purposes
await _hubContext.Clients.All.ReceiveNotification("Hello");
The Problem:
When I trigger the controller, it executes successfully. However, when I connect to the hub using Postman or a custom console application, I don't receive any notifications.
In Postman and the console application, I see the message Connected to wss://localhost:7159/notificationHub, indicating that the connection is successful. However, no messages are received. In the console application, I see ping logs every few seconds, showing that the connection is alive, but there are no messages.
What I've Tried:
- Verified that the NotificationHub methods are being called and that the messages should be sent.
- Checked the connection status and ping logs, which indicate that the connection is active.
- Tested with both Postman and a custom console application, but neither receives the expected messages.
Client Side Code:
class Program
{
static async Task Main(string[] args)
{
var token = "JWT_TOKEN";
var connection = new HubConnectionBuilder()
.WithUrl("https://localhost:7159/notification", options =>
{
options.AccessTokenProvider = () => Task.FromResult(token);
})
.ConfigureLogging(logging =>
{
logging.SetMinimumLevel(LogLevel.Debug);
logging.AddConsole();
})
.Build();
connection.On<ClientNotificationDto>("ReceiveNotification", notification =>
{
Console.WriteLine("Received notification event triggered");
try
{
if (notification != null)
{
Console.WriteLine($"Received notification: {notification.Title} - {notification.Content}");
}
else
{
Console.WriteLine("Received null notification.");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error processing received notification: {ex.Message}");
}
});
connection.Closed += async (error) =>
{
Console.WriteLine($"Connection closed: {error?.Message}");
await Task.Delay(5000);
try
{
await connection.StartAsync();
Console.WriteLine("Connection restarted.");
}
catch (Exception ex)
{
Console.WriteLine($"Error while restarting connection: {ex.Message}");
}
};
try
{
await connection.StartAsync();
Console.WriteLine("Connection started.");
}
catch (Exception ex)
{
Console.WriteLine($"Connection error: {ex.Message}");
}
Console.ReadLine();
}
}
If I add the following line to my main code:
await _hubContext.Clients.All.ReceiveNotification("hello");
on the client-side, where I'm listening for messages, I get the following error:
fail: Microsoft.AspNetCore.SignalR.Client.HubConnection[57]
Failed to bind arguments received in invocation '(null)' of 'ReceiveNotification'.
System.IO.InvalidDataException: Error binding arguments. Make sure that the types of the provided values match the types of the hub method being invoked.
---> System.Text.Json.JsonException: The JSON value could not be converted to SignalrTest.ClientNotificationDto. Path: $ | LineNumber: 0 | BytePositionInLine: 129.
at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsObject(Utf8JsonReader& reader, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadAsObject(Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo)
at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindType(Utf8JsonReader& reader, Type type)
at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindTypes(Utf8JsonReader& reader, IReadOnlyList`1 paramTypes)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindTypes(Utf8JsonReader& reader, IReadOnlyList`1 paramTypes)
at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.ParseMessage(ReadOnlySequence`1 input, IInvocationBinder binder)
However, if I remove that line and only include:
var notificationDto = new ClientNotificationDto
{
Id = 1,
Title = "Test Title",
Content = "Test Content",
IsRead = false,
};
await _hubContext.Clients.User(clientNotification.CustomerId).ReceiveNotification(notificationDto);
then nothing is received on the client side.
I'm at a loss as to why the notifications are not being received by the clients, despite the connection being successful. Is there something I'm missing in the setup or the way the notifications are being sent? How can I troubleshoot this issue and get the notifications to appear in the client?
Any help or suggestions would be greatly appreciated!