本主題列出客戶在開發 WCF 用戶端和服務時所遇到許多已知問題。 如果您遇到的問題不在此清單中,我們建議您為服務配置追蹤功能。 這會產生追蹤檔案,您可以使用追蹤檔案查看器來檢視,並取得服務內可能發生之例外狀況的詳細資訊。 如需設定追蹤的詳細資訊,請參閱: 設定追蹤。 如需追蹤檔案檢視器的詳細資訊,請參閱: 服務追蹤查看器工具 (SvcTraceViewer.exe) 。
安裝 Windows 7 和 IIS 之後,當我嘗試流覽至 WCF 服務時,我收到下列錯誤訊息:HTTP 錯誤 404.3 – 找不到
HTTP 錯誤 404.3 – 找不到您請求的頁面,因為擴充套件配置錯誤。 如果頁面是腳本,請新增處理程式。 如果這個檔案應該下載,請新增 MIME 對應表。 模組名稱為 StaticFileModule 的詳細錯誤資訊。
如果我的用戶端在第一個要求之後閑置一段時間,我有時會在第二個要求上收到 MessageSecurityException。 發生了什麼事情?
當我拋出一個類型為例外狀況的FaultException<例外> 時,我在用戶端總是會收到一般的FaultException類型,而不是具體的泛型類型。 發生了什麼事情?
我在使用 X.509 憑證搭配我的服務時,遇到了 System.Security.Cryptography.CryptographicException。 發生了什麼事情?
我正在使用一個追蹤工具時,收到了「找不到端點異常」(EndpointNotFoundException)。 發生了什麼事情?
安裝 Windows 7 和 IIS 之後,當我嘗試流覽至 WCF 服務時,我收到下列錯誤訊息:HTTP 錯誤 404.3 – 找不到
完整的錯誤訊息是:
HTTP 錯誤 404.3 – 找不到您請求的頁面,因為擴充套件配置錯誤。 如果頁面是腳本,請新增處理程式。 如果這個檔案應該下載,請新增 MIME 對應表。 模組名稱為 StaticFileModule 的詳細錯誤資訊。
當 [控制面板] 中未明確設定 「Windows Communication Foundation HTTP 啟用」時,就會發生此錯誤訊息。 若要進行此設定,請到[控制面板],然後點擊視窗左下角的[程式]。 按兩下 [開啟或關閉 Windows 功能]。 展開 [Microsoft .NET Framework 3.5.1],然後選取 [Windows Communication Foundation HTTP 啟用]。
如果我的用戶端在第一個要求之後閑置一段時間,我有時會在第二個要求上收到 MessageSecurityException。 發生了什麼事情?
第二個請求可能因為兩個主要原因而失敗:(1) 會話已逾時;或(2)承載服務的網頁伺服器已重新啟動。 在第一個案例中,會話有效,直到服務逾時為止。當服務在服務系結中指定的期間內未收到來自用戶端的要求時,ReceiveTimeout服務就會終止安全性會話。 後續的用戶端訊息會導致 MessageSecurityException。 用戶端必須與服務重新建立安全會話,才能傳送未來的訊息或使用狀態式安全性上下文令牌。 具狀態安全性內容令牌也允許安全會話在 Web 伺服器回收時倖存下來。 如需在安全會話中使用具狀態安全內容令牌的詳細資訊,請參閱 如何:建立安全會話的安全性內容令牌。 或者,您可以停用安全會話。 當您使用 <wsHttpBinding> 系結時,您可以將 屬性設定 establishSecurityContext
為 false
來停用安全會話。 若要停用其他系結的安全會話,您必須建立自定義系結。 如需建立自定義系結的詳細資訊,請參閱 如何:使用 SecurityBindingElement 建立自定義系結。 在套用上述任何選項之前,您必須瞭解應用程式的安全性需求。
大約 10 個用戶端與其互動之後,我的服務就會開始拒絕新的用戶端。 發生了什麼事情?
根據預設,服務只能有10個並行會話。 因此,如果服務綁定使用會話,服務會接受新的用戶端連線,直到達到指定的連線數量為止,之後才會拒絕新的用戶端連線,直到目前的其中一個會話結束為止。 您可以透過多種方式支援更多用戶端。 如果您的服務不需要會話,請勿使用會話系結。 (如需詳細資訊,請參閱 使用會話。)另一個選項是將 屬性的值 MaxConcurrentSessions 變更為適合您情況的數位,以增加會話限制。
我可以從 WCF 應用程式組態檔以外的某個位置載入我的服務組態嗎?
是的,不過,您必須建立自定義的ServiceHost類別以覆寫ApplyConfiguration方法。 在該方法內,您可以先呼叫基底來載入組態(如果您想要載入標準組態資訊),但也可以完全取代組態載入系統。 如果您想要從不同於應用程式組態檔的組態檔載入組態,您必須自行剖析組態檔並載入組態。
下列程式代碼範例示範如何覆寫 ApplyConfiguration 方法並直接設定端點。
public class MyServiceHost : ServiceHost
{
public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
Console.WriteLine("MyServiceHost Constructor");
}
protected override void ApplyConfiguration()
{
string straddress = GetAddress();
Uri address = new Uri(straddress);
Binding binding = GetBinding();
base.AddServiceEndpoint(typeof(IData), binding, address);
}
string GetAddress()
{
return "http://MyMachine:7777/MyEndpointAddress/";
}
Binding GetBinding()
{
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.None;
return binding;
}
}
我的服務和用戶端運作很好,但是當用戶端在另一部計算機上時,我無法讓它們運作? 發生了什麼事情?
視例外狀況而定,可能會有數個問題:
您可能需要將用戶端端點位址變更為主機名,而不是 「localhost」。。
您可能需要開啟應用程式的端口。 如需詳細資訊,請參閱 SDK 範例中的 防火牆指示 。
如需其他可能的問題,請參閱執行 Windows Communication Foundation 範例主題。
如果您的用戶端使用 Windows 認證,但例外狀況為 SecurityNegotiationException,請設定 Kerberos,如下所示。
將身份憑證新增至用戶端 App.config 檔案中的端點元素:
<endpoint address="http://MyServer:8000/MyService/" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceExample" contract="IServiceExample" behaviorConfiguration="ClientCredBehavior" name="WSHttpBinding_IServiceExample"> <identity> <userPrincipalName value="name@corp.contoso.com"/> </identity> </endpoint>
在 [系統] 或 [網路服務] 帳戶下執行自行託管服務。 您可以執行此指令,在 [系統帳戶] 底下建立命令視窗:
at 12:36 /interactive "cmd.exe"
根據預設,在 Internet Information Services (IIS) 下裝載服務,其會使用服務主體名稱 (SPN) 帳戶。
使用 SetSPN 向網域註冊新的 SPN。 您必須是網域管理員,才能這麼做。
如需 Kerberos 通訊協定的詳細資訊,請參閱 WCF 中使用的安全性概念 和:
當我拋出一個類型為例外狀況的FaultException<例外> 時,我在用戶端總是會收到一般的FaultException類型,而不是具體的泛型類型。 發生了什麼事情?
強烈建議您建立自己的自訂錯誤資料類型,並將其定義為錯誤約定中的詳細資料類型。 原因是因為使用系統提供的例外類型:
建立類型相依性,移除服務導向應用程式的最大優點之一。
無法相依於以標準方式串行化的例外狀況。 有些 —例如 SecurityException— 可能完全無法串行化。
向客戶端公開內部實作詳細數據。 如需詳細資訊,請參閱 指定及處理合約和服務中的錯誤。
不過,如果您要對應用程式進行偵錯,您可以串行化例外狀況資訊,並使用 ServiceDebugBehavior 類別將它傳回給用戶端。
當回復不包含任何數據時,似乎單向和請求-回覆作業會以大致相同的速度傳回。 發生了什麼事?
指定作業是單向表示作業合約只接受輸入訊息,而且不會傳回輸出訊息。 在 WCF 中,當輸出數據已經發送到網路或擲出例外時,所有客戶端呼叫都回傳。 單向作業的運作方式相同,如果服務無法找到,它們可能會拋出異常;如果服務尚未準備好接受來自網路的資料,它們可能會阻塞。 一般而言,在 WCF 中,這會導致單向呼叫傳回給用戶端的速度比要求-回復更快;但是,透過網路來減緩輸出數據傳送速度的任何條件,會減緩單向作業以及要求-回復作業。 如需詳細資訊,請參閱 One-Way 服務 和 使用WCF用戶端存取服務。
我在使用 X.509 憑證搭配我的服務時,遇到了 System.Security.Cryptography.CryptographicException。 發生了什麼事情?
這通常會在更改 IIS 工作流程運行的用戶帳戶之後發生。 例如,在 Windows XP 中,如果您將 Aspnet_wp.exe 執行的預設使用者帳戶從 ASPNET 變更為自訂使用者帳戶,您可能會看到此錯誤。 如果使用私鑰,使用該金鑰的程式必須有許可權存取儲存該金鑰的檔案。
如果是這種情況,您必須為包含私鑰的檔案授予程序賬戶讀取許可權。 例如,如果 IIS 背景工作進程是在 Bob 帳戶下執行,則您必須為包含私鑰的檔案提供 Bob 讀取許可權。
如需如何為包含特定 X.509 憑證私鑰的檔案提供正確的使用者帳戶存取權的詳細資訊,請參閱 如何:讓 WCF 可存取 X.509 憑證。
我已將操作的第一個參數從大寫變更為小寫,現在我的用戶端拋出例外狀況。 發生了什麼事?
作業簽章中參數名稱的值是合約的一部分,而且區分大小寫。 System.ServiceModel.MessageParameterAttribute當您需要區分本機參數名稱和描述用戶端應用程式作業的元數據時,請使用 屬性。
我正在使用一個追蹤工具時,收到了「找不到端點異常」(EndpointNotFoundException)。 發生了什麼事情?
如果您使用不是系統提供的 WCF 追蹤機制的追蹤工具,而且您收到 EndpointNotFoundException 指出地址篩選不相符的 ,則必須使用 ClientViaBehavior 類別將訊息導向至追蹤公用程式,並讓公用程式將這些訊息重新導向至服務位址。 類別 ClientViaBehavior 會改變尋址標頭 Via
,以分別指定下一個網路位址和最終接收者,其由 To
尋址標頭指出。 不過,這樣做時,請勿變更用來建立 To
值的端點位址。
下列程式代碼範例顯示範例用戶端組態檔。
<endpoint
address="http://localhost:8000/MyServer/"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IMyContract"
behaviorConfiguration="MyClient"
contract="IMyContract"
name="WSHttpBinding_IMyContract">
</endpoint>
<behaviors>
<endpointBehaviors>
<behavior name="MyClient">
<clientVia viaUri="http://localhost:8001/MyServer/"/>
</behavior>
</endpointBehaviors>
</behaviors>
什麼是基位址? 它與端點位址有何關聯?
基位址是類別的 ServiceHost 根位址。 根據預設,如果您將類別 ServiceMetadataBehavior 新增至服務組態,則會從 HTTP 基位址擷取主機發布之所有端點的 Web 服務描述語言 (WSDL),以及提供給元數據行為的任何相對位址,加上 “?wsdl”。 如果您熟悉 ASP.NET 和 IIS,基地址就相當於虛擬目錄。
使用 NetTcpBinding 在服務端點與 mex 端點之間共用埠
如果您將服務的基位址指定為 net.tcp://MyServer:8080/MyService,並新增下列端點:
<services>
<service name="Microsoft.Samples.NetTcp.CalculatorService">
<endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
</services>
如果您修改其中一個 NetTcpBinding 設定,如下列組態代碼段所示:
<bindings>
<netTcpBinding>
<binding closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="11" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
</security>
</binding>
</netTcpBinding>
</bindings>
您會看到如下的錯誤:未處理的例外狀況:System.ServiceModel.AddressAlreadyInUseException:IP 端點 0.0.0.0.0:9000 上已經有接聽程式,您可以使用 MEX 端點的不同埠指定完整 URL,如下列組態代碼段所示:
<services>
<service name="Microsoft.Samples.NetTcp.CalculatorService">
<endpoint address="calcsvc" binding ="netTcpBinding" contract="Microsoft.Samples.NetTcp.ICalculator"/>
<endpoint address="net.tcp://localhost:9001/servicemodelsamples/mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
</services>
從 WCF SOAP 應用程式呼叫 WCF Web HTTP 應用程式時,服務會傳回下列錯誤:405 方法不允許
從 WCF 服務呼叫 WCF Web HTTP 應用程式(使用 WebHttpBinding 和 WebHttpBehavior 的應用程式)可能會產生下列例外狀況:Unhandled Exception: System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: The remote server returned an unexpected response: (405) Method Not Allowed.
。發生此例外狀況,是因為 WCF 使用傳入的 OperationContext 覆寫了傳出的 OperationContext。 若要解決此問題,請在 WCF Web HTTP 服務作業中建立 OperationContextScope 。 例如:
public string Echo(string input)
{
using (new OperationContextScope(this.InnerChannel))
{
return base.Channel.Echo(input);
}
}