Implementing User-Specific Notifications with SignalR in an ASP.NET Core Web API & React Project

30 views Asked by At

I'm developing a layered ASP.NET Core Web API 6.0 project with a React frontend, which includes functionality for money transfers between clients. To enhance user experience, I'm looking to implement an Inbox feature for notifications, enabling clients to read specific or all notifications, and delete them individually or in bulk. For real-time communication, I've decided to integrate SignalR.

My project employs Identity for authentication, and I have custom JWT token validation in place to authorize endpoints. The JWT token also helps in extracting client identifiers, which is crucial for my use case.

However, I'm encountering challenges with configuring SignalR to send targeted notifications. For instance, when Client A sends money to Client B, I want to generate a notification for Client B visible through a SignalR hub. This involves creating a database record for the notification addressed to Client B.

I'm seeking guidance on the following:

SignalR Authentication: How can I configure SignalR to utilize the same JWT tokens used by my ASP.NET Core Web API for authentication? Is it a best practice to share the token between these components, or should SignalR have a separate authentication mechanism?

Database Interaction: How can SignalR be set up to read from a specific table dedicated to notifications, allowing for CRUD operations on notifications, including marking them as read?

Client-Side Notification Management: Is it more efficient for notification management (marking as read, deleting) to be handled through SignalR hubs or should these actions be routed through traditional controllers and API endpoints, with SignalR solely responsible for notifying clients of new events?

I've attempted to implement this functionality as follows:

public sealed class TestNotificationHub : Hub
{
    private readonly ITestNotificationService _testNotificationService;

    public NotificationHub(ITestNotificationService testNotificationService)
    {
        _testNotificationService = testNotificationService;
    }

    public async Task GetUnreadNotificationsForUser(string userId)
    {
        var notifications = await 
_testNotificationService.GetUnreadNotifications(userId);
        await Clients.User(userId).SendAsync("TakeNotifications", notifications);
    }
}

And the corresponding service method looks like this:

public class TestNotificationService : ITestNotificationService 
{
    private readonly IHubContext<NotificationHub> _hubContext;
    private readonly PersonalDbContext _dbContext;

    public TestNotificationService(IHubContext<NotificationHub> hubContext, DbContext dbContext)
    {
        _hubContext = hubContext;
        _dbContext = dbContext;
    }

    public async Task NotifyUser(string userId, string message)
    {
        await _hubContext.Clients.User(userId).SendAsync("TakeNotification", message);
    }

    public async Task MarkAllNotificationsAsRead(string userId)
    {
        await _dbContext.Notifications
            .Where(un => un.ClientId == userId && !un.IsRead)
            .UpdateAsync(un => new Notification { IsRead = true });
    }

    // Additional methods for marking notifications as read and deleting notifications...
}

I feel like I'm missing something crucial about SignalR's proper integration and usage within my project context. Any insights, examples, or guidance on best practices for achieving this functionality would be greatly appreciated.

0

There are 0 answers