Search code examples
azureazure-signalrazure-functions-isolated

Azure SignalR: How to return ConnectionInfo when you don't know UserId in parameters yet?


I have a SignalR service that uses IHostedService to access SignalR on Azure. I'm trying to implement a Negotiate function that returns SignalRConnectionInfo. Problem is i need to pass the UserId into the ConnectionInfo but i don't know it yet when filling in parameters. I'm using .NET 8 in Isolated mode and following these Microsoft docs.

Function

[Function("Negotiate")]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "SomeHub", UserId = "????")] string connectionInfo)
{
    Guid userId = // Get userId from database
    await signalRService.AddUserToGroupAll(userId);
    return connectionInfo; // How to get this when i don't know UserId in the parameters yet??
}

SignalRService

public class SignalRService(IConfiguration configuration)
{
    private ServiceHubContext _messageHubContext;

    public async Task AddUserToGroupAll(Guid userId)
    {
        await _messageHubContext.Groups.AddToGroupAsync(userId.ToString(), /** groupname **/);
    }

    #region IHostService Functions
    async Task IHostedService.StartAsync(CancellationToken cancellationToken)
    {
        using ServiceManager serviceManager = new ServiceManagerBuilder()
            .WithOptions(o => o.ConnectionString = configuration[ConfigurationConstants.AzureSignalRConnectionString])
            .BuildServiceManager();
        _messageHubContext = await serviceManager.CreateHubContextAsync("SomeHub", cancellationToken);
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await _messageHubContext.DisposeAsync();
    }
    #endregion
}

My question is how do i return SignalRConnectionInfo in this case?

Thanks!


Solution

  • ServiceHubContext has a method called NegotiateAsync to which you can pass NegotiationOptions. You can set the UserId in there.

    For example:

    var negotiationResponse = await _serviceHubContext.NegotiateAsync(new NegotiationOptions { 
        UserId = userId.ToString() 
    });
    var connInfo = new SignalRConnectionInfo {
        AccessToken = negotiationResponse.AccessToken,
        Url = negotiationResponse.Url
    };
    

    And now you have your negotiated info with UserId.