32 messaggi dal 13 agosto 2017
Salve amici, in Signalr al refresh della pagina si perde la connessione e se ne crea una nuova causando il fastidioso "off-on" dell'utente. A tal proposito per ovviare all'inconveniente avrei pensato di salvare la session-state della pagina in un file xml e poi richiamarlo, è corretto? C'è un metodo migliore? Come dovrei operare? Il codice lato server che ho implementato è questo:


Imports Microsoft.AspNet.SignalR
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports Chatproject.SignalRChat.Common
Imports System.Threading.Tasks
Imports Microsoft.Owin
Imports Owin

Namespace Chatproject
    Public Class ChatHub
        Inherits Hub
#Region "Data Members"

        Shared ConnectedUsers As New List(Of UserDetail)()
        Shared CurrentMessage As New List(Of MessageDetail)()

#End Region

#Region "Methods"

        Public Sub Connect(userName As String)
            Dim id = Context.ConnectionId


            If ConnectedUsers.Where(Function(x) x.ConnectionId = id).Count = 0 Then
                ConnectedUsers.Add(New UserDetail() With { _
                    .ConnectionId = id, _
                    .UserName = userName _
                })


                ' send to caller
                Clients.Caller.onConnected(id, userName, ConnectedUsers, CurrentMessage)

                ' send to all except caller client

                Clients.AllExcept(id).onNewUserConnected(id, userName)
            End If

        End Sub
        Public Sub Send(ByVal msg As String, ByVal room As String, ByVal userName As String)
            Clients.Group(room).addMessage(msg, room)
            Clients.Group(room).messageReceived(userName, msg)
            AddMessageinCache(userName, msg)
        End Sub

        Public Sub JoinRoom(ByVal roomName As String, ByVal userName As String)
            Groups.Add(Context.ConnectionId, roomName)
            Dim msg As String = "<div class='text-muted'>" & userName & " joined the chat.</div>"
            Clients.Group(roomName).addMessage(msg, roomName)
            Clients.Group(roomName).messageReceived(userName, msg)
        End Sub

        Public Sub LeaveRoom(ByVal roomName As String, ByVal userName As String)
            Groups.Remove(Context.ConnectionId, roomName)
            Dim msg As String = "<div class='text-muted'>" & userName & " quit the chat.</div>"
            Clients.Group(roomName).addMessage(msg, roomName)
            Clients.Group(roomName).messageReceived(userName, msg)
        End Sub

        Public Sub SendPrivateMessage(toUserId As String, message As String)

            Dim fromUserId As String = Context.ConnectionId

            Dim toUser = ConnectedUsers.FirstOrDefault(Function(x) x.ConnectionId = toUserId)
            Dim fromUser = ConnectedUsers.FirstOrDefault(Function(x) x.ConnectionId = fromUserId)

            If toUser IsNot Nothing AndAlso fromUser IsNot Nothing Then
                ' send to 
                Clients.Client(toUserId).sendPrivateMessage(fromUserId, fromUser.UserName, message)

                ' send to caller user
                Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message)
            End If

        End Sub

        Public Overrides Function OnDisconnected(stopCalled As Boolean) As Threading.Tasks.Task

            Dim item = ConnectedUsers.FirstOrDefault(Function(x) x.ConnectionId = Context.ConnectionId)
            If item IsNot Nothing Then
                ConnectedUsers.Remove(item)
                Dim id = Context.ConnectionId

                Clients.All.onUserDisconnected(id, item.UserName)
            End If

            Return MyBase.OnDisconnected(stopCalled)
        End Function



#End Region

#Region "private Messages"

        Private Sub AddMessageinCache(userName As String, message As String)
            CurrentMessage.Add(New MessageDetail() With { _
                .UserName = userName, _
                .Message = message _
            })

            If CurrentMessage.Count > 100 Then
                CurrentMessage.RemoveAt(0)
            End If
        End Sub

#End Region
    End Class

End Namespace


Grazie a tutti.
Modificato da MarkRoss il 26 gennaio 2018 19.23 -
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


in Signalr al refresh della pagina

In quali situazioni la pagina si refresha? Intendi dire quando l'utente preme F5 per ricaricarla? Oppure ci sono altre operazioni che l'utente compie e che portano al ricaricarsi della pagina?


A tal proposito per ovviare all'inconveniente avrei pensato di salvare la session-state della pagina in un file xml e poi richiamarlo, è corretto?

Uhm, non ho capito ma credo di non aver mai usato questa tecnica.

Dovresti cercare di non refreshare mai la pagina. Se devi inviare info al server, inviale con una richiesta Ajax.

ciao,
Moreno

Enjoy learning and just keep making
32 messaggi dal 13 agosto 2017
Ciao Moreno e grazie per la risposta, in sostanza se per esempio ho 100 utenti collegati e 5-6 di loro per i piu svariati motivi refreshano la pagina immagini bene che un effetto "userx disconnesso - userx connesso" ripetuto crea fastidio...detto ció stavo cercando di capire, come del resto anche tu mi consigliavi, come creare codice con le spa ajax ma ad essere sincero non c'ho capito niente... potresti farmi un esempio?
Grazie e un saluto.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Mark,
ripropongo il mio quesito: i refresh di cui parli, sono fatti intenzionalmente dall'utente premendo F5 oppure si verificano a causa di interazioni manuali o automatiche con la pagina durante la chat (es. mentre chatta, l'utente riceve istruzioni su come usare il sito e perciò fa la navigazione verso altre pagine)?

