SignalR 疑難排解 (SignalR 1.x)

作者: Patrick Fletcher

警告

本檔不適用於最新版的 SignalR。 請查看ASP.NET Core SignalR

本檔說明 SignalR 的常見疑難排解問題。

本檔包含下列各節。

在用戶端與伺服器之間以無訊息方式呼叫方法會失敗

本節說明用戶端與伺服器之間方法呼叫失敗的可能原因,而不會產生有意義的錯誤訊息。 在 SignalR 應用程式中,伺服器沒有用戶端實作之方法的相關資訊;當伺服器叫用用戶端方法時,方法名稱和參數資料會傳送至用戶端,而且只有在方法存在於伺服器指定的格式時,才會執行方法。 如果在用戶端上找不到相符的方法,則不會發生任何動作,而且伺服器上不會引發任何錯誤訊息。

若要進一步調查未呼叫的用戶端方法,您可以在中樞上呼叫 start 方法之前開啟記錄,以查看來自伺服器的呼叫。 若要在 JavaScript 應用程式中啟用記錄,請參閱 如何啟用用戶端記錄 (JavaScript 用戶端版本) 。 若要在 .NET 用戶端應用程式中啟用記錄,請參閱 如何啟用用戶端記錄 (.NET 用戶端版本)

拼錯的方法、不正確的方法簽章或不正確的中樞名稱

如果所呼叫方法的名稱或簽章與用戶端上的適當方法不完全相符,呼叫將會失敗。 確認伺服器呼叫的方法名稱符合用戶端上方法的名稱。 此外,SignalR 會使用 Camel 大小寫方法建立中樞 Proxy,如同 JavaScript 中的適當方法,因此會在用戶端 Proxy 中呼叫伺服器上呼叫 SendMessagesendMessage 的方法。 如果您在伺服器端程式碼中使用 HubName 屬性,請確認所使用的名稱符合用來在用戶端上建立中樞的名稱。 如果您未使用 HubName 屬性,請確認 JavaScript 用戶端中的中樞名稱為 camel 大小寫,例如 chatHub,而不是 ChatHub。

用戶端上的重複方法名稱

請確認用戶端上沒有重複的方法,只有大小寫不同。 如果您的用戶端應用程式有一個稱為 sendMessage 的方法,請確認也有一個呼叫 SendMessage 的方法。

用戶端上遺漏 JSON 剖析器

SignalR 需要有 JSON 剖析器,才能序列化伺服器與用戶端之間的呼叫。 如果您的用戶端沒有內建 JSON 剖析器 (,例如 Internet Explorer 7) ,您必須在應用程式中包含一個。 您可以 在這裡下載 JSON 剖析器。

混合中樞和 PersistentConnection 語法

SignalR 使用兩種通訊模型:中樞和 PersistentConnections。 在用戶端程式代碼中呼叫這兩個通訊模型的語法不同。 如果您已在伺服器程式碼中新增中樞,請確認您的所有用戶端程式代碼都使用適當的中樞語法。

在 JavaScript 用戶端中建立 PersistentConnection 的 JavaScript 用戶端程式代碼

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

在 JAVAscript 用戶端中建立中樞 Proxy 的 JavaScript 用戶端程式代碼

var myHub = $.connection.MyHub;

將路由對應至 PersistentConnection 的 C# 伺服器程式碼

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

將路由對應至中樞的 C# 伺服器程式碼,或如果您有多個應用程式,則對應至多個中樞

RouteTable.Routes.MapHubs();

在新增訂用帳戶之前啟動連線

如果在將可從伺服器呼叫的方法新增至 Proxy 之前啟動中樞的連線,將不會收到訊息。 下列 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 () {
        ...
    });

中樞 Proxy 上遺漏方法名稱

確認伺服器上定義的 方法已在用戶端上訂閱。 即使伺服器定義 方法,它仍必須新增至用戶端 Proxy。 方法可以透過下列方式新增至用戶端 Proxy (請注意,方法會新增至 client 中樞的成員,而不是直接) 中樞:

將方法新增至中樞 Proxy 的 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 Web 服務。) 如果目標平臺沒有 SignalR 用戶端可用,就無法直接存取伺服器的端點。

手動序列化資料

SignalR 會自動使用 JSON 來序列化您的方法參數-不需要自行執行。

OnDisconnected 函式中未在用戶端上執行的遠端中樞方法

這是設計的行為。 呼叫 時 OnDisconnected ,中樞已進入 Disconnected 狀態,這不允許呼叫進一步的中樞方法。

在 OnDisconnected 事件中正確執行程式碼的 C# 伺服器程式碼

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

已達到連線限制

在 Windows 7 等用戶端作業系統上使用完整版的 IIS 時,會加總 10 個連線限制。 使用用戶端 OS 時,請改用 IIS Express 以避免此限制。

跨網域連線未正確設定

如果跨網域連線 (SignalR URL 不在與主控頁面相同的網域中,) 未正確設定,連線可能會失敗,而不會顯示錯誤訊息。 如需如何啟用跨網域通訊的資訊,請參閱 如何建立跨網域連線

