Solución de problemas de SignalR (SignalR 1.x)

por Patrick Fletcher

Advertencia

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

En este documento se describen los problemas comunes con SignalR.

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 hub para ver qué llamadas proceden del servidor. Para habilitar el registro en una aplicación de JavaScript, consulte Cómo habilitar el registro del lado del cliente (versión cliente de JavaScript). Para habilitar el registro en una aplicación cliente .NET, consulte Cómo habilitar el registro del lado del cliente (versión cliente .NET).

Método mal escrito, firma de método incorrecta o nombre de hub 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 hub usando métodos en camelCase, 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 hub en el cliente. Si no usa el atributo HubName, compruebe que el nombre del hub en un cliente JavaScript está en camelCase, 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 hub 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 hub, o a varios hubs si tiene varias aplicaciones

RouteTable.Routes.MapHubs();

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 hub correctamente:

Código de cliente JavaScript incorrecto que no permitirá recibir mensajes de Hubs

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 hub

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 hub

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 hub, no al hub directamente):

Código de cliente JavaScript que agrega métodos a un proxy de hub

// 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) {...}
});

Métodos de hub o hub no declarados como públicos

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

Acceso al hub 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 hub ya ha entrado en el estado Disconnected, que no permite llamar a más métodos del hub.

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();
    }
}

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 Cómo establecer 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;

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 Cómo establecer 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 hub no tiene el formato correcto: este error se suele ver si la referencia a la dirección del proxy del hub generado no tiene el formato correcto. Compruebe que la referencia a la dirección del hub se hace correctamente. Consulte Cómo hacer 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 hub: si su aplicación usa otras rutas, compruebe que la primera ruta agregada es la llamada a MapHubs.

Error "500 Internal Server Error"

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 Cómo controlar los errores en la clase Hub.

Error "TypeError: <hubType> is undefined"

Este error se producirá si la llamada a MapHubs no se realiza correctamente. Consulte Cómo registrar 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 hubs. Verifique que su referencia a jQuery y al proxy del hub 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 hubs. La referencia predeterminada al proxy de hubs 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 hub 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.

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 de hub para cada conexión, no puede crear una instancia de hub en su código usted mismo. Para llamar a métodos de un hub desde fuera del propio hub, consulte Cómo llamar a métodos de clientes y administrar grupos desde fuera de la clase Hub para ver cómo obtener una referencia al contexto del hub.

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 MapHubs dos veces. Algunas aplicaciones de ejemplo llaman a MapHubs 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.

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.

Problemas de IIS

Esta sección contiene problemas con Internet Information Services.

El sitio web se bloquea tras una llamada a MapHubs

Este problema se ha corregido en la versión más reciente de SignalR. Verifique que está usando la última versión publicada de SignalR actualizando su instalación usando NuGet.

Problemas de Azure

Esta sección contiene incidencias con Microsoft Azure.

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.