Solución de problemas de SignalR

por Patrick Fletcher

Advertencia

Esta documentación no se aplica a la última versión de SignalR. Eche un vistazo a SignalR de ASP.NET Core.

En este documento se describen los problemas comunes con SignalR.

Versiones de software empleadas en este tema

Versiones anteriores de este tema

Para obtener información sobre versiones anteriores de SignalR, consulte Versiones anteriores de SignalR.

Preguntas y comentarios

Deje sus comentarios sobre este tutorial y sobre lo que podríamos mejorar en los comentarios en la parte inferior de la página. Si tiene alguna pregunta que no esté directamente relacionadas con el tutorial, puede publicarla en el foro de ASP.NET SignalR o en StackOverflow.com.

Este documento contiene las siguientes secciones.

Se produce un error silencioso en los métodos de llamada entre el cliente y el servidor

En esta sección se describen las posibles causas de que una llamada a un método entre cliente y servidor falle sin que aparezca un mensaje de error significativo. En una aplicación de SignalR, el servidor no tiene información sobre los métodos que implementa el cliente; cuando el servidor invoca un método del cliente, el nombre del método y los datos de los parámetros se envían al cliente, y el método se ejecuta solo si existe en el formato que especificó el servidor. Si no se encuentra ningún método coincidente en el cliente, no ocurre nada y no se emite ningún mensaje de error en el servidor.

Para investigar más a fondo los métodos del cliente a los que no se llama, puede activar el registro antes de llamar al método de inicio en el centro de conectividad para ver qué llamadas proceden del servidor. Para habilitar el registro en una aplicación de JavaScript, consulte Habilitación del registro del lado del cliente (versión cliente de JavaScript). Para habilitar el registro en una aplicación cliente .NET, consulte Habilitación del registro del lado del cliente (versión cliente .NET).

Método mal escrito, firma de método incorrecta o nombre del centro de conectividad incorrecto

Si el nombre o la firma de un método llamado no coincide exactamente con un método apropiado en el cliente, la llamada fallará. Compruebe que el nombre del método invocado por el servidor coincide con el nombre del método en el cliente. Además, SignalR crea el proxy del centro de conectividad usando métodos con mayúsculas y minúsculas, como es apropiado en JavaScript, por lo que un método llamado SendMessage en el servidor se llamaría sendMessage en el proxy del cliente. Si usa el atributo HubName en su código del lado del servidor, verifique que el nombre usado coincide con el utilizado para crear el centro de conectividad en el cliente. Si no usa el atributo HubName, compruebe que el nombre del centro de conectividad en un cliente JavaScript está en mayúsculas y minúsculas, como chatHub en lugar de ChatHub.

Nombre de método duplicado en el cliente

Compruebe que no tiene un método duplicado en el cliente que solo difiere por mayúsculas y minúsculas. Si su aplicación cliente tiene un método llamado sendMessage, verifique que no haya también un método llamado SendMessage.

Falta el analizador JSON en el cliente

SignalR requiere la presencia de un analizador JSON para serializar las llamadas entre el servidor y el cliente. Si su cliente no tiene un analizador JSON incorporado (como Internet Explorer 7), tendrá que incluir uno en su aplicación. Puede descargar el analizador sintáctico de JSON aquí.

Combinación de la sintaxis de Hub y PersistentConnection

SignalR usa dos modelos de comunicación: Hubs y PersistentConnections. La sintaxis para llamar a estos dos modelos de comunicación es diferente en el código del cliente. Si ha agregado un centro de conectividad en el código de su servidor, verifique que todo el código de su cliente usa la sintaxis de centro adecuada.

Código de cliente JavaScript que crea una PersistentConnection en un cliente JavaScript

var myConnection = $.connection('/echo');

Código de cliente JavaScript que crea un centro de conectividad mediante proxy en un cliente JavaScript

var myHub = $.connection.MyHub;

Código de servidor C# que asigna una ruta a una PersistentConnection

RouteTable.Routes.MapConnection<MyConnection>("my", "/echo");

