I'm trying to implement a notification system that notifies specific users depending on their roles or permissions in Blazor Server Side .NET 5 with SignalR. I've already implemented Identity Authentication and Authorization.
In my MainLayout.razor page i've implemented a HubConnectionBuilder as follows:
private HubConnection _hubConnection;
protected override async Task OnInitializedAsync()
{
//SignalR
_hubConnection = new HubConnectionBuilder()
.WithUrl(MyNavigationManager.ToAbsoluteUri("/hub"))
.Build();
_hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
Toaster.NotificacaoGlobal(user, message);
StateHasChanged();
});
await _hubConnection.StartAsync();
}
I've also created a TestHub.cs where i have a few methods as follows:
public class TestHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
return base.OnDisconnectedAsync(exception);
}
}
In Startup.cs i've added:
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
endpoints.MapHub<TestHub>("/hub");
});
and
services.AddSignalR();
My ideia was to store the connectionId and UserId on the OnConnectedAsync() and then on the method await Clients.All.SendAsync("ReceiveMessage", user, message); filter the user with something like Clients.User(userId).SendAsync("ReceiveMessage", user, message);
I've tried to use both Context.UserIdentifier and Context.User.Identity.Name inside OnConnectedAsync() method and both return null. Some said to use the [Authorize] atribute in the TestHub.cs but that gives me an exception: HttpRequestException: Response status code does not indicate success: 401 (Unauthorized). on await _hubConnection.StartAsync()
Implementing IUserIdProvider did not resolve the problem as some suggested:
public class IdBasedUserIdProvider : IUserIdProvider
{
public string GetUserId(HubConnectionContext connection)
{
//TODO: Implement USERID Mapper Here
//throw new NotImplementedException();
return connection.User.FindFirst("sub").Value;
}
}
services.AddSingleton<IUserIdProvider, IdBasedUserIdProvider>();
I'm new to blazor and SignalR and might be something that I'm not aware.
Thanks in advance!
EDIT 1:
As asked i'm going to clarify the problem i'm having as best as I can.
What do I need? A system for sending push notifications to specific users.
What have I done? Tried to implement SignalR to send those notifications through SignalR
The struggles: After implementing the TestHub.cs class and the initializer on OnInitializedAsync() on my razor page I was unable to map the identity user with the connectionId in SignalR.
What I need is some clarification, if possible, whether am I making a mistake implementing SignalR, if SignalR makes sense in this cenario or if is there any other tool or system that makes more sense.
I hope I clarified enough. Thanks.