分散式系統中,服務端異常如何正確傳遞至客戶端是核心課題。WCF 採用 SOAP Fault 機制,透過 FaultContract 與 FaultException<T> 實現強型別錯誤傳遞,避免通道錯誤導致 Proxy 失效。
CLR 異常模型特性:跨語言、跨進程、跨機器;優於返回碼檢查;使用 try/catch/finally 結構;throw 拋出異常物件。
CommunicationExceptionWCF 將無法識別的 .NET 異常統一包裝為 FaultException(可序列化),客戶端可捕獲 FaultException 或基類 CommunicationException。泛型版本 FaultException<TDetail> 允許攜帶自訂錯誤資料型別 TDetail。
屬 WCF 四大契約之一。裝飾於 OperationContract,聲明該操作可能拋出的強型別 SOAP Fault:
[ServiceContract]
public interface IWCFService {
[OperationContract]
[FaultContract(typeof(OverflowException))]
string SayHello(string name);
}
若未標註 FaultContract,服務拋出的 FaultException<OverflowException> 會被視為未宣告 Fault,導致通道進入 Faulted 狀態。
實作 System.ServiceModel.Dispatcher.IErrorHandler 可攔截未處理異常:
ProvideFault:將任意異常轉換為 FaultException<T>(異常提升)HandleError:記錄日誌、監控告警透過 IServiceBehavior.ApplyDispatchBehavior 掛載至分發器。
[ServiceContract(Namespace = "https://www.cnblogs.com/frank_xl/")]
public interface IWCFService {
[OperationContract]
[FaultContract(typeof(OverflowException))]
string SayHello(string name);
[OperationContract]
[FaultContract(typeof(OverflowException))]
string SayGoodBye(string name);
}
public class WCFService : IWCFService {
public string SayHello(string name) {
if (name.Length < 10) {
Console.WriteLine("Hello! {0}...", name);
return "Hello! " + name;
}
throw new FaultException<OverflowException>(new OverflowException(), "name Length is more than 10");
}
// SayGoodBye 同理
}
static void Main() {
using (ServiceHost host = new ServiceHost(typeof(WCFService))) {
host.Open();
Console.WriteLine("Host running at {0}", host.State);
foreach (var se in host.Description.Endpoints)
Console.WriteLine("Listening at {0}", se.Address.Uri);
Console.Read();
}
}
var proxy = new WCFServiceClient("WSHttpBinding_IWCFService");
try {
Console.WriteLine(proxy.SayHello("Frank Xu")); // 正常
Console.WriteLine(proxy.SayHello("Frank Xu Lei WSHttpBinding")); // 觸發 Fault
}
catch (FaultException<OverflowException> oe) {
Console.WriteLine("Fault: " + oe.Message);
}
catch (CommunicationException ce) {
Console.WriteLine("Comm: " + ce.Message);
}
finally { proxy.Close(); }

FaultContract 或拋出非 FaultException,客戶端仍可收到異常,但通道會 Faulted。ServiceBehavior.IncludeExceptionDetailInFaults=true 可讓客戶端捕獲詳細 .NET 異常,但生產環境嚴禁開啟(資安與效能風險)。InstanceContextMode:PerCall/PerSession 釋放實例,Single 則保留。掌握 FaultContract + FaultException<T> 模式,是建構健壯 WCF 服務的基石。配合 IErrorHandler 實現集中式錯誤處理與日誌記錄,可大幅提升系統可維護性。