2

In the live trace tool on the Azure portal, I consistently get the message that the user message was not received because there’s no active connection for user XXX

I'm using a custom IUserIdProvider in my ASP.NET Core app. When I use the default, in-memory functionality of SignalR, this works like a charm. However, with Azure SignalR Service, there seems to be a mismatch between connections and User IDs.

A connection is made, but this doesn’t seem to find its way back to Azure SignalR service, because the other User IDs shown in the trace cannot be traced back to our code. The result of that is that no message ever arrives in the users’ browsers. In the screenshot attached, the user IDs in the first two lines seem to be auto-generated by Azure SignalR Service, while the third row indicates a user id in our app. Hence the warning message that there aren't any active connections for that user.

enter image description here

Not much fancy is going on in our app in terms of SignalR config:

  services
  .AddSignalR()
  .AddAzureSignalR(signalRConnString);
  
  services.AddSingleton<IUserIdProvider, UserIdProvider>();

UserIdProvider's code combines two claims from the connection's user:

public class UserIdProvider : IUserIdProvider
{
  public virtual string GetUserId(HubConnectionContext connection) 
    => connection.User?.FindFirst("CLAIM1")?.Value!
       + "_T_"
       + connection.User?.FindFirst("CLAIM2")?.Value!;
}

The hub itself is pretty bland, there's not much going on. Except when broadcasting from the server to a subselection of users, who are retrieved from the cache/database based on several business rules. I simply fetch a list of users that should receive this message, after which I just invoke:

await HubContext.Clients.User(x.UserId).SendAsync(...);

As mentioned before, without Azure SignalR, this works perfectly.

Perhaps this could be the problem, but I'm actually invoking SignalR through IHubContext<T>. There have been similar topics on the subject that suggest something like this:

ServiceManager serviceManager = new ServiceManagerBuilder().WithOptions(option => { option.ConnectionString = signalRConnString; }).BuildServiceManager();
ServiceHubContext hubContext = serviceManager.CreateHubContextAsync(HubNames.PlanningHub, CancellationToken.None).Result;
services.Add(new ServiceDescriptor(typeof(IHubContext<Hub>), hubContext));

Is there any extra config that must be provided to Azure SignalR Service to be able to use the same IUserIdProvider instance?

hbulens
  • 1,872
  • 3
  • 24
  • 45
  • Please share your `OnConnectedAsync` method inside your Hub class, I want to check how you manage the connectionIds. – Jason Pan Apr 03 '23 at 12:35
  • It's empty. I used to keep track of the connections in a Redis cache, but supposedly that's not a best practice anymore with SignalR Core, so I intend to scrap it in favor of Azure SignalR. – hbulens Apr 03 '23 at 16:00
  • Hi hbulens, could you share the IUserIdProvider and UserIdProvider, so that we could check it, if we could reproduce the issue in our side, it can save your time. – Jason Pan Apr 04 '23 at 06:00
  • Thanks Jason. I updated the question. It's a pretty simple one since it simply combines two claims of the connected user. – hbulens Apr 04 '23 at 06:25
  • After my test, your code can work in my side and work fine. I also find you post the same question in Microsoft Froum, I will also leave message there. – Jason Pan Apr 04 '23 at 12:26
  • How do you start a connection on the front-end? I'm using 'new signalR.HubConnectionBuilder().withUrl("/planningHub", {}).withAutomaticReconnect().build();' I've been fiddling around with the options param and set skipNegotation to true as I've been considering Redis cache as the backplane. – hbulens Apr 04 '23 at 13:36
  • I compared the code, I think it's same. `var connection = new signalR.HubConnectionBuilder().withUrl("/mainHub") .withAutomaticReconnect({ nextRetryDelayInMilliseconds: () => { this._errorState$.next(true); return 1000; }, reconnectDelay: 500 // set the reconnect delay to 500ms }) .configureLogging(signalR.LogLevel.Debug).build();` – Jason Pan Apr 04 '23 at 13:40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/252970/discussion-between-jason-pan-and-hbulens). – Jason Pan Apr 04 '23 at 13:41
  • In order to help more forum user who will face the same issue later, pls allow me summarize the issue and the solution as answer below. – Jason Pan Apr 05 '23 at 10:28
  • 1
    Go for it, and I'll accept your answer. – hbulens Apr 05 '23 at 10:34

1 Answers1

2

Everything works fine when using Asp.Net Core SignalR, but there are problems when using Azure SignalR.

At this time, we first need to configure Azure SignlaR correctly, and then check how the connection is created in the front-end code. The first thing we need to check is the SkipNegotation option. We need to disable or delete it to connect and use azure signalr normally. Official doc: Configure additional options

enter image description here

Jason Pan
  • 15,263
  • 1
  • 14
  • 29