Código de servidor C# que asigna una ruta a un centro de conectividad, o a varios centros de conectividad si tiene varias aplicaciones

App.MapSignalR();

Conexión iniciada antes de agregar las suscripciones

Si la conexión del centro de conectividad se inicia antes de que los métodos que pueden ser llamados desde el servidor sean agregados al proxy, los mensajes no se recibirán. El siguiente código JavaScript no iniciará el centro de conectividad correctamente:

Código de cliente JavaScript incorrecto que no permitirá recibir mensajes de los centros de conectividad

var chat = $.connection.chatHub;
$.connection.hub.start().done(function () {
    chat.client.broadcastMessage = function (name, message) {...};
});

En su lugar, agregue las suscripciones del método antes de llamar a Inicio:

Código de cliente JavaScript que agrega correctamente suscripciones a un centro de conectividad

var chat = $.connection.chatHub;
chat.client.broadcastMessage = function (name, message) {...};
    $.connection.hub.start().done(function () {
        ...
    });

Falta el nombre del método en el proxy del centro de conectividad

Compruebe que el método definido en el servidor está suscrito en el cliente. Aunque el servidor defina el método, hay que agregarlo mediante proxy al cliente. Los métodos pueden agregarse al proxy del cliente de las siguientes maneras (tenga en cuenta que el método se agrega al miembro client del centro de conectividad, no al centro de conectividad directamente):

Código de cliente JavaScript que agrega métodos a un proxy del centro de conectividad

// Method added to proxy in JavaScript:
myHubProxy.server.method1 = function (param1, param2) {...};
//Multiple methods added to proxy in JavaScript using jQuery:
$.extend(myHubProxy.server, {
    method1: function (param1, param2) {...},
    method2: function (param3, param4) {...}
});

Centro de conectividad o métodos de centro de conectividad no declarados como públicos

Para que sean visibles en el cliente, la implementación y los métodos del centro de conectividad deben declararse como public.

Acceso al centro de conectividad desde una aplicación diferente

Solo se puede acceder a SignalR Hubs a través de aplicaciones que implementen clientes de SignalR. SignalR no puede interoperar con otras bibliotecas de comunicación (como los servicios web de SOAP o WCF.) Si no hay ningún cliente de SignalR disponible para su plataforma de destino, no podrá acceder directamente al punto de conexión del servidor.

Serialización manual de datos

SignalR usará automáticamente JSON para serializar los parámetros del método; no es necesario hacerlo usted mismo.

El método del centro de conectividad remoto no se ejecuta en el cliente en la función OnDisconnected

Este comportamiento es por diseño. Cuando se escribe OnDisconnected, el centro de conectividad ya ha entrado en el estado Disconnected, que no permite llamar a más métodos del centro de conectividad.

Código de servidor C# que ejecuta correctamente el código en el evento OnDisconnected

public class MyHub : Hub
{
    public override Task OnDisconnected()
    {
        // Do what you want here
        return base.OnDisconnected();
    }
}

OnDisconnect no se activa en momentos consistentes

Este comportamiento es por diseño. Cuando un usuario intenta alejarse de una página con una conexión de SignalR activa, el cliente de SignalR realizará un mejor intento de notificar al servidor que se detendrá la conexión de cliente. Si el intento de mejor esfuerzo del cliente de SignalR no puede llegar al servidor, el servidor eliminará la conexión después de una configuración configurable DisconnectTimeout más adelante, en cuyo momento se desencadenará el evento OnDisconnected. Si el intento de mejor esfuerzo del cliente de SignalR es correcto, el evento OnDisconnected se desencadenará inmediatamente.

Para obtener información sobre cómo establecer la configuración DisconnectTimeout, consulte Control de eventos de duración de conexión: DisconnectTimeout.

Límite de conexión alcanzado

Cuando se usa la versión completa de IIS en un sistema operativo cliente como Windows 7, se impone un límite de 10 conexiones. Si usa un sistema operativo cliente, use IIS Express en su lugar para evitar este límite.

La conexión entre dominios no se ha configurado correctamente

