user3687273
user3687273

Reputation: 63

SignalR HubConnection not receiving messages from serverless Azure SignalR service

I have created an Azure SignalR service in serverless mode. I have a suite of functions in an Azure Function App to manage a chat service which must include groups. When publishing the Function App I set the AzureSignalRConnectionString to that set under the Keys setting in the SignalR service. I have double checked in the Azure Portal that the connectionstring is present and correct.

I can use Postman to call the individual functions in Azure successfully and can monitor this in the Azure Portal and see logging messages etc.

However, if I use HubConnection in the client to attempt to call a function, it does not get there. Also, messages sent successfully by Postman do not cause the hub to fire receipt.

So the following call using the REST interface can be seen to execute from the Azure Portal:

await client.PostAsync($"{baseUrl}/api/{group}/add/{userName}", new StringContent(string.Empty));

however the following call using HubConnection does not trigger the same Azure Function:

await hubConnection.SendAsync("AddToGroup", group, userName);

The function bindings for this are:

[FunctionName("AddToGroup")]
public static async Task<IActionResult> Run(
    [HttpTrigger(
    AuthorizationLevel.Anonymous, 
    "post", 
    Route = "{groupName}/add/{userId}")] 
    HttpRequest req,
    string groupName,
    string userId,
    [SignalR(HubName = Constants.HubName)]
    IAsyncCollector<SignalRGroupAction> signalRGroupActions,
    ILogger log)
{
    log.LogInformation("AddToGroup invoked");

    await signalRGroupActions.AddAsync(
    new SignalRGroupAction
    {
        UserId = userId,
        GroupName = groupName,
        Action = GroupAction.Add
    });

    return new OkObjectResult("All done");
}

The Function App contains a Negotiate function which is used to initialise the Hub Connection like this:

var negotiateJson = await client.GetStringAsync($"{baseUrl}/api/negotiate");
var info = JsonConvert.DeserializeObject<NegotiateInfo>(negotiateJson);
hubConnection = new HubConnectionBuilder()
    .WithUrl(info.Url, options =>
    {
        options.AccessTokenProvider = () => Task.FromResult(info.AccessToken);
    })
    .Build();

Debugging this shows the Url to be correct and the Access Token is present.

I am using Microsoft.AspNetCore.SignalR.Client V3.0.0 and have followed through a number of guides and samples but cannot get the Azure SignalR hub to work.

(I have worked with hosted SignalR in the past and found it pretty straight forward but have not worked with the Azure service or Azure Functions before).

I would be eternally grateful for any assistance or guidance.

Thank you

Upvotes: 4

Views: 2516

Answers (2)

PramodValavala
PramodValavala

Reputation: 6647

Azure SignalR Service + Azure Functions currently doesn't now supports sending messages from a client to the service via SignalR as documented.

This achieved by setting up upstreams.

Instead, you will have to directly make the HTTP requests from the client.

Also, if required, you can achieve what you are trying by using ASP.NET Core with Azure SignalR instead of Azure Functions.

Upvotes: 1

range-rover
range-rover

Reputation: 51

Azure SignalR Service + Azure Functions supports sending messages from a client to service via SignalR (with ASP.NET CORE)

Serverside (Traditional Model):

[FunctionName("notifyServerViaSignalR")]
public async Task NotifyServerViaSignalR([SignalRTrigger("YourHub", "messages", "NotifyServerViaSignalR")]
InvocationContext invocationContext, [SignalRParameter] string additionalParameter, ILogger logger)
{
    logger.LogInformation($"Processed NotifyServerViaSignalR - AdditionalParameter:{additionalParameter} from ConnectionId:{invocationContext.ConnectionId}.");
}

Also configure, Upstream URL in Azure SignalR settings

<Function_App_URL>/runtime/webhooks/signalr?code=<API_KEY>

The Function_App_URL can be found on Function App's Overview page and The API_KEY is generated by Azure Function. You can get the API_KEY from signalr_extension in the App keys blade of Function App.

Clientside:

connection.invoke("NotifyServerViaSignalR", additionalParameter);

Upvotes: 1

Related Questions