Устранение неполадок SignalR

Патрик Флетчер

Предупреждение

Эта документация не подходит для последней версии SignalR. Взгляните на ASP.NET Core SignalR.

В этом документе описываются распространенные проблемы с устранением неполадок с SignalR.

Версии программного обеспечения, используемые в этом разделе

Предыдущие версии этого раздела

Сведения о более ранних версиях SignalR см. в разделе SignalR более ранних версий.

Вопросы и комментарии

Оставьте отзыв о том, как вам понравилось это руководство и что, по вашему мнению, мы можем улучшить в комментариях в нижней части страницы. Если у вас есть вопросы, которые не связаны напрямую с руководством, их можно опубликовать на форуме ASP.NET SignalR или StackOverflow.com.

Этот документ содержит следующие разделы.

Вызов методов между клиентом и сервером незаметно завершается сбоем.

В этом разделе описываются возможные причины сбоя вызова метода между клиентом и сервером без понятного сообщения об ошибке. В приложении SignalR сервер не имеет сведений о методах, которые реализует клиент; Когда сервер вызывает метод клиента, имя метода и данные параметров отправляются клиенту, а метод выполняется только в том случае, если он существует в указанном сервере формате. Если на клиенте нет соответствующего метода, на сервере ничего не происходит, и на сервере не возникает сообщение об ошибке.

Для более детального изучения случаев, когда методы клиента не вызываются, можно включить ведение журнала перед вызовом метода запуска на концентраторе, чтобы увидеть, какие вызовы приходят с сервера. Сведения о включении ведения журнала в приложении JavaScript см. в статье "Как включить ведение журнала на стороне клиента (версия клиента JavaScript)". Чтобы включить ведение журнала в клиентском приложении .NET, см. инструкции по включению ведения журнала на стороне клиента (версия клиента .NET).

Неправильный метод, неправильная сигнатура метода или неправильное имя хаба

Если имя или подпись вызываемого метода не совпадает с соответствующим методом на клиенте, вызов завершится ошибкой. Убедитесь, что имя метода, вызываемое сервером, соответствует имени метода на клиенте. Кроме того, SignalR создает прокси-сервер концентратора с помощью методов в стиле CamelCase, как это принято в JavaScript, поэтому метод, вызываемый SendMessage на сервере, будет вызываться как sendMessage в клиенте в прокси-сервере. Если атрибут используется HubName в коде на стороне сервера, убедитесь, что имя, используемое для создания концентратора на клиенте, совпадает с именем. Если вы не используете атрибут HubName, убедитесь, что имя концентратора в клиенте JavaScript написано в стиле camelCase, например chatHub вместо ChatHub.

Повторяющееся имя метода на клиенте

Убедитесь, что у вас нет повторяющегося метода на стороне клиента, который отличается только размерами букв. Если клиентское приложение вызывает метод sendMessage, убедитесь, что также не существует метода SendMessage .

Отсутствует средство синтаксического анализа JSON на клиенте

SignalR требует, чтобы средство синтаксического анализа JSON присутствовало для сериализации вызовов между сервером и клиентом. Если у клиента нет встроенного средства синтаксического анализа JSON (например, Internet Explorer 7), необходимо включить его в приложение. Здесь можно скачать средство синтаксического анализа JSON.

Синтаксис Mixing Hub и PersistentConnection

SignalR использует две модели связи: Hubs и PersistentConnections. Синтаксис вызова этих двух моделей обмена данными отличается в клиентском коде. Если вы добавили концентратор в код сервера, убедитесь, что весь клиентский код использует правильный синтаксис концентратора.

Клиентский код JavaScript, который создает PersistentConnection в клиенте JavaScript

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

Клиентский код JavaScript, который создает прокси Hub в JavaScript-клиенте

var myHub = $.connection.MyHub;

Код сервера C#, который сопоставляет маршрут с PersistentConnection

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

Код сервера C#, который сопоставляет маршрут с концентратором или с несколькими центрами, если у вас несколько приложений

App.MapSignalR();

Подключение запущено до добавления подписок

Если подключение Центра запущено до того, как методы, которые можно вызвать с сервера, добавляются в прокси-сервер, сообщения не будут получены. Следующий код JavaScript не будет запускать концентратор должным образом:

Некорректный клиентский код JavaScript, который не позволит получать сообщения от Hubs

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

Вместо этого добавьте подписки метода перед вызовом Start:

Клиентский код JavaScript, который правильно добавляет подписки в концентратор

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

Отсутствует имя метода на прокси-сервере концентратора

