How Can I Send Message To specific User with signalR
Asked Answered
H

2

7

I have some problem with signalR, I can not send message to specific User From Hub.

I want to do like this:

public void Send(string userToId, string userForId, string message)
{

    IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ChatHubs>();

    //userForId - it is Session["UserId"]
    context.Clients.User(userForId).updateMessages(message);
}

I have already read this topic: http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections , but It's not clear for me, because I have not this var name = Context.User.Identity.Name; I have User information in Session Variable and second when I get connectionId like this: var myClientId = $.connection.hub.id; connectionId -is changed when I refresh page or when I click another menu on my project.

I have some questions: 1) Can I send message to specific user without connectionId (use only session["UserId"]) ? 2) In General, How can I make easily one-to-one messaging with SignalR ?

P.S. I'm working ASP.NET MVC (C#)

Hypophyge answered 25/2, 2015 at 5:36 Comment(1)
You may have a look at this answer. However, it doesn't use Session, but explains how to plug in custom user ids.Southport
A
7

You can send broadcast message to all Users without connection id. You just need to assign a Unique ID to Every user and Send it as Message parameters.

SignalR Gives a Unique ID to Every Client as connection ID. Either you can use that connection Id or you can assign unique ID to client while creating client and use it as Connection ID. thats up to you what you want to Use.

Edit

Just Update Your Your Method in your Hub Class File.....

     public void Send(string name, string message, string connectionid)
{
    // Call the addNewMessageToPage method to update clients.
    Clients.All.addNewMessageToPage(name, message, connectionid);
}

And In Your Client Side You can Update Add Code After including SignalR Files:-

        var chat = $.connection.chatHub;


             chat.client.addNewMessageToPage = function (name, message, connectionid) {
            if (connectionid == $('#connection').val()) {

               //   Do What You want Here...
            };
        };
        // Get the user name and store it to prepend to messages.
        $('#displayname').val(prompt('Enter your name:', ''));
        $('#connection').val(prompt('Enter your ID:', ''));

        // Set initial focus to message input box.
        $('#message').focus();
        // Start the connection.
        $.connection.hub.start().done(function () {
            $('#sendmessage').click(function () {
                // Call the Send method on the hub.
                chat.server.send($('#displayname').val(), $('#message').val(), $('#connection').val());
                // Clear text box and reset focus for next comment.
                $('#message').val('').focus();
            });
        });

Hope This Helps...

Arabesque answered 25/2, 2015 at 5:47 Comment(9)
Thank you for answer. How to get SignalR Unique ID and how to match it to custom application User (Session["User"]) , please give me code example.Hypophyge
@Arabesque Please edit your answer to include the code example. External links have a habit of going missing.Chlori
Nice example and smart solution, I try and give you feedback. Thank you one more for help me.Hypophyge
I think, this solution has some negative side, if you have about 1000 client online, when one user send message to other user, hub always call all 1000 users's function and check ConnectionId: chat.client.addNewMessageToPage = function (name, message, connectionid) { if (connectionid == $('#connection').val()) { // Do What You want Here... }; Do you have some idea to fix this problem ?Hypophyge
One thing you can try for it which is creating group. In Groups When a User sends Message into group than it only affacts clients added to group. So basically what can you do is create a group for two people.Arabesque
I've done what @Arabesque has suggested. I add each user to their own SignalR hub group. That way I have a group I can sort through, by whatever "name" I want to give it. Lets me normalize the code-read a bit.Harwill
This workaround is not good solution. Because as @AvtandilKavrelishvili said you always send message to all clients. Its so much unnecessary effort for SignalR and server.Gallman
In My Hub context.Clients.Client(connectionId).updateMessages(result); do not working, I get connectionId from client side like this: $.connection.hub.id; Can anybody help me ?Hypophyge
This is very bad idea, as mentioned before.Countertenor
G
5

If you want to send message to specific user in SignalR, easiest way is the use Form authentication. Also you can use your custom session with form authentication. Right after creation your session code put this code.

FormsAuthentication.SetAuthCookie(username.Trim(), false);

Then in signalR you can use this line for send message to this user:

var username = Context.User.Identity.Name;
context.Clients.User(username).updateMessages(message);

EDIT:

For your question pass username to this method (receiver username) and push message to that user.Then you dont need to give a userForId, because you already have sender username with "var username = Context.User.Identity.Name;".Also this method will just push to method that receiver user name. If you want to get also message to sender you need to user "Caller" and you need a write new function to get caller messages in javascript.I hope its clear for you.

public void Send(string username, string message)
{
    context.Clients.Caller.updateMessagesCaller(message);
    context.Clients.User(username).updateMessages(message);
}

This message will go only that username.And my recommendation is use FormAuthentication implementation in your whole project.Thanks.

Gallman answered 25/2, 2015 at 7:23 Comment(5)
Thank you for answer. I try and modify my solution to FormAuthentication and I have already done it. When I use this - var username = Context.User.Identity.Name; in hub, it get me My UserName, but I need other user username to send message.Hypophyge
I edited my answer for your question.Pls take a lookGallman
In My Hub context.Clients.Client(connectionId).updateMessages(result); do not working, I get connectionId from client side like this: $.connection.hub.id; Can anybody help me ?Hypophyge
suppose i want to send message to foo but when this code run Context.User.Identity.Name then it will give my name so how this line of code to send message to foo context.Clients.User(username).updateMessages(message); ? plzz help me to understand. thanksRenaud
what is context here?Cha

© 2022 - 2024 — McMap. All rights reserved.