none
SignalR y Session RRS feed

  • Pregunta

  • Hola espero que esten bien.

    Tengo una aplicación la cual utiliza el SignalR para hacer consulta en la Base de datos tengo una Clase Hub

    Dentro tengo funciones las cuales hacen las operaciones, el problema que en una funcion necesito acceder a un dato que tendo en una variable de session "Session("IDProv")" pero me dice "Error de instancia de Objeto"

    de igual manera ya lo coloque asi:

    HttpContext.Current.Session("IDProv")

    y sigue el mismo error.

    Como puedo acceder a esa variable de session?

    Public Sub NotificationST()
            Dim IDP As Integer = HttpContext.Current.Session("IDProv") '<============ ¿COMO ACCESO A ESTA VARIABLE
            Dim JSNotificacion = Nothing
            Dim QueryString As String = "DECLARE @CTV AS INT, @FTV AS BIT EXEC dbo.NotificationST @IDP, @CTV OUT, @FTV OUT SELECT @CTV AS CTV, @FTV AS FTV"
            Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("CNX").ConnectionString)
                connection.Open()
                Using command As New SqlCommand(QueryString, connection)
                    command.Parameters.AddWithValue("IDP", IDP)
                    command.Notification = Nothing
                    Dim Dependency As New SqlDependency(command)
                    AddHandler Dependency.OnChange, AddressOf dependency_Onchange
                    If connection.State = ConnectionState.Closed Then
                        connection.Open()
                    End If
                    Dim Reader As SqlDataReader = command.ExecuteReader()
                    If Reader.Read Then
                        JSNotificacion = New With {.CTV = IIf(Reader("CTV") = 0, "", Reader("CTV")), .FTV = Reader("FTV")}
                    End If
                End Using
                Clients.All.notificationST(JSNotificacion)
            End Using
        End Sub

    sábado, 20 de mayo de 2017 18:07

Respuestas

  • hola

    Hasta donde conozco no puedes acceder a la Session en SignalR

    No access to the Session information through SignalR Hub

    es mas si necesitas accederlo es porque algo esta mal planteado, deberias pensar ese codigo para todos los proveedores y no para uno en concreto, pudiendo enviarles notificaciones si hace falta

    Si la idea es solo notificar a determinados proveedores deberia ser configurable, ya sea que lo tomes del .config que proveedores pueden ser notificados de cambios o quizas con algun campos en la tabla proveedor que indique si se notifican o no

    pero a donde voy es que las notificaciones de signalR deberian ser mas genericas y no depende de la Session

    Ademas un procedure no se ejecuta de esa forma, no se usa el EXEC, tienes que definir el CommandType

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Folanc miércoles, 24 de mayo de 2017 15:02
    lunes, 22 de mayo de 2017 11:20

