Azure SignalR message ignores SignalROptions

78 Views Asked by At

Locally it works perfectly, the message is camelcase.

{"type":1,"target":"questions","arguments":[[{"id":"1","text":"Test","columnId":"1"}]]}

But when I deploy the functions to Azure it's not working anymore.

{"type":1,"target":"questions","arguments":[[{"Id":"1","Text":"Test","ColumnId":"1"}]]}

I configured the Statup.cs as followed:

builder.Services.Configure<SignalROptions>(o => o.JsonObjectSerializer = new JsonObjectSerializer(
            new JsonSerializerOptions()
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            }));

EDIT:

The function call for the SignalR (where GetAllColumnsMapped just maps the DB result)

var payload = await GetAllColumnsMapped(tenantId, questions);
await signalRMessages.AddAsync(new SignalRMessage {Target = "columns", Arguments = new object[] {payload}});
1

There are 1 best solutions below

4
Dasari Kamali On

I tried the following sample function code to send messages to SignalR using an Azure Function App.

Code :

Function1.cs :

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;

namespace FunctionApp92
{
    public static class SignalRFunction
    {
        [FunctionName("SendToSignalR")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            [SignalR(HubName = "chat")] IAsyncCollector<SignalRMessage> signalRMessages,
            ILogger log)
        {
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            log.LogInformation("Received SignalR message: " + requestBody);
            var payload = JsonSerializer.Deserialize<SignalRMessagePayload>(requestBody);
            string serializedPayload = JsonSerializer.Serialize(payload);

            await signalRMessages.AddAsync(
                new SignalRMessage
                {
                    Target = "newMessage",
                    Arguments = new[] { serializedPayload }
                });

            return new OkObjectResult("SignalR message sent successfully");
        }
    }
}

Startup.cs :

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Azure.SignalR;
using Azure.Core.Serialization;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using System.Text.Json;
using Microsoft.Azure.SignalR.Management;
using System;

[assembly: FunctionsStartup(typeof(FunctionApp92.Startup))]

namespace FunctionApp92
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton(serviceProvider =>
            {
                var connectionString = Environment.GetEnvironmentVariable("AzureSignalRConnectionString");
                return new ServiceManagerBuilder()
                    .WithOptions(option =>
                    {
                        option.ConnectionString = connectionString;
                        option.ServiceTransportType = ServiceTransportType.Persistent;
                    })
                    .Build();
            });

            builder.Services.Configure<SignalROptions>(o => o.JsonObjectSerializer = new JsonObjectSerializer(
            new JsonSerializerOptions()
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            }));
        }
    }
}

SignalRMessagePayload.cs :

public class SignalRMessagePayload
{
    public int Type { get; set; }
    public string Target { get; set; }
    public List<List<Question>> Arguments { get; set; }
}

public class Question
{
    public string Id { get; set; }
    public string Text { get; set; }
    public string ColumnId { get; set; }
}

local.settings.json :

{
"AzureSignalRConnectionString": "Endpoint=https://<signalR_name>.service.signalr.net;AccessKey=<signalR_key>;Version=1.0;"
}

Postman output :

{
    "type": 1,
    "target": "questions",
    "arguments": [
        [
            {
                "id": "1",
                "text": "Test",
                "columnId": "1"
            }
        ]
    ]
}

enter image description here

Output :

It ran successfully, as shown below.

Azure Functions Core Tools
Core Tools Version:       4.0.5504 Commit hash: N/A +f829589bca9e7404c76db163c2d904326be8d347 (64-bit)
Function Runtime Version: 4.28.3.21820

[2024-02-12T04:10:41.466Z] Found C:\Users\xxxxxxxx\source\repos\FunctionApp92\FunctionApp92\FunctionApp92.csproj. Using for user secrets file configuration.

Functions:

        SendToSignalR: [GET] http://localhost:7103/api/SendToSignalR

For detailed output, run func with --verbose flag.
[2024-02-12T04:10:53.611Z] Host lock lease acquired by instance ID '00000000xxxxxxxxxxxx'.
[2024-02-12T08:15:36.558Z] Executing 'SendToSignalR' (Reason='This function was programmatically called via the host APIs.', Id=685b53f9xxxxxxxxxxxx)
[2024-02-12T08:15:36.641Z] Received SignalR message: {
[2024-02-12T08:15:36.643Z]     "type": 1,
[2024-02-12T08:15:36.645Z]     "target": "questions",
[2024-02-12T08:15:36.646Z]     "arguments": [
[2024-02-12T08:15:36.648Z]         [
[2024-02-12T08:15:36.655Z]             {
[2024-02-12T08:15:36.657Z]                 "id": "1",
[2024-02-12T08:15:36.659Z]                 "text": "Test",
[2024-02-12T08:15:36.661Z]                 "columnId": "1"
[2024-02-12T08:15:36.662Z]             }
[2024-02-12T08:15:36.664Z]         ]
[2024-02-12T08:15:36.667Z]     ]
[2024-02-12T08:15:36.669Z] }
[2024-02-12T08:15:36.673Z]
[2024-02-12T08:15:37.846Z] Executed 'SendToSignalR' (Succeeded, Id=685b53f9xxxxxxxxx, Duration=1947ms)

enter image description here

I added the SignalR connection string to the Function App App settings in the Azure Portal as follows.

"AzureSignalRConnectionString": "Endpoint=https://<signalR_name>.service.signalr.net;AccessKey=<signalR_key>;Version=1.0;"

enter image description here

I successfully published my project to the function app, as shown below:

enter image description here

Azure Portal :

The function app ran successfully in the Azure Portal, as shown below.

enter image description here