2017-07-23 7 views
0

Ich muss Chat auf meinem Webprojekt implementieren. Wie man es auf einer Seite implementiert - es gibt viele Artikel darüber. Aber ich muss haben Fähigkeit: 1. andere Benutzer benachrichtigen, dass jemand Site angemeldet (auf jeder Seite, nicht nur auf dem Chat-Seite) 2. Andere Benutzer benachrichtigen, dass jemand abzumeldenSignalR - korrekte Implementierung des Chats

Also, ich habe folgendes Code der Nabe:

public void Connect() 
    { 
     try 
     { 
      var id = Context.ConnectionId; 
      string username = Context.User.Identity.Name; 

      var currentUser = connectedUsers.Where(p => p.Username == username).FirstOrDefault(); 
      if (currentUser == null) 
      { 
       AddNewUserToCollection(); 
      } 
      else 
      { 
       // update ConnectionId for sure (connection id is changed sometimes (probably if user is logged out and login again)) 
       if (currentUser.ConnectionId != id) 
       { 
        var companyId = _chatRepository.GetCompanyIdOfUser(username); // throws exception if companyId is null 
        Groups.Remove(currentUser.ConnectionId, companyId.ToString()); 
        Groups.Add(id, companyId.ToString()); 
        currentUser.ConnectionId = id; 
        //Clients.Group(companyId.ToString()).onNewUserConnected(username); 
       } 
      } 
     } 
     catch(InvalidCompanyException c_ex) 
     { 
      Clients.Client(Context.ConnectionId).onErrorMessage($"User '{c_ex.Username}' does not exist"); 
     } 
    } 


    public void Disconnect() 
    { 
     string username = Context.User.Identity.Name; 
     var item = connectedUsers.Where(p => p.Username == username).FirstOrDefault(); 
     if (item != null) 
     { 
      connectedUsers.Remove(item); 
      Groups.Remove(item.ConnectionId, item.CompanyID.ToString()); 
      Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username); 
     } 
    } 

    public override Task OnDisconnected(bool stopCalled) 
    { 
     var item = connectedUsers.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault(); 
     if (item != null) 
     { 
      connectedUsers.Remove(item); 
      Groups.Remove(item.ConnectionId, item.CompanyID.ToString()); 
      Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username); 
     } 
     return base.OnDisconnected(stopCalled); 
    } 

und I hinzugefügt, um den folgenden Code _layout.cshtml:

<script> 
     $(document).ready(function() { 
      var chat = $.connection.chatHub; 

      $.connection.hub.start().done(function() { 
       chat.server.connect(); 
      }); 
     }); 
    </script> 

andere Benutzer zu informieren, dass der aktuelle Benutzer angemeldet ist. Aber Debugger sagt, dass das Paar OnDisconnected/Connect jedes Mal aufgerufen wird, wenn Benutzer Seite mit verschiedenen ConnectionId neu laden (gehen durch Seiten). Wenn ich diesen Clientcode entferne - dieses Paar wird nicht aufgerufen. Wie man es richtig implementiert, um andere Benutzer zu benachrichtigen, dass jemand online ist, aber ohne jedes Mal neu zu verbinden?

+0

Sie sind fast für die einfachste Version da. Alles, was ich vorschlagen würde, wartet ein paar Sekunden, nachdem jemand die Verbindung trennt, bevor er allen anderen, die sie getrennt haben, mitteilt (und nur dann, wenn der Benutzer nicht mit einer neuen Verbindungs-ID aufgekreuzt ist). Ihr nächstes Problem besteht darin, mit einem Benutzer zu arbeiten, der mehrere Registerkarten geöffnet hat (Sie müssen die Anzahl der Verbindungen verfolgen, die jeder Benutzer hat). Dies wäre idealerweise in einer Hub-Pipeline, aber Sie sollten wahrscheinlich zuerst hier arbeiten. – thab

Antwort

1

Da Sie den Aufruf von connect() in einer Rasierer (_layout.cshtml) Seite haben, werden Sie effektiv trennen/verbinden bei jedem Post zurück (Seite laden).

Das Szenario, das Sie verwenden möchten, ist am besten in einem SPA (oder AJAX) -Szenario, in dem die Navigation asynchron von clientseitigem JavaScript verarbeitet wird. Ihr aktuelles Setup aktualisiert den Bildschirm, lädt das JavaScript neu und führt die Funktion ready() des Dokuments mit jeder vom Server gerenderten Navigation erneut aus.

Eine weitere Alternative besteht darin, die tatsächliche Benutzer-ID des Clients zu verwenden und diese an die server.connect (id) -Methode weiterzuleiten. Verwenden Sie diese Benutzer-ID dann, um die Benutzeraktivität anstelle des Hub ConnectionId zu verfolgen.

Verwandte Themen