Todas las respuestas

  • El problema es que la sesión se reconoce gracias a la cookie de sesión. Esa cookie es transmitida desde el navegador al servidor en cada navegación por http, y gracias a ella el servidor distingue cuál de todas las sesiones es la que tiene que usar. Pero cuando usas SignalR, no son peticiones http que contengan las cookies, sino que es un enlace "binario" a través de websockets. No se envía la cookie al servidor en cada llamada. Por lo tanto, el servidor no tiene forma de saber de qué sesión se trata. Tienes que usar algún otro mecanismo para identificar al cliente, en lugar de usar el Session. Por ejemplo, puedes añadir un parámetro a la función y que el cliente la llame pasando ahí algo que reconozcas en el servidor y que te permita recoger los datos asociados a ese cliente concreto.
    sábado, 20 de mayo de 2017 20:17
  • hola

    Hasta donde conozco no puedes acceder a la Session en SignalR

    No access to the Session information through SignalR Hub

    es mas si necesitas accederlo es porque algo esta mal planteado, deberias pensar ese codigo para todos los proveedores y no para uno en concreto, pudiendo enviarles notificaciones si hace falta

    Si la idea es solo notificar a determinados proveedores deberia ser configurable, ya sea que lo tomes del .config que proveedores pueden ser notificados de cambios o quizas con algun campos en la tabla proveedor que indique si se notifican o no

    pero a donde voy es que las notificaciones de signalR deberian ser mas genericas y no depende de la Session

    Ademas un procedure no se ejecuta de esa forma, no se usa el EXEC, tienes que definir el CommandType

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Folanc miércoles, 24 de mayo de 2017 15:02
    lunes, 22 de mayo de 2017 11:20
  • HOla Muchas gracias a los dos por darme respues, tomare muy encuenta sus comentarios.

    y si leandro lo que quiero hacer es como seran varios proveedores en mi Base, quiero que solo le llegue la notificacion o actualización al proveedor que le estoy dando seguimiento, no usar el "Clients.All" si no el "Clients.client", vaya lo que no tengo claro aun o no he visualizado porque aun inicie con el SignalR y estoy buscando información es como usar el ConnectionID, como almacenarlo o como vincularlo al proveedor, pues imagino que el ConnectionID cambia con cada inicio de sesión, o tu me recomiendas usar solo el "Clients.all"?.

    Con respecto a lo del procedimiento almacenado, investigare esa parte, ya que asi como lo tengo es un ejemplo que encontre.

    muchas gracias por sus respuestas.

    lunes, 22 de mayo de 2017 22:16
  • Ya hice el cambio del procedimiento almacenado es el siguiente:

    Public Sub NotificationCCP()
            Dim JSNotificacion = Nothing
            '"DECLARE @CTV AS INT, @FTV AS BIT EXEC dbo.NotificationCCP @CTV OUT, @FTV OUT SELECT @CTV AS CTV, @FTV AS FTV"
            Dim QueryString As String = "NotificationCCP"
            Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("CNX").ConnectionString)
                connection.Open()
                Using command As New SqlCommand(QueryString, connection)
                    command.CommandType = CommandType.StoredProcedure
                    Dim CTV As SqlParameter = command.Parameters.Add("CTV", SqlDbType.Int)
                    CTV.Direction = ParameterDirection.Output
                    Dim FTV As SqlParameter = command.Parameters.Add("FTV", SqlDbType.Bit)
                    FTV.Direction = ParameterDirection.Output
                    command.Notification = Nothing
                    Dim Dependency As New SqlDependency(command)
                    AddHandler Dependency.OnChange, AddressOf dependency_Onchange
                    If connection.State = ConnectionState.Closed Then
                        connection.Open()
                    End If
                    command.ExecuteNonQuery()
                    'Dim Reader As SqlDataReader = command.ExecuteReader()
                    'If Reader.Read Then
                    'JSNotificacion = New With {.CTV = Reader("CTV"), .FTV = Reader("FTV")}
                    'End If
                    JSNotificacion = New With {.CTV = CTV.Value, .FTV = FTV.Value}
                End Using
            End Using
            Clients.All.notificationCCP(JSNotificacion)
        End Sub
    Por favor si omití algo espero puedan decirme.

    lunes, 22 de mayo de 2017 22:39
  • hola

    si usas el

    command.CommandType = CommandType.StoredProcedure

    entonces no necesitas definir los parametros, el comand seria

    Dim JSNotificacion As String= "dbo.NotificationCCP"

    asi directo los parametros a la coleccion Parameters del command, aunque no veo donde asignas el CTV y FTV al command

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 23 de mayo de 2017 0:16
  • Hola de nuevo, tengo los cambios

     Public Sub NotificationCCP()
            Dim JSNotificacion = Nothing
            Dim QueryString As String = "dbo.NotificationCCP"
            Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("CNX").ConnectionString)
                connection.Open()
                Using command As New SqlCommand(QueryString, connection)
                    command.CommandType = CommandType.StoredProcedure
                    Dim CTV As SqlParameter = command.Parameters.Add("CTV", SqlDbType.Int)
                    CTV.Direction = ParameterDirection.Output
                    Dim FTV As SqlParameter = command.Parameters.Add("FTV", SqlDbType.Bit)
                    FTV.Direction = ParameterDirection.Output
                    command.Notification = Nothing
                    Dim Dependency As New SqlDependency(command)
                    AddHandler Dependency.OnChange, AddressOf dependency_Onchange
                    If connection.State = ConnectionState.Closed Then
                        connection.Open()
                    End If
                    command.ExecuteNonQuery()
                    JSNotificacion = New With {.CTV = CTV.Value, .FTV = FTV.Value}
                End Using
            End Using
            Clients.All.notificationCCP(JSNotificacion)
        End Sub

    Con respecto a tu pregunta de la asignación de los parametros CTV y FTV, si agrego un "command.Parameters.Add(CTV)" al momento de la ejecución me da un error, así como lo tengo me devuelve los valores, esto lo tome de un ejemplo en esta pagina: Como llamar un procedimiento

    Agradezco cualquier comentario.

    Saludos.

    martes, 23 de mayo de 2017 14:41
  • hola

    >>al momento de la ejecución me da un error, así como lo tengo me devuelve los valores

    ahh ok no habia visto que el Add() lo asignabas a la variable, por lo general simpre veia que se usa

    Dim CTV As New SqlParameter("CTV", SqlDbType.Int)
    CTV.Direction = ParameterDirection.Output
    command.Parameters.Add(CTV)

    pero tu forma tambien es correcta

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 23 de mayo de 2017 16:07
  • Hola, Leandro aprovechando esta misma pregunta.

    En esa función que tengo, esta se ejecuta a cada momento ya que le asigno este evento:

     AddHandler Dependency.OnChange, AddressOf dependency_Onchange

    y en el evento es así:

    Private Sub dependency_Onchange(ByVal sender As Object, ByVal e As SqlNotificationEventArgs)
            Call NotificationCCP()
        End Sub

    Pregunta: como se ejecuta a cada momento, esto afecta el rendimiento en este caso del servidor? ya sea que haya 1, 2, 3 o mas usuarios iniciados que lo utilicen?. intente colocar "If e.Type =SqlNotificationType.Change then" pero ya con este ya no entra porque lo que me devuelve es un e.Type =SqlNotificationType.Subscribe. hay alguna forma que solo se ejecute cuando haya cambios en mi BD?.

    Esta misma funcion asi como esta, me sirve para evitar el cierre de la sesión? ya que en ocaciones las variables Session despues de un tiempo me borra información.

    Espero me haya explicado.

    Saludos.

    miércoles, 24 de mayo de 2017 15:02