事件
SignalR 疑難排解
作者: Patrick Fletcher
警告
本檔不適用於最新版的 SignalR。 請查看ASP.NET Core SignalR。
本檔說明 SignalR 的常見疑難排解問題。
本主題中使用的軟體版本
- Visual Studio 2013
- .NET 4.5
- SignalR 第 2 版
本主題的舊版
如需舊版 SignalR 的相關資訊,請參閱 SignalR 舊版。
問題和批註
請留下您喜歡本教學課程的意見反應,以及我們可以在頁面底部的批註中改善的內容。 如果您有與教學課程不直接相關的問題,您可以將問題張貼到 ASP.NET SignalR 論壇 或 StackOverflow.com。
本檔包含下列各節。
- 在用戶端與伺服器之間以無訊息方式呼叫方法會失敗
- 將 IIS Websocket 設定為 ping/pong 以偵測不正確用戶端
- 其他連線問題
- 編譯和伺服器端錯誤
- Visual Studio 問題
- Internet Information Services 問題
- Microsoft Azure 問題
本節說明用戶端與伺服器之間方法呼叫失敗的可能原因,而不會產生有意義的錯誤訊息。 在 SignalR 應用程式中,伺服器沒有用戶端實作之方法的相關資訊;當伺服器叫用用戶端方法時,方法名稱和參數資料會傳送至用戶端,而且只有在方法存在於伺服器指定的格式時,才會執行方法。 如果在用戶端上找不到相符的方法,則不會發生任何動作,而且伺服器上不會引發任何錯誤訊息。
若要進一步調查未呼叫的用戶端方法,您可以在中樞上呼叫 start 方法之前開啟記錄功能,以查看來自伺服器的呼叫。 若要在 JavaScript 應用程式中啟用記錄,請參閱 如何啟用用戶端記錄 (JavaScript 用戶端版本) 。 若要在 .NET 用戶端應用程式中啟用記錄,請參閱 如何啟用用戶端記錄 (.NET 用戶端版本) 。
如果所呼叫方法的名稱或簽章與用戶端上的適當方法不完全相符,呼叫將會失敗。 確認伺服器呼叫的方法名稱符合用戶端上方法的名稱。 此外,SignalR 會使用 Camel 大小寫方法建立中樞 Proxy,如同 JavaScript 中的適當方法,因此會在用戶端 Proxy 中呼叫伺服器上呼叫 SendMessage
sendMessage
的方法。 如果您在伺服器端程式碼中使用 HubName
屬性,請確認所使用的名稱符合用來在用戶端上建立中樞的名稱。 如果您未使用 HubName
屬性,請確認 JavaScript 用戶端中的中樞名稱為 camel 大小寫,例如 chatHub,而不是 ChatHub。
請確認用戶端上沒有重複的方法,只有大小寫不同。 如果您的用戶端應用程式有一個稱為 sendMessage
的方法,請確認也有一個呼叫 SendMessage
的方法。
SignalR 需要有 JSON 剖析器,才能序列化伺服器與用戶端之間的呼叫。 如果您的用戶端沒有內建 JSON 剖析器 (,例如 Internet Explorer 7) ,您必須在應用程式中包含一個。 您可以 在這裡下載 JSON 剖析器。
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# 伺服器程式碼,或如果您有多個應用程式,則對應至多個中樞
App.MapSignalR();
如果在將可從伺服器呼叫的方法新增至 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 (請注意,方法會新增至 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
,中樞已進入 Disconnected
狀態,這不允許呼叫進一步的中樞方法。
在 OnDisconnected 事件中正確執行程式碼的 C# 伺服器程式碼
public class MyHub : Hub
{
public override Task OnDisconnected()
{
// Do what you want here
return base.OnDisconnected();
}
}
這是設計的行為。 當使用者嘗試從具有使用中 SignalR 連線的頁面流覽時,SignalR 用戶端會盡最大努力嘗試通知伺服器用戶端連線將會停止。 如果 SignalR 用戶端嘗試無法連線到伺服器,伺服器會在稍後可設定 DisconnectTimeout
之後處置連線,此時 OnDisconnected
會引發事件。 如果 SignalR 用戶端的嘗試成功,事件 OnDisconnected
將會立即引發。
如需設定 DisconnectTimeout
的相關資訊,請參閱 處理連線存留期事件:DisconnectTimeout。
在 Windows 7 等用戶端作業系統上使用完整版的 IIS 時,會加總 10 個連線限制。 使用用戶端 OS 時,請改用 IIS Express 以避免此限制。
如果跨網域連線 (SignalR URL 不在與主控頁面相同的網域中,) 未正確設定,連線可能會失敗,而不會顯示錯誤訊息。 如需如何啟用跨網域通訊的資訊,請參閱 如何建立跨網域連線。
如果連線未正確設定,使用網域安全性的 .NET 用戶端應用程式中的連線可能會失敗。 若要在網域環境中使用 SignalR,請設定必要的連線屬性,如下所示:
實作連線認證的 C# 用戶端程式代碼
connection.Credentials = CredentialCache.DefaultCredentials;
SignalR 伺服器不知道用戶端是否無效,而且依賴來自基礎 Websocket 的通知進行連線失敗,也就是 OnClose
回呼。 此問題的其中一個解決方案是設定 IIS Websocket 為您執行 ping/pong。 這可確保您的連線會在意外中斷時關閉。 如需詳細資訊,請參閱 此 stackoverflow 文章。
本節說明連線期間發生之特定徵兆或錯誤訊息的原因和解決方案。
如果程式碼在啟動連接之前參考 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 物件仍在參考時停止連線,也會看到此錯誤。
如果專案包含名為 SignalR 的資料夾,就會干擾自動建立的 Proxy,可能會看到此錯誤。 若要避免此錯誤,請勿在應用程式中使用名為 SignalR
的資料夾,或關閉自動產生 Proxy。 如需詳細資訊,請參閱 產生的 Proxy 及其用途 。
此錯誤可能會在未正確啟用跨網域通訊的跨網域環境中發生。 如需如何啟用跨網域通訊的資訊,請參閱 如何建立跨網域連線。 若要在 Silverlight 用戶端中建立跨網域連線,請參閱 Silverlight 用戶端的跨網域連線。
此問題有幾個原因。 確認下列所有專案:
中樞 Proxy 位址參考的格式不正確: 如果產生的中樞 Proxy 位址的參考格式不正確,通常會看到此錯誤。 確認已正確建立中樞位址的參考。 如需詳細資訊 ,請參閱如何參考動態產生的 Proxy 。
在新增中樞路由之前,先將路由新增至應用程式: 如果您的應用程式使用其他路由,請確認新增的第一個路由是 呼叫
MapSignalR
。針對無副檔名 URL 使用 IIS 7 或 7.5: 使用 IIS 7 或 7.5 需要無延伸模組 URL 的更新,讓伺服器能夠存取位於
/signalr/hubs
的中樞定義。 您可以 在這裡找到更新。IIS 快取過期或損毀: 若要確認快取內容未過期,請在 PowerShell 視窗中輸入下列命令以清除快取:
PowerShellnet stop w3svc Remove-Item -Path "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\*" -Force -Recurse net start w3svc
這是非常泛型的錯誤,可能會有各種不同的原因。 錯誤的詳細資料應該會出現在伺服器的事件記錄檔中,或可透過偵錯伺服器找到。 在伺服器上開啟詳細錯誤,可能會取得更詳細的錯誤資訊。 如需詳細資訊,請參閱 如何在 Hub 類別中處理錯誤。
如果防火牆或 Proxy 未正確設定,則通常也會看到此錯誤,導致要求標頭重寫。 解決方案是在防火牆或 Proxy 上確定已啟用埠 80。
如果應用程式中所使用的 .NET Framework 版本與 Web.Config 中指定的版本不符,就可能發生此錯誤。解決方案是確認應用程式設定和Web.Config檔案都使用 .NET 4.5。
如果未正確呼叫 , MapSignalR
就會產生此錯誤。 如需詳細資訊 ,請參閱如何註冊 SignalR 中介軟體和設定 SignalR 選項 。
確認您傳送至方法的參數不包含不可序列化的類型, (例如檔案控制碼或資料庫連線) 。 如果您需要在伺服器端物件上使用您不想傳送給用戶端的成員, (基於安全性或序列化) 的原因,請使用 JSONIgnore
屬性。
如果用戶端不支援 SignalR 使用的傳輸,就可能發生此錯誤。 如需哪些瀏覽器可以搭配 SignalR 使用的資訊,請參閱 傳輸和後援 。
如果在 DisableJavaScriptProxies
設定時也包含動態產生 Proxy signalr/hubs
的參考,則會發生此錯誤。 如需手動建立 Proxy 的詳細資訊,請參閱 產生的 Proxy 及其用途。
如果使用驗證,而且用戶端會在連線停止之前登出,可能會看到此錯誤。 解決方案是在登出用戶端之前停止 SignalR 連線。
SignalR JavaScript 用戶端需要 jQuery 才能執行。 確認 jQuery 的參考正確、使用的路徑有效,而且 jQuery 的參考是在 SignalR 的參考之前。
此錯誤會導致未正確參考 jQuery 或中樞 Proxy。 確認對 jQuery 和中樞 Proxy 的參考是否正確、使用的路徑有效,而且 jQuery 的參考是在中樞 Proxy 的參考之前。 中樞 Proxy 的預設參考看起來應該如下所示:
正確參考中樞 Proxy 的 HTML 用戶端程式代碼
<script src="/signalr/hubs"></script>
使用 的多載 Hub.On
不正確時,可能會發生此錯誤。 如果方法有傳回值,則必須將傳回型別指定為泛型型別參數:
在用戶端上定義的方法 (,而不產生 Proxy)
MyHub.On<ReturnType>("MethodName", LocalMethod);
這是設計的行為。 由於中樞物件裝載于頁面物件中,因此在重新整理頁面時會終結中樞。 多頁應用程式必須維護使用者與連線識別碼之間的關聯,以便在頁面載入之間保持一致。 連線識別碼可以儲存在物件或資料庫中的伺服器上 ConcurrentDictionary
。
目前不支援具有選擇性參數的伺服器端方法;如果省略選擇性參數,方法將會失敗。 如需詳細資訊,請參閱選擇性參數 (機器翻譯)。
如果 WebSocket 傳輸的交涉失敗,而是改用另一個傳輸,就可以在 Firebug 中看到此錯誤訊息。 這是設計的行為。
如果您的伺服器需要自訂用戶端憑證,您可以在提出要求之前,將 x509certificate 新增至連線。 使用 Connection.AddClientCertificate
將憑證新增至連線。
這是設計的行為。 連線處於作用中狀態時,無法修改驗證認證;若要重新整理認證,必須停止並重新啟動連線。
jQuery Mobile 的函 initializePage
式會強制重新執行每個頁面中的腳本,進而建立第二個連線。 此問題的解決方案包括:
- 在 JavaScript 檔案之前包含 jQuery Mobile 的參考。
- 藉由設定
$.mobile.autoInitializePage = false
來停用函initializePage
式。 - 等候頁面完成初始化,再啟動連線。
在 Silverlight 上使用伺服器傳送的事件時,訊息會延遲。 若要強制改用長時間輪詢,請在啟動連線時使用下列專案:
connection.Start(new LongPollingTransport());
這是已知的問題, 此處所述。 使用最新的 JQuery 程式庫可能會看到此徵兆;因應措施是將您的應用程式降級為 JQuery 1.8.2。
如果使用 WebSocket 通訊協定,但網路 Proxy 正在修改要求標頭,就可能發生此錯誤。 解決方案是設定 Proxy 以允許埠 80 上的 WebSocket。
此錯誤可能是使用無法在 JSON 承載中探索到的資料類型,例如 Array。 因應措施是使用 JSON 可探索的資料類型,例如 IList。 如需詳細資訊,請參閱 .NET 用戶端無法使用陣列參數呼叫中樞方法。
下一節包含編譯器和伺服器端執行時間錯誤的可能解決方案。
由於會為每個連線建立中樞實例,因此您無法自行在程式碼中建立中樞的實例。 若要從中樞本身外部呼叫中樞上的方法,請參閱 如何呼叫用戶端方法,以及從 Hub 類別外部管理群組 ,以瞭解如何取得中樞內容的參考。
這是設計的行為。 SignalR 不支援 ASP.NET 會話狀態,因為啟用會話狀態會中斷雙工傳訊。
如果您使用舊版檔或部落格中的程式碼,可能會看到此錯誤。 請確認您未參考已變更或已被取代的方法名稱 (,例如 OnConnectedAsync
) 。
這是設計的行為。 此成員已被取代,不應使用。
如果 MapSignalR
應用程式呼叫兩次,就會看到此錯誤。 有些範例應用程式會直接在 Startup 類別中呼叫 MapSignalR
;其他應用程式則會在包裝函式類別中呼叫 。 請確定您的應用程式不會同時執行兩者。
如果您已確認您的伺服器和用戶端符合支援 的平臺 檔中所列的 WebSocket (需求) ,則必須在伺服器上啟用 WebSocket。 您可以在這裡找到執行這項操作的指示。
此錯誤表示頁面上的腳本未正確載入,或中樞 Proxy 無法連線或存取不正確。 確認頁面上的腳本參考對應至您專案中載入的腳本,而且當伺服器執行時,可以在瀏覽器中存取 /signalr/hubs。
此錯誤表示 Microsoft.CSharp
程式庫遺失。 在 [ 元件架構 > ] 索引標籤中新增它。
若要存取 Visual Basic 或強型別中樞中的呼叫端狀態,請使用 Clients.CallerState
SignalR 2.1 中引進的屬性 () ,而不是 Clients.Caller
。
本節說明 Visual Studio 中遇到的問題。
我們的部分教學課程會在偵錯時,引導您前往Solution Explorer中的「指令檔」節點。 這個節點是由 JavaScript 偵錯工具所產生,而且只會在 Internet Explorer 中偵錯瀏覽器用戶端時出現;如果使用 Chrome 或 Firefox,則不會顯示節點。 如果另一個用戶端偵錯工具正在執行,例如 Silverlight 偵錯工具,JavaScript 偵錯工具也不會執行。
這是設計的行為。 SignalR 需要.NET Framework 4 或更新版本;這需要在 Visual Studio 2010 或更新版本中開發 SignalR 應用程式。 SignalR 的伺服器元件需要 .NET Framework 4.5。
本節包含 Internet Information Services 的問題。
IIS 7.0 和 7.5 支援 SignalR,但必須新增無擴充 URL 的支援。 若要新增對無延伸模組 URL 的支援,請參閱 https://support.microsoft.com/kb/980368
SignalR 需要 ASP.NET 安裝在伺服器上, (ASP.NET 預設不會安裝在 IIS 上) 。 若要安裝 ASP.NET,請參閱 下載 ASP.NET。
本節包含 Microsoft Azure 的問題。
在 Azure 背景工作角色中裝載 SignalR 可能會導致例外狀況「無法載入檔案或元件 '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 背板所使用的主題會在內部維護;它們不是使用者可設定的。
其他資源
訓練
模組
在 Web 應用程式中使用 Azure Functions 與 SignalR Service 啟用即時更新 - Training
將 JavaScript Web 應用程式更新機制從輪詢變更為使用 SignalR Service、Azure Cosmos DB 和 Azure Functions 的即時推送型架構。 使用 Vue.js 和 JavaScript,透過 Visual Studio Code 使用 SignalR。
文件
-
ASP.NET SignalR 中樞 API 指南 - JavaScript 用戶端
本檔提供在 JavaScript 用戶端中使用 SignalR 第 2 版中樞 API 的簡介,例如瀏覽器和 Windows 市集 (WinJS) 應用程式...
-
ASP.NET SignalR 中樞 API 指南 - 伺服器 (C#)
本檔提供程式設計適用于 SignalR 第 2 版之 ASP.NET SignalR 中樞 API 伺服器端的簡介,並示範程式碼範例...
-
本文說明如何使用中樞 API 公開的事件。