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

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

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

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

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

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

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

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

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

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

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

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

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

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

Метод с ошибкой, неправильная сигнатура метода или неправильное имя концентратора

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

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

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

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

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

Сочетание синтаксиса Hub и PersistentConnection

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

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

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

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

var myHub = $.connection.MyHub;

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

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

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

App.MapSignalR();

Подключение началось перед добавлением подписок

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

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

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 для выполнения пинга или понг за вас. Это гарантирует, что подключение закроется в случае неожиданного разрыва. Дополнительные сведения см. в этой записи 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 Framework, используемая в приложении, не соответствует версии, указанной в Web.Config. Решение заключается в том, чтобы убедиться, что .NET 4.5 используется как в параметрах приложения, так и в файле Web.Config.

Ошибка TypeError: <hubType> is undefined

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

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

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

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

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

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

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

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

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

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

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

Ошибка "Uncaught TypeError: Не удается прочитать свойство "<property>" из undefined

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Если серверу требуются пользовательские сертификаты клиента, можно добавить сертификат x509 к подключению перед выполнением запроса. Добавьте сертификат в подключение с помощью 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, таких как Array. Обходной путь — использовать тип данных, который можно обнаружить с помощью 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 отсутствие библиотеки. Добавьте его на вкладку Сборки-Платформа>.

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

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

Проблемы с Visual Studio

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

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

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

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

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

Проблемы со службами IIS

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

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". Это известная проблема с NuGet; Перенаправления привязки не добавляются автоматически в проекты рабочих ролей Azure. Чтобы устранить эту проблему, можно добавить перенаправления привязки вручную. Добавьте следующие строки в app.config файл проекта рабочей роли.

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

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

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