Убедитесь, что метод, определённый на сервере, запрашивается на клиенте. Несмотря на то, что сервер определяет метод, он по-прежнему должен быть добавлен в прокси-сервер клиента. Методы можно добавить в клиентский прокси следующим образом (обратите внимание, что метод добавляется в client модуля концентратора, а не напрямую в концентратор):

Клиентский код JavaScript, добавляющий методы к прокси-серверу концентратора

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

Методы хаба или узла, не объявленные как общедоступные

Чтобы быть видимыми на клиенте, реализация и методы концентратора должны быть объявлены как public.

Доступ к концентратору из другого приложения

Узлы SignalR могут быть доступны только через приложения, реализующие клиенты SignalR. SignalR не может взаимодействовать с другими библиотеками коммуникации (например, веб-службами SOAP или WCF.) Если для целевой платформы нет клиента SignalR, вы не сможете напрямую получить доступ к конечной точке сервера.

Сериализация данных вручную

SignalR автоматически будет использовать JSON для сериализации параметров метода. Это не нужно делать самостоятельно.

Метод удаленного концентратора не выполняется на клиенте в функции OnDisconnected

Это поведение является намеренным. Когда вызывается OnDisconnected, концентратор уже находится в состоянии Disconnected, которое не позволяет вызывать дополнительные методы концентратора.

Код сервера C#, который правильно выполняет код в событии OnDisconnected

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

OnDisconnect не работает в согласованное время

Это поведение является намеренным. Когда пользователь пытается перейти с страницы с активным подключением SignalR, клиент SignalR попытается уведомить сервер о том, что подключение клиента будет остановлено. Если наилучшая попытка клиента SignalR не достигнет сервера, сервер удалит подключение через заданный промежуток времени DisconnectTimeout, в то время событие OnDisconnected будет вызвано. Если попытка клиента SignalR успешно выполнена, OnDisconnected событие немедленно запустится.

Сведения о настройке параметра DisconnectTimeout см. в разделе Обработка событий времени существования подключения: DisconnectTimeout.

Достигнуто ограничение подключения

При использовании полной версии IIS в клиентской операционной системе, например Windows 7, применяется ограничение на 10 подключений. При использовании клиентской ОС используйте IIS Express вместо этого, чтобы избежать этого ограничения.

Подключение между доменами не настроено должным образом

Если подключение между доменами (подключение, для которого URL-адрес SignalR не находится в том же домене, что и сайт, на котором размещена страница) не настроено правильно, подключение может не удастся без сообщения об ошибке. Сведения о том, как включить междоменный обмен данными, см. в разделе "Как установить междомовое подключение".

Подключение с помощью NTLM (Active Directory) не работает в клиенте .NET

Подключение в клиентском приложении .NET, использующее безопасность домена, может завершиться ошибкой, если подключение настроено неправильно. Чтобы использовать SignalR в доменной среде, задайте необходимое свойство подключения следующим образом:

Клиентский код C#, реализующий учетные данные подключения

connection.Credentials = CredentialCache.DefaultCredentials;

Настройка веб-сокетов IIS для выполнения ping/pong с целью обнаружения неактивного клиента.

Серверы SignalR не знают, является ли клиент мертвым или нет, и они полагаются на уведомление из базового websocket для сбоев подключения, то есть обратного OnClose вызова. Одним из решений этой проблемы является настройка вебсокетов IIS, чтобы они выполняли ping/pong за вас. Это гарантирует, что подключение будет закрыто, если оно неожиданно прерывается. Дополнительные сведения см. в этой записи stackoverflow.

Другие проблемы с подключением

В этом разделе описываются причины и решения для определенных симптомов или сообщений об ошибках, возникающих во время подключения.

"Запуск должен вызываться перед отправкой данных"

Эта ошибка часто возникает, если код ссылается на объекты SignalR перед началом подключения. После завершения подключения необходимо добавить провод для обработчиков и таких методов, которые будут вызывать методы, определенные на сервере. Обратите внимание, что вызов Start является асинхронным, поэтому код, находящийся после вызова, может быть выполнен до его завершения. Наиболее эффективный способ добавить обработчики после полного старта подключения — это поместить их в функцию обратного вызова, переданную в качестве параметра методу start.

Клиентский код JavaScript, который правильно добавляет обработчики событий, ссылающиеся на объекты 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();
    });

Эта ошибка также будет замечена, если подключение останавливается, а объекты SignalR по-прежнему ссылаются.

Ошибка "301 перемещена окончательно" или "302 перемещено временно"