Si una conexión entre dominios (una conexión para la que la URL de SignalR no se encuentra en el mismo dominio que la página de hospedaje) no se configura correctamente, la conexión puede fallar sin que aparezca un mensaje de error. Para obtener información sobre cómo habilitar la comunicación entre dominios, consulte Establecimiento de una conexión entre dominios.

La conexión mediante NTLM (Active Directory) no funciona en el cliente de .NET

Una conexión en una aplicación cliente de .NET que use la seguridad de dominio puede fallar si la conexión no está configurada correctamente. Para usar SignalR en un entorno de dominio, establezca la propiedad de conexión necesaria como se indica a continuación:

Código de cliente C# que implementa las credenciales de conexión

connection.Credentials = CredentialCache.DefaultCredentials;

Configuración de websockets de IIS para hacer ping/pong para detectar un cliente inactivo

Los servidores de SignalR no saben si el cliente está inactivo o no y dependen de la notificación del websocket subyacente para los errores de conexión, es decir, la devolución de llamada OnClose. Una solución a este problema es configurar websockets de IIS para hacer el ping/pong para usted. Esto garantiza que la conexión se cerrará si se interrumpe inesperadamente. Para más información, consulte esta publicación de StackOverflow.

Otros problemas de conexión

En esta sección se describen las causas y soluciones para síntomas específicos o mensajes de error que se producen durante una conexión.

Error "Start must be called before data can be sent"

Este error se suele ver si el código hace referencia a objetos SignalR antes de que se inicie la conexión. La conexión para controladores y similares que llamarán a métodos definidos en el servidor debe agregarse una vez finalizada la conexión. Tenga en cuenta que la llamada a Start es asincrónica, por lo que el código posterior a la llamada puede ejecutarse antes de su finalización. La mejor manera de agregar controladores después de que una conexión se inicie por completo es colocarlos en una función de devolución de llamada que se pase como parámetro al método de inicio:

Código cliente de JavaScript que agrega correctamente controladores de eventos que hacen referencia a objetos SignalR

