后端:.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 时,我没有这个标题和我想在后端自己设置值。 医生
刚刚找到解决方案,希望这对其他人有帮助: 首先,您需要添加这个 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;
}