Эта ошибка может появиться, если проект содержит папку SignalR, которая будет препятствовать автоматическому созданию прокси-сервера. Чтобы избежать этой ошибки, не используйте папку, названную SignalR в приложении, или отключите автоматическую генерацию прокси. Дополнительные сведения см. в разделе "Созданный прокси и его функции для вас".

Ошибка "403 Запрещено" в клиенте .NET или Silverlight

Эта ошибка может возникать в междоменных средах, где связь между доменами не включена должным образом. Сведения о том, как включить междоменный обмен данными, см. в разделе "Как установить междомовое подключение". Сведения о создании междоменного подключения в клиенте Silverlight см. в разделе "Междоменные подключения" от клиентов Silverlight.

Ошибка "404 не найдена"

Существует несколько причин этой проблемы. Проверьте все следующее:

  • Ссылка на прокси-адрес концентратора неправильно отформатирована: Эта ошибка часто возникает, если ссылка на созданный прокси-адрес концентратора неправильно отформатирована. Убедитесь, что ссылка на главный адрес выполнена правильно. Дополнительные сведения см. в статье о том, как ссылаться на динамически созданный прокси-сервер .

  • Добавление маршрутов в приложение перед добавлением центрального маршрута: Если приложение использует другие маршруты, убедитесь, что первый добавленный маршрут является вызовом MapSignalR.

  • Использование IIS 7 или 7.5 без обновления для URL-адресов без расширения: Для использования IIS 7 или 7.5 требуется обновление для URL-адресов без расширения, чтобы сервер смог предоставить доступ к определениям концентратора /signalr/hubs. Обновление можно найти здесь.

  • Кэш IIS устарел или поврежден: Чтобы убедиться, что содержимое кэша не устарело, введите следующую команду в окне PowerShell, чтобы очистить кэш:

    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"

Это очень универсальная ошибка, которая может иметь широкий спектр причин. Сведения об ошибке должны отображаться в журнале событий сервера или можно найти с помощью отладки сервера. Более подробные сведения об ошибке могут быть получены путем включения отображения полных сведений об ошибках на сервере. Дополнительные сведения см. в разделе "Обработка ошибок в классе Hub".

Эта ошибка также часто возникает, если брандмауэр или прокси-сервер настроен неправильно, что приводит к перезаписи заголовков запросов. Решение заключается в том, чтобы убедиться, что порт 80 включен в брандмауэре или прокси-сервере.

"Непредвиденный код ответа: 500"

Эта ошибка может возникать, если версия платформы .NET, используемая в приложении, не соответствует версии, указанной в Web.Config. Решение заключается в том, чтобы убедиться, что .NET 4.5 используется как в параметрах приложения, так и в файле Web.Config.

Ошибка TypeError: <hubType> не определена

Эта ошибка возникнет, если вызов MapSignalR выполнен неправильно. Дополнительные сведения см. в статье "Регистрация ПО промежуточного слоя SignalR" и настройка параметров SignalR .

JsonSerializationException не был обработан пользовательским кодом

Убедитесь, что параметры, отправляемые в ваши методы, не содержат несериализируемые типы (например, дескрипторы файлов или подключения к базам данных). Если необходимо использовать элементы на серверном объекте, который не требуется отправлять клиенту (по соображениям безопасности или по соображениям сериализации), используйте JSONIgnore атрибут.

Ошибка протокола: неизвестный транспорт

Эта ошибка может возникать, если клиент не поддерживает транспорты, которые использует SignalR. См. раздел "Транспорты и резервные механизмы" для получения информации о том, какие браузеры можно использовать с SignalR.

"Создание прокси-сервера JavaScript Hub было отключено".

Эта ошибка возникнет, если DisableJavaScriptProxies установлено, и при этом включена ссылка на динамически созданный прокси на signalr/hubs. Дополнительные сведения о создании прокси-сервера вручную см. в разделе "Созданный прокси-сервер" и его действия.

"Идентификатор подключения находится в неправильном формате" или "Удостоверение пользователя не может измениться во время активного подключения SignalR"

Эта ошибка может возникать, если используется проверка подлинности, и клиент выходит из системы до остановки подключения. Решение заключается в том, чтобы прервать подключение SignalR перед выходом из системы клиентом.

"Неохваченная ошибка: SignalR: jQuery не найден. Убедитесь, что jQuery ссылается перед ошибкой SignalR.js файла

Для запуска клиента JavaScript SignalR требуется jQuery. Убедитесь, что ссылка на jQuery является правильной, что используемый путь является допустимым, и что ссылка на jQuery находится перед ссылкой на SignalR.