在 .NET 用戶端中使用 NTLM (Active Directory) 連線

如果連線未正確設定,使用網域安全性的 .NET 用戶端應用程式中的連線可能會失敗。 若要在網域環境中使用 SignalR,請設定必要的連線屬性,如下所示:

實作連線認證的 C# 用戶端程式代碼

connection.Credentials = CredentialCache.DefaultCredentials;

其他連線問題

本節說明連線期間發生之特定徵兆或錯誤訊息的原因和解決方案。

「必須先呼叫開始,才能傳送資料」錯誤

如果在啟動連接之前,程式碼參考 SignalR 物件,通常會看到此錯誤。 必須在連接完成之後新增處理常式的連線,以及呼叫伺服器上所定義之方法的連線。 請注意,對 的呼叫 Start 是非同步,因此呼叫之後的程式碼可能會在完成之前執行。 完全啟動連接之後新增處理常式的最佳方式,就是將它們放入回呼函式中,以參數的形式傳遞至 start 方法:

可正確新增參考 SignalR 物件的事件處理常式的 JavaScript 用戶端程式代碼

$.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 的資料夾,可能會看到此錯誤,這會干擾自動建立的 Proxy。 若要避免此錯誤,請勿在應用程式中使用名為 SignalR 的資料夾,或關閉自動產生 Proxy。 如需詳細資訊,請參閱 產生的 Proxy 及其用途

.NET 或 Silverlight 用戶端中的「403 禁止」錯誤

此錯誤可能會在未正確啟用跨網域通訊的跨網域環境中發生。 如需如何啟用跨網域通訊的資訊,請參閱 如何建立跨網域連線。 若要在 Silverlight 用戶端中建立跨網域連線,請參閱 Silverlight 用戶端的跨網域連線

「404 找不到」 錯誤

此問題有幾個原因。 確認下列所有專案:

  • 中樞 Proxy 位址參考的格式不正確: 如果產生的中樞 Proxy 位址參考格式不正確,通常會看到此錯誤。 確認已正確參考中樞位址。 如需詳細資訊 ,請參閱如何參考動態產生的 Proxy
  • 在新增中樞路由之前,將路由新增至應用程式: 如果您的應用程式使用其他路由,請確認新增的第一個路由是 的 MapHubs 呼叫。

「500 內部伺服器錯誤」

這是非常泛型的錯誤,可能會有各種不同的原因。 錯誤的詳細資料應該會出現在伺服器的事件記錄檔中,或可透過偵錯伺服器找到。 在伺服器上開啟詳細錯誤,可能會取得更詳細的錯誤資訊。 如需詳細資訊,請參閱 如何在 Hub 類別中處理錯誤

「TypeError: < hubType > 未定義」 錯誤

如果未正確呼叫 , MapHubs 就會產生此錯誤。 如需詳細資訊 ,請參閱如何註冊 SignalR 路由和設定 SignalR 選項

使用者程式碼未處理 JsonSerializationException

確認您傳送至方法的參數不包含不可序列化的類型, (例如檔案控制碼或資料庫連線) 。 如果您需要在伺服器端物件上使用您不想傳送給用戶端的成員, (基於安全性或序列化) 的原因,請使用 JSONIgnore 屬性。

「通訊協定錯誤:未知傳輸」錯誤

如果用戶端不支援 SignalR 使用的傳輸,就可能發生此錯誤。 如需哪些瀏覽器可以搭配 SignalR 使用的資訊,請參閱 傳輸和後援

「JavaScript Hub Proxy 產生已停用」。

如果在 DisableJavaScriptProxies 設定時也包含動態產生 Proxy signalr/hubs 的參考,則會發生此錯誤。 如需手動建立 Proxy 的詳細資訊,請參閱 產生的 Proxy 及其用途

「連線識別碼的格式不正確」或「使用者身分識別無法在作用中的 SignalR 連線期間變更」錯誤

如果使用驗證,而且用戶端會在連線停止之前登出,可能會看到此錯誤。 解決方案是在登出用戶端之前停止 SignalR 連線。

「未攔截的錯誤: SignalR: jQuery 找不到。 請確定在SignalR.js檔案之前參考 jQuery」 錯誤

SignalR JavaScript 用戶端需要 jQuery 才能執行。 確認 jQuery 的參考正確、使用的路徑有效,而且 jQuery 的參考是在 SignalR 的參考之前。

「未攔截的 TypeError:無法讀取未定義的屬性 ' < property > '」錯誤

此錯誤會導致未正確參考 jQuery 或中樞 Proxy。 確認對 jQuery 和中樞 Proxy 的參考是否正確、使用的路徑有效,而且 jQuery 的參考是在中樞 Proxy 的參考之前。 中樞 Proxy 的預設參考看起來應該如下所示:

正確參考中樞 Proxy 的 HTML 用戶端程式代碼

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

「RuntimeBinderException 未由使用者程式碼處理」錯誤