$.connection.hub.start().done(function () {
    // Wire up Send button to call NewContosoChatMessage on the server.
    $('#newContosoChatMessage').click(function () {
        contosoChatHubProxy.server.newContosoChatMessage(
            $('#displayname').val(), $('#message').val());
            $('#message').val('').focus();
    });

Este error también se verá si una conexión se detiene mientras se siguen haciendo referencias a los objetos SignalR.

Error "301 Moved Permanently" o "302 Moved Temporarily"

Este error puede verse si el proyecto contiene una carpeta llamada SignalR, que interferirá con el proxy creado automáticamente. Para evitar este error, no use una carpeta llamada SignalR en su aplicación, o desactive la generación automática de proxy. Consulte El proxy generado y lo que hace por usted para obtener más detalles.

Error "403 Forbidden" en el cliente de Silverlight o .NET

Este error puede producirse en entornos multidominio en los que la comunicación entre dominios no esté habilitada correctamente. Para obtener información sobre cómo habilitar la comunicación entre dominios, consulte Establecimiento de una conexión entre dominios. Para establecer una conexión entre dominios en un cliente de Silverlight, consulte Conexiones entre dominios desde clientes de Silverlight.

Error "404 Not Found"

Hay varias causas de este problema. Verifique todo lo siguiente:

  • La referencia a la dirección del proxy del centro de conectividad no tiene el formato correcto: este error se suele ver si la referencia a la dirección del proxy del centro de conectividad generado no tiene el formato correcto. Compruebe que la referencia a la dirección del centro de conectividad se hace correctamente. Consulte Referencia al proxy generado dinámicamente para obtener más detalles.

  • Añadir rutas a la aplicación antes de añadir la ruta al centro de conectividad: si su aplicación usa otras rutas, compruebe que la primera ruta agregada es la llamada a MapSignalR.

  • Usar IIS 7 o 7.5 sin la actualización de direcciones URL sin extensión: el uso de IIS 7 o 7.5 requiere una actualización para las direcciones URL sin extensión para que el servidor pueda proporcionar acceso a las definiciones del centro de conectividad en /signalr/hubs. La actualización se puede encontrar aquí:

  • Caché de IIS obsoleta o dañada: para comprobar que el contenido de la caché no está actualizado, escriba el siguiente comando en una ventana de PowerShell para borrar la memoria caché:

    net stop w3svc
    Remove-Item -Path "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\*" -Force -Recurse
    net start w3svc
    

"500 Error interno del servidor"

Se trata de un error muy genérico que puede tener causas muy diversas. Los detalles del error deberían aparecer en el registro de eventos del servidor, o pueden encontrarse depurando el servidor. Puede obtener información más detallada sobre los errores activando la opción de errores detallados en el servidor. Para más información, consulte Control de los errores en la clase Hub.

Este error también se ve normalmente si un firewall o proxy no está configurado correctamente, lo que provoca que los encabezados de solicitud se vuelvan a escribir. La solución consiste en asegurarse de que el puerto 80 está habilitado en el firewall o el proxy.

"Código de respuesta inesperado: 500".

Este error puede producirse si la versión de .NET Framework usada en la aplicación no coincide con la versión especificada en Web.Config. La solución consiste en comprobar que .NET 4.5 se usa en la configuración de la aplicación y en el archivo Web.Config.

Error "TypeError: <hubType> no está definido"

Este error se producirá si la llamada a MapSignalR no se realiza correctamente. Consulte Registro de la ruta de SignalR y configurar las opciones de SignalR para más información.

El código de usuario no controla JsonSerializationException

Compruebe que los parámetros que envía a sus métodos no incluyen tipos no serializables (como manipuladores de archivos o conexiones a bases de datos). Si necesita usar miembros en un objeto del lado del servidor que no quiere que se envíe al cliente (ya sea por seguridad o por razones de serialización), use el atributo JSONIgnore.

Error "Protocol error: Unknown transport"

Este error puede producirse si el cliente no es compatible con los transportes que usa SignalR. Consulte Transportes y reservas para obtener información sobre qué exploradores se pueden usar con SignalR.

Error "JavaScript Hub proxy generation has been disabled."

Este error se producirá si se establece DisableJavaScriptProxies incluyendo también una referencia al proxy generado dinámicamente en signalr/hubs. Para más información sobre cómo crear el proxy manualmente, consulte El proxy generado y lo que hace por usted.

Error "The connection ID is in the incorrect format" o "The user identity cannot change during an active SignalR connection"

Este error puede verse si se está usando la autenticación y el cliente se desconecta antes de que se detenga la conexión. La solución consiste en detener la conexión de SignalR antes de cerrar el registro del cliente.

Error "Uncaught Error: SignalR: jQuery not found. Please ensure jQuery is referenced before the SignalR.js file"

El cliente JavaScript de SignalR requiere jQuery para funcionar. Compruebe que su referencia a jQuery es correcta, que la ruta de acceso usada es válida y que la referencia a jQuery es anterior a la referencia a SignalR.

Error "Uncaught TypeError: Cannot read property '<property>' of undefined"

Este error es el resultado de no tener las referencias adecuadas a jQuery o al proxy de los centros de conectividad. Verifique que su referencia a jQuery y al proxy del centro de conectividad es correcta, que la ruta de acceso usada es válida y que la referencia a jQuery está antes de la referencia al proxy de centros de conectividad. La referencia predeterminada al proxy de centros de conectividad debe ser similar a la siguiente:

Código HTML del lado del cliente que hace referencia correctamente al proxy del centro de conectividad

<script src="/signalr/hubs"></script>

Error "RuntimeBinderException was unhandled by user code"

Este error puede producirse cuando se usa una sobrecarga incorrecta de Hub.On. Si el método tiene un valor devuelto, el tipo de valor devuelto debe especificarse como parámetro de tipo genérico:

Método definido en el cliente (sin proxy generado)

MyHub.On<ReturnType>("MethodName", LocalMethod);

El id. de conexión es incoherente o la conexión se interrumpe entre cargas de página

Este comportamiento es por diseño. Dado que el objeto Hub se aloja en el objeto de página, el centro de conectividad se destruye cuando se actualiza la página. Una aplicación multipágina necesita mantener la asociación entre usuarios e id. de conexión para que sean coherentes entre cargas de páginas. Los id. de conexión pueden almacenarse en el servidor en un objeto de ConcurrentDictionary o en una base de datos.

Error "Value cannot be null"

Los métodos del lado del servidor con parámetros opcionales no son compatibles actualmente; si se omite el parámetro opcional, el método fallará. Para obtener más información, consulta Parámetros opcionales.

Error "Firefox can't establish a connection to the server at <address>" en Firebug

Este mensaje de error se puede ver en Firebug si falla la negociación del transporte WebSocket y se usa otro transporte en su lugar. Este comportamiento es por diseño.

Error "The remote certificate is invalid according to the validation procedure" en la aplicación cliente de .NET

Si su servidor requiere certificados de cliente personalizados, puede agregar un certificado x509 a la conexión antes de que se realice la solicitud. Agregue el certificado a la conexión usando Connection.AddClientCertificate.

La conexión se anula tras agotarse el tiempo de autenticación

Este comportamiento es por diseño. Las credenciales de autenticación no pueden modificarse mientras una conexión está activa; para actualizar las credenciales, la conexión debe detenerse y reiniciarse.

OnConnected se llama dos veces al usar jQuery Mobile

La función initializePage de jQuery Mobile obliga a volver a ejecutar los scripts de cada página, creando así una segunda conexión. Entre las soluciones para este problema se incluyen:

  • Incluya la referencia a jQuery Mobile antes de su archivo JavaScript.
  • Deshabilite la función de initializePage estableciendo $.mobile.autoInitializePage = false.
  • Espere a que la página termine de inicializarse antes de iniciar la conexión.

Los mensajes se retrasan en las aplicaciones de Silverlight con eventos enviados por el servidor

Los mensajes se retrasan al usar eventos enviados por servidor en Silverlight. Para forzar que se use long polling en su lugar, use lo siguiente al iniciar la conexión:

connection.Start(new LongPollingTransport());

Error "Permission Denied" con el protocolo Forever Frame

Se trata de un problema conocido, que se describe aquí. Este síntoma puede verse usando la última biblioteca de JQuery; la solución alternativa es cambiar a una versión anterior su aplicación, a JQuery 1.8.2.

"InvalidOperationException: no es una solicitud de socket web válida.

Este error puede producirse si se usa el protocolo WebSocket, pero el proxy de red está modificando los encabezados de solicitud. La solución consiste en configurar el proxy para permitir el WebSocket en el puerto 80.

"Excepción: no se pudo resolver el método de <nombre del método>" cuando el cliente llama al método en el servidor

Este error puede deberse al uso de tipos de datos que no se pueden detectar en una carga JSON, como Array. La solución alternativa es usar un tipo de datos reconocible por JSON, como IList. Para más información, consulte El cliente .NET no puede llamar a métodos de centro de conectividad con parámetros de matriz.

Errores de compilación y del lado del servidor

La siguiente sección contiene posibles soluciones a los errores del compilador y del runtime del lado del servidor.

La referencia a la instancia de centro de conectividad es null

Dado que se crea una instancia del centro de conectividad para cada conexión, no puede crear una instancia del centro de conectividad en su código usted mismo. Para llamar a métodos de un centro de conectividad desde fuera del propio centro de conectividad, consulte Llamada a métodos de clientes y administrar grupos desde fuera de la clase Hub para ver cómo obtener una referencia al contexto del centro de conectividad.

HTTPContext.Current.Session es null

Este comportamiento es por diseño. SignalR no admite el estado de sesión de ASP.NET, ya que habilitar el estado de sesión interrumpiría la mensajería dúplex.

No hay ningún método adecuado para invalidar

Puede ver este error si está usando código de documentación o blogs antiguos. Verifique que no está haciendo referencia a nombres de métodos que han sido cambiados o están en desuso (como OnConnectedAsync).

HostContextExtensions.WebSocketServerUrl es null

Este comportamiento es por diseño. Este miembro está en desuso y no debe usarse.

Error "A route named 'signalr.hubs' is already in the route collection"

Este error se verá si la aplicación llama a MapSignalR dos veces. Algunas aplicaciones de ejemplo llaman a MapSignalR directamente en el archivo de aplicación global; otras realizan la llamada en una clase contenedora. Asegúrese de que su aplicación no hace ambas cosas.

WebSocket no se usa

Si ha comprobado que el servidor y los clientes cumplen los requisitos de WebSocket (enumerados en el documento Plataformas admitidas), deberá habilitar WebSocket en el servidor. Puede encontrar instrucciones para hacerlo aquí.

$.connection no está definido

Este error indica que los scripts de una página no se cargan correctamente, o que el proxy del centro de conectividad no es accesible o al que se accede incorrectamente. Compruebe que las referencias de script de la página corresponden a los scripts cargados en el proyecto y que se puede tener acceso a /signalr/hubs en un explorador cuando se ejecuta el servidor.

No se encuentran uno o varios tipos necesarios para compilar una expresión dinámica.

Este error indica que falta la biblioteca Microsoft.CSharp. Agréguelo en la pestaña Ensamblados->Framework.

No se puede tener acceso al estado del autor de la llamada desde Clients.Caller en Visual Basic o en un centro de conectividad fuertemente tipado. El error "La conversión del tipo 'Task(Of Object)' al tipo 'String' no es válida"

Para acceder al estado del autor de la llamada en Visual Basic o en un concentrador fuertemente tipado, use la propiedad Clients.CallerState (introducida en SignalR 2.1) en lugar de Clients.Caller.

Problemas de Visual Studio

En esta sección se describen los problemas detectados en Visual Studio.

El nodo Documentos de scripts no aparece en el Explorador de soluciones

Algunos de nuestros tutoriales le dirigen al nodo "Documentos de scripts" del Explorador de soluciones mientras depura. Este nodo es producido por el depurador de JavaScript, y solo aparecerá mientras se depuran clientes de explorador en Internet Explorer; el nodo no aparecerá si se usan Chrome o Firefox. El depurador de JavaScript tampoco se ejecutará si se está ejecutando otro depurador de cliente, como el depurador de Silverlight.

SignalR no funciona en Visual Studio 2008 o anterior

Este comportamiento es por diseño. SignalR requiere .NET Framework 4 o posterior; esto requiere que las aplicaciones de SignalR se desarrollen en Visual Studio 2010 o posterior. El componente de servidor de SignalR requiere .NET Framework 4.5.

Problemas de IIS

Esta sección contiene problemas con Internet Information Services.

SignalR funciona en el servidor de desarrollo de Visual Studio, pero no en IIS

SignalR se admite en IIS 7.0 y 7.5, pero se debe agregar compatibilidad con direcciones URL sin extensión. Para agregar compatibilidad de IIS7 para direcciones URL sin extensión, consulte https://support.microsoft.com/kb/980368.

SignalR requiere que ASP.NET se instale en el servidor (ASP.NET no está instalado en IIS de forma predeterminada). Para instalar ASP.NET, consulte Descargas de ASP.NET.

Problemas de Microsoft Azure

Esta sección contiene incidencias con Microsoft Azure.

FileLoadException al hospedar SignalR en un rol de trabajo de Azure

Hospedar SignalR en un rol de trabajo de Azure podría dar lugar a la excepción "No se pudo cargar el archivo o ensamblado 'Microsoft.Owin, Version=2.0.0.0'". Se trata de un problema conocido con NuGet. Las redirecciones de enlace no se agregan automáticamente en los proyectos de rol de trabajo de Azure. Para corregirlo, puede agregar los redireccionamientos de enlace manualmente. Agregue las líneas siguientes al archivo app.config del proyecto rol de trabajo.

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.2.0" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.2.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

Los mensajes no se reciben a través del backplane de Azure después de alterar los nombres de los temas

Los temas usados por el backplane de Azure no están diseñados para ser configurables por el usuario.