"Uncaught TypeError: не удается прочитать свойство "<свойство>" неопределенной ошибки

Эта ошибка возникает из-за отсутствия правильной ссылки на jQuery или прокси hub. Убедитесь, что ссылка на jQuery и прокси-сервер концентраторов правильна, что используемый путь является допустимым, и что ссылка на jQuery находится перед ссылкой на прокси-сервер концентраторов. Ссылка по умолчанию на прокси-сервер концентраторов должна выглядеть следующим образом:

Код HTML на стороне клиента, который правильно ссылается на прокси-сервер Центров

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

Ошибка RuntimeBinderException не была обработана пользовательским кодом

Эта ошибка может возникать при использовании неправильной перегрузки Hub.On. Если метод имеет возвращаемое значение, возвращаемый тип должен быть указан в качестве параметра универсального типа:

Метод, определенный на клиенте (без созданного прокси-сервера)

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

Идентификатор подключения несостыкован или соединение разрывается между загрузками страниц

Это поведение является намеренным. Так как объект концентратора размещается в объекте страницы, концентратор уничтожается при обновлении страницы. Приложение с несколькими страницами должно поддерживать связь между пользователями и идентификаторами подключений, чтобы они были согласованы между нагрузками страниц. Идентификаторы подключений можно хранить на сервере в объекте ConcurrentDictionary или базе данных.

Ошибка "Значение не может быть null"

В настоящее время не поддерживаются методы на стороне сервера с необязательными параметрами; Если необязательный параметр опущен, метод завершится ошибкой. Дополнительные сведения см. в разделе "Необязательные параметры".

Ошибка "Firefox не может установить подключение к серверу по <адресу>" в Firebug

Это сообщение об ошибке можно увидеть в Firebug, если согласование транспорта WebSocket завершается ошибкой, а другой транспорт используется вместо этого. Это поведение является намеренным.

Ошибка "Удаленный сертификат недействителен согласно процедуре валидации" в клиентском приложении .NET

Если для сервера требуются пользовательские сертификаты клиента, можно добавить x509certificate в подключение перед выполнением запроса. Добавьте сертификат в подключение с помощью Connection.AddClientCertificate.

Отключение после истечения времени ожидания проверки подлинности

Это поведение является намеренным. Учетные данные проверки подлинности нельзя изменить при активном подключении; Чтобы обновить учетные данные, подключение должно быть остановлено и перезапущено.

OnConnected вызывается дважды при использовании jQuery Mobile

Функция jQuery Mobile initializePage заставляет скрипты на каждой странице повторно выполняться, создавая при этом второе подключение. Ниже приведены решения для этой проблемы:

  • Добавьте ссылку на jQuery Mobile перед файлом JavaScript.
  • Отключите функцию initializePage , задав параметр $.mobile.autoInitializePage = false.
  • Дождитесь завершения инициализации страницы перед началом подключения.

Сообщения задерживаются в приложениях Silverlight, использующих события, отправляемые сервером.

Сообщения задерживаются при использовании событий, отправляемых сервером, на Silverlight. Чтобы принудительно использовать длинный опрос, используйте следующее при запуске подключения:

connection.Start(new LongPollingTransport());

Доступ запрещен с помощью протокола Forever Frame

Это известная проблема, описанная здесь. Этот симптом может быть замечен с помощью последней библиотеки JQuery; Решением является понижение уровня приложения до JQuery 1.8.2.

"InvalidOperationException: недопустимый запрос веб-сокета.

Эта ошибка может возникать, если используется протокол WebSocket, но сетевой прокси-сервер изменяет заголовки запроса. Решение заключается в настройке прокси-сервера, чтобы разрешить WebSocket через порт 80.

Исключение: <имя метода> не удалось разрешить, когда клиент вызывает метод на сервере.

Эта ошибка может возникнуть из-за использования типов данных, которые не могут быть обнаружены в полезной нагрузке JSON, таких как Массив. Обходной путь — использовать тип данных, который можно обнаружить в формате JSON, например IList. Дополнительные сведения см. в статье о том, что клиент .NET не может вызывать методы концентратора с параметрами массива.

Ошибки компиляции и сервера

В следующем разделе содержатся возможные решения для ошибок компилятора и серверной среды выполнения.

Ссылка на экземпляр узла имеет значение NULL