使用 的多載 Hub.On 不正確時,可能會發生此錯誤。 如果方法有傳回值,則必須將傳回型別指定為泛型型別參數:

在用戶端上定義的方法 (,而不產生 Proxy)

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

連線識別碼不一致,或頁面載入之間的連接中斷

這是設計的行為。 由於中樞物件裝載于頁面物件中,因此在重新整理頁面時會終結中樞。 多頁應用程式必須維護使用者與連線識別碼之間的關聯,以便在頁面載入之間保持一致。 連線識別碼可以儲存在物件或資料庫中的伺服器上 ConcurrentDictionary

「值不可為 Null」錯誤

目前不支援具有選擇性參數的伺服器端方法;如果省略選擇性參數,方法將會失敗。 如需詳細資訊,請參閱選擇性參數 (機器翻譯)

Firebug 中的「Firefox 無法建立伺服器位址 <> 連線」錯誤

如果 WebSocket 傳輸的交涉失敗,而是改用另一個傳輸,就可以在 Firebug 中看到此錯誤訊息。 這是設計的行為。

.NET 用戶端應用程式中的「遠端憑證無效」錯誤

如果您的伺服器需要自訂用戶端憑證,您可以在提出要求之前,將 x509certificate 新增至連線。 使用 Connection.AddClientCertificate 將憑證新增至連線。

驗證逾時後連線中斷

這是設計的行為。 連線處於作用中狀態時,無法修改驗證認證;若要重新整理認證,必須停止並重新啟動連線。

使用 jQuery Mobile 時,OnConnected 會呼叫兩次

jQuery Mobile 的函 initializePage 式會強制重新執行每個頁面中的腳本,進而建立第二個連線。 此問題的解決方案包括:

  • 在 JavaScript 檔案之前包含 jQuery Mobile 的參考。
  • 藉由設定 $.mobile.autoInitializePage = false 來停用函 initializePage 式。
  • 等候頁面完成初始化,再啟動連線。

使用伺服器傳送的事件,Silverlight 應用程式中的訊息會延遲

在 Silverlight 上使用伺服器傳送的事件時,訊息會延遲。 若要強制改用長時間輪詢,請在啟動連線時使用下列專案:

connection.Start(new LongPollingTransport());

使用 Forever Frame 通訊協定的「許可權遭拒」

這是已知的問題, 此處所述。 使用最新的 JQuery 程式庫可能會看到此徵兆;因應措施是將您的應用程式降級為 JQuery 1.8.2。

編譯和伺服器端錯誤

下一節包含編譯器和伺服器端執行時間錯誤的可能解決方案。

中樞實例的參考為 Null

由於會為每個連線建立中樞實例,因此您無法自行在程式碼中建立中樞的實例。 若要從中樞本身外部呼叫中樞上的方法,請參閱 如何從 Hub 類別外部呼叫用戶端方法和管理群組 ,以瞭解如何取得中樞內容的參考。

HTTPCoNtext.Current.Session 為 null

這是設計的行為。 SignalR 不支援 ASP.NET 會話狀態,因為啟用會話狀態會中斷雙工傳訊。

沒有適當的覆寫方法

如果您使用舊版檔或部落格中的程式碼,可能會看到此錯誤。 確認您未參考已變更或已被 (取代的方法名稱,例如 OnConnectedAsync) 。

HostCoNtextExtensions.WebSocketServerUrl 為 Null

這是設計的行為。 此成員已被取代,不應使用。

「名稱為 'signalr.hubs' 的路由已在路由集合中」錯誤

如果 MapHubs 應用程式呼叫兩次,就會看到此錯誤。 某些範例應用程式會直接在全域應用程式檔中呼叫 MapHubs ;其他則呼叫包裝函式類別。 請確定您的應用程式不會同時執行兩者。

Visual Studio 問題

本節說明 Visual Studio 中遇到的問題。

指令檔節點不會出現在Solution Explorer

我們的部分教學課程會在偵錯時,引導您前往Solution Explorer中的「指令檔」節點。 此節點是由 JavaScript 偵錯工具所產生,而且只會在 Internet Explorer 中偵錯瀏覽器用戶端時出現;如果使用 Chrome 或 Firefox,則不會顯示節點。 如果另一個用戶端偵錯工具正在執行,例如 Silverlight 偵錯工具,JavaScript 偵錯工具也不會執行。

SignalR 不適用於 Visual Studio 2008 或更早版本

這是設計的行為。 SignalR 需要.NET Framework 4 或更新版本;這需要在 Visual Studio 2010 或更新版本中開發 SignalR 應用程式。

IIS 問題

本節包含 Internet Information Services 的問題。

MapHubs 呼叫後的網站損毀

此問題已在最新版本的 SignalR 中修正。 使用 NuGet 更新安裝,以確認您使用的是最新發行的 SignalR 版本。

Azure 問題

本節包含 Microsoft Azure 的問題。

更改主題名稱之後,不會透過 Azure 上架接收訊息

Azure 上架所使用的主題並非使用者可設定的。