Nel primo caso, non è utile implementare funzionalità Ajax nel sito perché se l'utente preme F5, la pagina si ricaricherà a prescindere.
Nel secondo caso, forse una Single Page Application ridurrebbe il problema al minimo però non è detto che valga la pena affrontare il costo della riscrittura, soprattutto se non hai ancora realizzato pagine con funzionalità Ajax.

Una soluzione per entrambe le situazioni potrebbe essere questa: quando SignalR rileva che un utente si è disconnesso, non comunicarlo subito agli altri client. Invece, predisponi una sorta di timer che invierà tale comunicazione in maniera differita (es. dopo 20 secondi). Se l'utente dovesse ricollegarsi in quel frangente, interrompi il timer perché non aveva l'effettiva intenzione di lasciare la chat. In questo modo, gli altri client non percepiranno alcuna disconnessione da parte di quell'utente.

Attenzione perché nell'intervallo di tempo in cui la pagina si refreshava, l'utente non era connesso all'hub e perciò potrebbe aver perso dei messaggi. Alla sua riconnessione devi essere in grado di recapitargli tutti i messaggi recenti, in modo che anche a lui sembri di non essersi mai disconnesso dalla chat.

ciao,
Moreno
Modificato da BrightSoul il 04 febbraio 2018 11.31 -

Enjoy learning and just keep making
32 messaggi dal 13 agosto 2017
Di nuovo grazie a te per l'ennesima risposta BrightSoul, bè diciamo che non c'è un motivo vero e proprio per cui un utente debba fare un refresh della pagina ma in fase di programmazione uno sviluppatore, come ben sai, deve prevedere un pò di tutto. Detto ciò la parte relativa al tasto f5 è superabile con relativa funzione javascript. Volendo andare ancora in profondità si può disabilitare il tasto destro del mouse con altra funzione ecc...ecc...Rimane il fatto del tasto del browser che praticamente (e per fortuna direi per ovvi motivi di sicurezza) non può essere disattivato...ho provato anche con il timer ma questo comporta di fatto un fastidioso "utente disconnesso-utente connesso" pertanto a mio avviso penso sia meglio lasciarlo così com'è...
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


Volendo andare ancora in profondità si può disabilitare il tasto destro del mouse con altra funzione ecc...ecc...

No no, non lo fare. Lascia all'utente la libertà di refreshare, se vuole. Tanto non possiamo farci niente.



ho provato anche con il timer ma questo comporta di fatto un fastidioso "utente disconnesso-utente connesso"

Fai vedere il codice che hai usato. Con il timer dovresti risolvere. Non è che per caso stai notificando i client all'OnDisconnect? Devi ritardare la notifica e inviarla solo quando il timer scade.

ciao,
Moreno

Enjoy learning and just keep making
32 messaggi dal 13 agosto 2017
Si il timer l'ho inserito sull' "onUserDisconnected", comunque questo è il codice client :

  function registerClientMethods(chatHub) {

                 // Calls when user successfully logged in
                 chatHub.client.onConnected = function (id, userName, allUsers, messages) {

                     setScreen(true);

                     $('#hdId').val(id);
                     $('#hdUserName').val(userName);
                     $('#spanUser').html(userName);

                     // Add All Users
                     for (i = 0; i < allUsers.length; i++) {

                         AddUser(chatHub, allUsers[i].ConnectionId, allUsers[i].UserName);
                     }

                     // Add Existing Messages
                     for (i = 0; i < messages.length; i++) {

                         AddMessage(messages[i].UserName, messages[i].Message);
                     }


                 }

                 // On New User Connected
                 chatHub.client.onNewUserConnected = function (id, name) {
                    
                     AddUser(chatHub, id, name);

                                     }


                 // On User Disconnected
                 chatHub.client.onUserDisconnected = function (id, userName) {
                     setTimeout(function () {
                          var roomname = $('#hdSelectedRoom').val();

                     chatHub.server.leaveRoom(roomname, userName);

                     $('#' + id).remove();

                     var ctrId = 'private_' + id;
                     $('#' + ctrId).remove();


                     var disc = $('<div class="disconnect">"' + userName + '" logged off.</div>');

                     $(disc).hide();
                     $('#divusers').prepend(disc);
                     $(disc).fadeIn(200).delay(2000).fadeOut(200);
                     }, 15000);
                   

                 }

                 chatHub.client.messageReceived = function (userName, message) {

                     AddMessage(userName, message);
                 }
 function AddUser(chatHub, id, name) {

                 var userId = $('#hdId').val();

                 var code = "";

                 if (userId == id) {

                     code = $('<div class="loginUser">' + '<ul class="users-list clearfix">' + '<li>' + '<img src="Avatar/A01.png"/>' + name + '</a>' + '<span class="users-list-date">' + '</span>' + '</li>' + '</ul>' + "</div>");

                 }
                 else {

                     code = $('<a id="' + id + '" class="user" >' + '<ul class="users-list clearfix">' + '<li>' + '<img src="Avatar/A01.png"/>' + name + '<span class="users-list-date">' + '</span>' + '</li>' + '</ul>' + '</a>');

                     $(code).dblclick(function () {

                         var id = $(this).attr('id');

                         if (userId != id)
                             OpenPrivateChatWindow(chatHub, id, name);

                     });
                 }


                 $("#divusers").append(code);

             }


Grazie ancora.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ok, benissimo, puoi far vedere anche il codice lato server?
In particolare, quando invochi la funzione client onUserDisconnected?

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.