1

I want to send a private message to a user, i have created a hub but unfortunately i have no idea how to do it in signalr core, the documentation also doesn't have any article in it.

  • Have you seen this tutorial? [Tutorial: Get started with ASP.NET Core SignalR](https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio) – Ammar Jun 23 '19 at 06:28

1 Answers1

0

How do i map user connection and user id in signalr so that i can send a message to a specific user

To achieve above requirement, please refer to the following example.

ChatHub class:

public class ChatHub : Hub
{
    public static List<KeyValuePair<string, string>> ConnectedIds = new List<KeyValuePair<string, string>>();

    public async Task SendMessage(string user, string message)
    {
        await Clients.Others.SendAsync("NoteUpdateNotification", user, message);

        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }

    public async Task SendPrivateMessage(string user, string message, string conid)
    {
        await Clients.Client(conid).SendAsync("ReceiveMessage", user, message + " (private message)");
    }

    public override async Task OnConnectedAsync()
    {
        var connId = Context.ConnectionId;

        var name = Context.GetHttpContext().Request.Query["user"].ToString();

        ConnectedIds.Add(new KeyValuePair<string, string>(connId, name));

        await Clients.All.SendAsync("updateList", ConnectedIds);

        await base.OnConnectedAsync();
    }
}

SignalR JavaScript Client:

<h1>PrivateChat</h1>

<div class="container">
    <div class="row">&nbsp;</div>
    <div class="row">
        <div class="col-6">&nbsp;</div>
        <div class="col-6">
            User..........
    <span id="uname"></span>
    @*<input type="text" id="userInput" />*@
            <br />
            Message...<input type="text" id="messageInput" />
            <input type="button" id="sendButton" value="Send Message" />
        </div>
    </div>
    <div class="row">
        <div class="col-12">
            <hr />
        </div>
    </div>
    <div class="row">
        <div class="col-6">&nbsp;</div>
        <div class="col-6">
            <ul id="messagesList"></ul>
        </div>
    </div>

    <div class="row">
        <div class="col-12">
            <hr />
        </div>
    </div>
    <div class="row">
        <div class="col-6">&nbsp;</div>
        <div class="col-6">
            <h2>Online Users</h2>
            <div>
                <!--<ul id="user_list"></ul>-->
                <div id="online"></div>
            </div>
        </div>
        <div class="col-12">
            <hr />
        </div>
        <div class="col-6">&nbsp;</div>
        <div class="col-6">
            <h2>Private Message</h2>
            <div id="user_id"></div>
            <input type="text" id="txtPrivateMessage" />
            <input type="button" id="sendprivatemessage" value="Send Private Message" />
            <input type="hidden" id="pconnId" value="" />
            <ul id="privatemessagelogs"></ul>
        </div>
    </div>
</div>


<script>
    var user = prompt('Enter your name:', '');
    $("#uname").text(user);
    var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub?user=" + user).build();

    //Disable send button until connection is established
    $("#sendButton").disabled = true;

    connection.on("ReceiveMessage", function (user, message) {
        var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        var encodedMsg = user + " says " + msg;

        var li = "<li>" + encodedMsg + "</li>";
        $("#messagesList").append(li);
    });

    connection.on("updateList", function (ids) {
        $('#online').empty();
        console.log(ids);

        $.each(ids, function (k, v) {
            console.log(v["key"] + "/" + v["value"]);

            if (v["value"].toString() != user) {
                $('#online').append("<span onclick=getValue('" + v["key"] + "','" + v["value"] + "')>" + v["value"] + "</span><br/>");
            }
        });
    });


    connection.start().then(function () {
        $("#sendButton").disabled = false;

    }).catch(function (err) {
        return console.error(err.toString());
    });

    $("#sendButton").on("click", function (event) {
        var message = $("#messageInput").val();

        connection.invoke("SendMessage", user, message).catch(function (err) {
            return console.error(err.toString());
        });
        event.preventDefault();
    });

    $("#sendprivatemessage").on("click", function (event) {
        var message = $("#txtPrivateMessage").val();
        var conid = $("#pconnId").val();
        connection.invoke("SendPrivateMessage", user, message, conid).catch(function (err) {
            return console.error(err.toString());
        });

        $('#privatemessagelogs').append('<li><strong>You sent: </strong>:&nbsp;&nbsp;' + $("#txtPrivateMessage").val() + '</li>');

        event.preventDefault();
    });

    function getValue(userId, name) {
        $("#user_id").text("Name: " + name + "Connection Id: " + userId);

        $("#pconnId").val(userId);

        $("#txtPrivateMessage").val("");

        $('#privatemessagelogs').empty();
    }
</script>

Test Result:

enter image description here

Note: The above example just for testing purpose, if you'd like to mapping user to connections on production environment, you can use permanent external storage, such as a database or Azure table storage for storing connection information.

Fei Han
  • 26,415
  • 1
  • 30
  • 41