2

I'm trying to send a message to a specific client in my Blazor WebAssembly project.

Startup.cs

services.AddSignalR();
....

app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapControllers();
                endpoints.MapHub<OrderHub>("/orderhub");
                endpoints.MapFallbackToFile("index.html");
            });

Client Code

protected override async Task OnInitializedAsync()
 {
    hubConnection = new HubConnectionBuilder()
           .WithUrl(NavigationManager.ToAbsoluteUri("/orderhub"))
           .Build();
            await hubConnection.StartAsync();
            await hubConnection.SendAsync("SendItemsCountMessage", orderpositions.Sum(x => x.amount));
 }

Hub.cs

public class OrderHub : Hub
{
    public async Task SendItemsCountMessage(int ItemsCount)
    {
        await Clients.All.SendAsync("ReceiveItemMessage", ItemsCount);
    }
}

Now I want to change it to have the option to send to a specific user:

public async Task SendItemsCountMessage(int ItemsCount)
{
            string conID = Context.ConnectionId;
            await Clients.User(conID).SendAsync("ReceiveItemMessage", ItemsCount);
}

But the context is null, with a user or without, with a logged in user or unauthorized, it all doesn't seems to matter. Any idea how to get the right Context.ConnectionId, best without being logged in user?

Maybe I need something like this?

Is it possible that I have to use bearer token authentication in my application and then send a generated token to Hub.cs where with var context = HttpContext.Request.Query[Token] I can get my Context?

Amal K
  • 4,359
  • 2
  • 22
  • 44
T0bi
  • 261
  • 1
  • 4
  • 13
  • 1
    You didn't include the code where you're declaring and initializing `Context` in your question. – Robert Harvey Aug 19 '21 at 15:07
  • I thought this would be automatically declared and initialized using the Microsoft.AspNetCore.SignalR. Can you show me an example of how to declare and initialize the context? – T0bi Aug 19 '21 at 15:10
  • Have a look here: https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-5.0 – Robert Harvey Aug 19 '21 at 15:13
  • the context comes from Microsoft.AspNetCore.SignalR in the public abstract class HubCallerContext through the services.AddSignalR();. I included it. Or i missunderstand you. – T0bi Aug 19 '21 at 15:13
  • Read the article I linked. It shows how to get to the `Context` from your object derived from `Hub`. – Robert Harvey Aug 19 '21 at 15:16
  • It only said "The Hub class has a Context property that contains the following properties with information about the connection" and not how to implement it. Furthermore, I used the Hub class as described. And my object is null. What did i miss? – T0bi Aug 19 '21 at 15:23
  • If I read the article correctly, you should be able to access the actual, live Context object by saying something like `myOrderHub.Context`. See [here](https://learn.microsoft.com/en-us/previous-versions/aspnet/jj890869(v=vs.118)) and [here](https://learn.microsoft.com/en-us/previous-versions/aspnet/jj908515(v=vs.100)) – Robert Harvey Aug 19 '21 at 15:33
  • In my changes i access the context (string conID = Context.ConnectionId;) but it is null. Or can you send me a example what exactly you mean maybe i dont get it. – T0bi Aug 19 '21 at 15:41
  • Yes, but where are you getting `Context` from? You never showed us that in your question. It has to be declared and initialized *somewhere.* – Robert Harvey Aug 19 '21 at 15:45
  • There's some more information [here](https://stackoverflow.com/questions/27299289/how-to-get-signalr-hub-context-in-a-asp-net-core). As you can see, SignalR is not the easiest thing to learn and use. – Robert Harvey Aug 19 '21 at 15:47
  • I have no clue how exactly it works, I guess when I call the hub or initialize it, the context is sent with it in the background, all contained in Microsoft.AspNetCore.SignalR. Do you have a working example of how to send to a specific user? or how to initialize the context? Then I will check if I forgot or missed something. – T0bi Aug 19 '21 at 15:50
  • @RobertHarvey not the easiest thing? i stuck on this two days straight and the more i read the worser it gets , i have no idea how something that easy to want so difficult in make can be – T0bi Aug 19 '21 at 15:51
  • 1
    Well, all of the examples I've seen on the Internet involve Dependency Injection, and that obscures the objects involved. You might want to build a little chat client with SignalR, take this out of the Blazor domain for awhile until you figure out how it works. – Robert Harvey Aug 19 '21 at 15:53
  • 1
    It should be an example in the Microsoft documentation of how to easily implement direct messaging. I mean their example is a damn chat that sends to everyone, they should extend it to one that sends to a specific user – T0bi Aug 19 '21 at 15:56
  • 2
    Have you guys considered moving this to a chat? Keeps the comment section clean. In all ASP.NET Technologies (for current versions of dotnet), `Context` will be instantiated and injected by the CDI container. – Connor Low Aug 19 '21 at 15:57
  • Have you tried [Groups](https://learn.microsoft.com/en-us/aspnet/core/signalr/groups?view=aspnetcore-5.0)? – Connor Low Aug 19 '21 at 16:18
  • @ConnorLow The idea is to add a user in a group and then add all ConnectionId's to this specific user. I have no Context.User in my Hub.cs to add it to a Group. – T0bi Aug 19 '21 at 16:24
  • Every user gets a unique connectionId. You override onconnect and use a table to associate the connectionID to a user Id. You do the same in reverse to ondisconnect. Once you have a userId asociated with one or more connectionId's you can message them directly. Another method is to assign users to a group with there user ID encoded. Then only broadcast to that group. – Brian Parker Aug 19 '21 at 17:52
  • @BrianParker and ConnorLow thank you very much this is my first new approach since two days , i will try it right now. – T0bi Aug 19 '21 at 18:03
  • This worked, in my development environment on my PC in localhost iis. When I publish it to azure, it doesn't work, but finally I have an approach that works and I can move on, thank you very much, sorry for my blindness with the group solution. When I figure out how to get it to work definitively I will formulate an answer to my question. – T0bi Aug 19 '21 at 18:46
  • @T0bi if you implement Auth on the hub. You can extract the users credentials on the server and associate with a hubconnectionId... – Brian Parker Aug 19 '21 at 18:50
  • 1
    @ConnorLow: The "move to chat" system on Stack Exchange is broken, and has been for some time. Even now, as I write this comment, I was not given the option to "move this conversation to chat." – Robert Harvey Aug 19 '21 at 20:55
  • That's annoying, [but you can still start your own chat](https://meta.stackexchange.com/a/106475). – Connor Low Aug 19 '21 at 21:06

0 Answers0