Так как для каждого подключения создается экземпляр концентратора, вы не можете создать экземпляр концентратора в коде самостоятельно. Чтобы вызвать методы из-за пределов самого концентратора, см. статью "Как вызвать клиентские методы" и управлять группами за пределами класса Концентратора , чтобы получить ссылку на контекст концентратора.

HTTPContext.Current.Session имеет значение NULL

Это поведение является намеренным. SignalR не поддерживает состояние сеанса ASP.NET, так как включение состояния сеанса приведет к прерыванию дуплексного обмена сообщениями.

Нет подходящего метода для переопределения

Эта ошибка может возникнуть, если вы используете код из более старой документации или блогов. Убедитесь, что вы не ссылаетесь на имена методов, которые были изменены или устарели (например OnConnectedAsync).

HostContextExtensions.WebSocketServerUrl имеет значение NULL

Это поведение является намеренным. Этот член устарел и не должен использоваться.

Ошибка "Маршрут с именем signalr.hubs" уже находится в коллекции маршрутов.

Эта ошибка будет замечена, если MapSignalR вызывается приложением дважды. Некоторые примеры приложений вызывают MapSignalR непосредственно в классе Startup, другие делают вызов в классе-обертке. Убедитесь, что ваше приложение не выполняет обе функции.

WebSocket не используется

Если вы убедились, что сервер и клиенты соответствуют требованиям WebSocket (перечисленным в документе "Поддерживаемые платформы "), необходимо включить WebSocket на сервере. Инструкции по этому использованию см. здесь.

$.connection не определен

Эта ошибка означает, что скрипты на странице не загружаются должным образом, или прокси-сервер концентратора недоступен или доступ к ней недоступен. Убедитесь, что ссылки на скрипты на странице соответствуют скриптам, загруженным в проекте, и что /signalr/hubs можно получить в браузере при запуске сервера.

Не удается найти один или несколько типов, необходимых для компиляции динамического выражения.

Эта ошибка указывает, что Microsoft.CSharp библиотека отсутствует. Добавьте его на вкладку Assemblies-Framework>.

Состояние вызывающего объекта невозможно получить из Client.Caller в Visual Basic или в строго типизированном концентраторе; "Преобразование типа "Task(Of Object)" в тип "String" недопустимо"

Чтобы получить доступ к состоянию вызывающего объекта в Visual Basic или в строго типизированном концентраторе, используйте Clients.CallerState свойство (представленное в SignalR 2.1) вместо Clients.Caller.

Проблемы с Visual Studio

В этом разделе описываются проблемы, возникающие в Visual Studio.

Узел "Документы скриптов" не отображается в обозревателе решений

Некоторые из наших руководств направляют вас на узел "Документы скриптов" в обозревателе решений при отладке. Этот узел создается отладчиком JavaScript и будет отображаться только при отладке клиентов браузера в Internet Explorer; Узел не будет отображаться, если используется Chrome или Firefox. Отладчик JavaScript также не будет запускаться, если запущен другой отладчик клиента, например отладчик Silverlight.

SignalR не работает в Visual Studio 2008 или более ранней версии

Это поведение является намеренным. Для SignalR требуется .NET Framework 4 или более поздней версии; Для этого требуется, чтобы приложения SignalR разрабатывались в Visual Studio 2010 или более поздней версии. Для компонента сервера SignalR требуется .NET Framework 4.5.

Проблемы с IIS

В этом разделе содержатся проблемы со службами Internet Information Services.

SignalR работает на сервере разработки Visual Studio, но не в службах IIS

SignalR поддерживается в IIS 7.0 и 7.5, но необходимо добавить поддержку URL-адресов без расширения. Дополнительные сведения о поддержке URL-адресов без расширения см. в статье https://support.microsoft.com/kb/980368

SignalR требует установки ASP.NET на сервере (ASP.NET по умолчанию не установлен в IIS). Сведения об установке ASP.NET см. в разделе ASP.NET Загрузки.

Проблемы с Microsoft Azure

В этом разделе содержатся проблемы с Microsoft Azure.

FileLoadException при размещении SignalR в рабочей роли Azure

Размещение SignalR в рабочей роли Azure может привести к исключению "Не удалось загрузить файл или сборку Microsoft.Owin, Version=2.0.0.0.0". Это известная проблема NuGet; перенаправления привязок не добавляются автоматически в проектах рабочих ролей Azure. Чтобы устранить эту проблему, можно вручную добавить перенаправления связываний. Добавьте следующие строки в файл app.config для вашего проекта Worker Role.

<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>

Сообщения не получаются через backplane Azure после изменения имен разделов

Темы, используемые задним планом Azure, не предназначены для настройки пользователем.