0

I have a project in ASP.NET Core 2.1 MVC SignalR. When I started the project I did not select Individual Account options in authorization. I want to send the message using the user's email address stored in a database instead of the connection Id but I can't achieve this. How can I fix this problem?

This is my hub class code:

 public class SignalRChat:Hub
    {
        
        Context c = new Context();
        public async Task setUserEmail(string email)
        {
            string id = Context.ConnectionId;
            c.EmailConnectionIds.Where(a => a.connection_id == id).FirstOrDefault().email = email;
        }
        
        public async Task ClientSendMessage(string connectionId,string user, string message)
        {
           var deger= c.EmailConnectionIds.Where(a => a.connection_id ==
            connectionId).FirstOrDefault();
            

            await Clients.Client(deger.connection_id).SendAsync("ReceiveMessage",user, message);
        }


        public override async Task OnConnectedAsync()
        {

            EmailConnectionId val = new EmailConnectionId();
            val.connection_id = Context.ConnectionId; ;
            val.email = "";
           
            c.EmailConnectionIds.Add(val);
            c.SaveChanges();

           await  base.OnConnectedAsync();


        }
        public override Task OnDisconnectedAsync(Exception exception)
        {
            var connection = c.EmailConnectionIds.Where(a => a.connection_id ==
            Context.ConnectionId).FirstOrDefault();

            if (connection != null)
            {
                c.EmailConnectionIds.Remove(connection);
            }

            return base.OnDisconnectedAsync(exception);
        }

    }
    

This is my code:

"use strict";

$(document).ready(() => {
    var connection = new signalR.HubConnectionBuilder().withUrl("/chathub").build();
  

     var email = $("#client").val();
  
    connection.start().then(() => connection.invoke('setUserEmail ', email));

    $("#msg-send").click(() => {
        let message = $("#txtMessage").val();
        $("#txtMessage").val(" ");
        var user = $("#sender").val();
        connection.invoke("ClientSendMessage", $("#client").val(), user, message)
            .catch(error => console.log("Error." + error));       
        var div = document.createElement("div");
        div.textContent = message;
        
        document.getElementById("chat-cont").appendChild(div);
    });

    connection.on("ReceiveMessage", function (user, message) {
        var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        var encodedMsg =  msg;
        var div = document.createElement("div");
        div.textContent = encodedMsg;
        
        document.getElementById("chat-cont").appendChild(div);
    });
});

HTML code:

<div class="container">
    <div id="chat-cont" class="clearfix" style="max-height:450px;overflow:scroll;">
    </div>

    <div style="margin-top:470px;margin-left:40%;bottom:50px !important;" class="footer navbar-fixed-bottom">
        <div class="row">
            <h5>Connection ID : <span id="connectionId"></span></h5>
        </div>
        <div class="row">
            <div class="col-md-7"><input type="text" id="sender" value="@ViewBag.message"></div>
        </div>
        <div class="row">
            <div class="col-md-7"><input type="text" placeholder="ReceiverId" id="client"></div>
        </div>
        <div class="row">
            <div class="col-md-7" style="position:relative;"> <input type="text" id="txtMessage" class="form-control" style="width:70%;"></div>
            <div class="col-md-5" style="position:absolute;margin-left:40%;"> <button id="msg-send" class="btn btn-success">Send</button></div>
        </div>
    </div>
</div>
Cankan
  • 15
  • 5
  • 1
    I'm not sure for 2.1, but maybe this can help: [How to use web sockets in C# .NET Core 3.1?](https://stackoverflow.com/questions/62756390/how-to-use-web-sockets-in-c-sharp-net-core-3-1) – Lazar Đorđević Jan 20 '21 at 11:35
  • You can add each user to group with the group name being the email address. Then you send a message to the user in the group based on that email address – Vince Jan 20 '21 at 11:44
  • @Vince I tried it it works in identiry not my project , how can I select receiver email stored in db and sen him the message – Cankan Jan 20 '21 at 12:12
  • @Cankan https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/working-with-groups – Vince Jan 21 '21 at 06:34

1 Answers1

0

I would suggest that you create a list of current connections CurrentConnections

static HashSet<EmailConnectionID> CurrentConnections = new HashSet<EmailConnectionID>();
class EmailConnectionID
{
    public string email { get; set; }
    public string connection_id { get; set; }
}

add the entries to CurrentConnections OnConnectedAsync

public override async Task<Task> OnConnectedAsync()
{

EmailConnectionID val = new EmailConnectionID();
val.connection_id = Context.ConnectionId; ;
val.email = "";
CurrentConnections.Add(val);

return base.OnConnectedAsync();
}

then after the client connect first thing you do is to send the email to the hub and edit the entry on the CurrentConnections list with the email

public async Task setUserEmail(string email)
{
string id = Context.ConnectionId;
CurrentConnections.Where(a => a.connection_id == id).FirstOrDefault().email = email;
}

you shold remove enties from CurrentConnections list OnDisconnectedAsync

public override Task OnDisconnectedAsync(Exception exception)
{
var connection = CurrentConnections.Where(a => a.connection_id == 
Context.ConnectionId).FirstOrDefault();

if (connection != null)
{
    CurrentConnections.Remove(connection);
}

return base.OnDisconnectedAsync(exception);
}

after that you can send based on email address

Wowo Ot
  • 1,362
  • 13
  • 21
  • How do you store this list? – Vince Jan 21 '21 at 06:34
  • You don't store this list it's online , It's a list of currently online users. – Wowo Ot Jan 21 '21 at 09:35
  • @WowoOt how to call setUserEmail method in my js file? – Cankan Feb 04 '21 at 14:02
  • `await connection.invoke("setUserEmail ", email);` – Wowo Ot Feb 04 '21 at 19:58
  • @Wowo Ot I tried but Nothing happened, how can I use connection.invoke in my above js file and hub class – Cankan Feb 05 '21 at 16:03
  • @WowoOt I tried but Nothing happened, how can I use connection.invoke in my above js file and hub class – Cankan Feb 05 '21 at 16:04
  • Have tried to put it after start `connection.start().then(() => connection.invoke('setUserEmail ', email));` – Wowo Ot Feb 05 '21 at 16:27
  • @WowoOt I adapted to database with your code like above . I edited my problem in the above. Which codes are wrong? – Cankan Feb 05 '21 at 17:32
  • I'm not sure , it should be working , try to put a break point on the server Hub `OnConnectedAsync` to see if there is actually a connection with the server ! – Wowo Ot Feb 05 '21 at 19:39
  • Another thing you need to consider is to make sure that you have a valid `SSL` Certificate if your connection is over `https` , otherwise try it using regular `http`. – Wowo Ot Feb 06 '21 at 15:29