I have a client which receives messages over SignalR. It is working great but it is more like a broadcast. I would like to be able to send messages to a specific client. On the client-side I have a userId and I set up my connection like this:
const userId = getUserId();
if (userId) {
const beacon = new signalR.HubConnectionBuilder()
.withUrl(`${URL}/api?userId=${userId}"`)
.build();
beacon.on('newMessage', notification => console.log);
beacon.start().catch(console.error);
}
};
On the server-side (Azure Function written in JavaScript) I have a message and a userId. The question for me is how does the server know which SignalR connection is going to this specific user? Can I somehow tell SignalR who I am?
Using the Azure SignalR Service and the client-side code from the question I was able to get it to work. I used the following Azure Function to negotiate the connection:
module.exports = async function (context, req, connectionInfo) {
context.res.body = connectionInfo;
context.done();
};
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "signalRConnectionInfo",
"name": "connectionInfo",
"userId": "{userId}", // <----- IMPORTANT PART!
"hubName": "chat",
"direction": "in"
}
]
}
As well as another function to send a message to a specific user:
module.exports = async function (context, req) {
const messageObject = req.body;
return {
"target": "newMessage",
"userId": messageObject.userId,
"arguments": [ messageObject.message]
};
};
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "signalR",
"name": "$return",
"hubName": "chat",
"direction": "out"
}
]
}
If you are using Azure SignalR Service:
module.exports = async function (context, req) {
context.bindings.signalRMessages = [{
// message will only be sent to this user ID
"userId": "userId1",
"target": "newMessage",
"arguments": [ req.body ]
}];
};
One userId could map to multiple client connections (e.g. devices), be aware of that.
If you need to send messages to multiple users or are hosting SignalR yourself:
Groups are the easiest way to send messages to a subset of users. If you want to send a message to a certain user, you can use the userId
as the name of the group.
Deciding which user belongs to which group is a server-side feature, so you need to write some code.
module.exports = async function (context, req) {
context.bindings.signalRGroupActions = [{
"userId": req.query.userId,
"groupName": "myGroup",
"action": "add"
}];
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With