SignalR C#:向特定用户或组发送消息

问题描述 投票:0回答:1

后端:.NET 6、C#10、Azure 独立函数项目

NuGet:Microsoft.Azure.Functions.Worker.Extensions.SignalRService v1.7.0

如何向特定用户或群组发送消息?

我发现向 SignalRConnectionInfoInput.UserId 添加一个值是可行的,但是这个类是密封的,我找不到动态添加 UserId 值的方法。这是允许我向所有用户广播的有效协商功能:

[Function(nameof(Negotiate))]
public static HttpResponseData Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "MyHubName")] string connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "application/json");
    response.WriteString(connectionInfo);
    return response;
}

我可以使用这个 BroadcastAll 函数向所有用户发送消息:

    [Function(nameof(BroadcastToAll))]
    public static SignalRMessageAction BroadcastToAll([HttpTrigger(AuthorizationLevel.Anonymous,   
       "post", Route = nameof(BroadcastToAll))] HttpRequestData req)
    {
        using var bodyReader = new StreamReader(req.Body);
        var body = bodyReader.ReadToEnd();
        return new SignalRMessageAction("MyTargetName")
        {
            Arguments = new object[] { body },
        };
    }

但是我没有找到一种方法将它正确地发送给特定的用户,然后使用像这个 Negociate 函数示例中那样硬编码的 UserId 属性使其工作:

[Function(nameof(Negotiate))]
public static HttpResponseData Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "MyHubName", **UserId = "12345"**)] string connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "application/json");
    response.WriteString(connectionInfo);
    return response;
}

然后我可以使用 SignalRMessageAction 类中的 UserId 属性来指定 UserId = "12345" 我想在前端发送消息,只有这个用户会收到这条消息。

    [Function(nameof(SendToUser))]
    public static async Task<SignalRMessageAction> SendToUser(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", 
            Route = nameof(SendToUser))] HttpRequestData req)
    {
        using var bodyReader = new StreamReader(req.Body);
        var requestBody = await bodyReader.ReadToEndAsync();
        return new SignalRMessageAction("MyTargetName")
        {
            Arguments = new object[] { requestBody },
            UserId = "12345"
        };
    }

我发现,当您在属性中设置 UserId 时,Azure SignalR 服务返回的 accessToken 在 connectionInfo 中包含一个标识用户的声明: “asrs.s.uid”:“12345”

这是我的前端代码示例: FrontEnd: Angular, TypeScript, MSAL (@azure/msal-angular": "^2.3.0"), SignalR (@microsoft/signalr": "^7.0.5")

public ConnectSignalR(): void {
    this.hubConnection = new signalR.HubConnectionBuilder().withUrl(this.basePath).build();
    
    this.hubConnection
    .start()
    .then(() => console.log('Connection started'))
    .catch((err) => console.log('Error while starting connection: ' + err));
    
    this.hubConnection.on('MyTargetName', (mySignalRMessage: string) => {
        console.log(mySignalRMessage)
    });
}

public DisconnectSignalR(): void {
    if (this.hubConnection) {
      this.hubConnection.stop();
    }
}

感谢您的帮助,我希望它能在未来帮助其他人。

我尝试添加 UserId = "{headers.x-ms-client-principal-id}" 就像文档在 Authenticated tokens 部分所说的那样,但是当我使用 MSAL 时,我没有这个标题和我想在后端自己设置值。 医生

c# .net signalr c#-10.0 azure-functions-isolated
1个回答
0
投票

刚刚找到解决方案,希望这对其他人有帮助: 首先,您需要添加这个 NuGet:Microsoft.Azure.SignalR.Management

    [Function("negotiate")]
    public async Task<HttpResponseData> Negotiate([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
    {
        var negotiateResponse = await MessageHubContext.NegotiateAsync(new() { UserId = "12345" });
        var response = req.CreateResponse();
        await response.WriteAsJsonAsync(negotiateResponse, JsonObjectSerializer);
        return response;
    }
© www.soinside.com 2019 - 2024. All rights reserved.