預設下,服務端拋出非 FaultException 異常不會傳遞至客戶端。啟用 ServiceDebugBehavior.IncludeExceptionDetailInFaults 後,異常細節將原封不動傳播。本文剖析其內部處理流程與 FaultFormatter 的關鍵角色。
MessageFault(固定 FaultReason、FaultCode、Action),客戶端捕獲相同資訊的 FaultException。ExceptionDetail,包裝於 MessageFault 並轉為 Fault 訊息,客戶端捕獲 FaultException<ExceptionDetail>,完整保留異常型別、訊息、堆疊等資訊。FaultFormatter 初始化時,會自動將 ExceptionDetail 型別加入自身的 FaultContractInfo 清單(透過反射新增),使其成為已知錯誤契約型別,故反序列化成功。偽代碼如下:
internal FaultFormatter(SynchronizedCollection<FaultContractInfo> faultContractInfoCollection)
{
List<FaultContractInfo> list = new List<FaultContractInfo>(faultContractInfoCollection);
faultContractInfoCollection.Add(new FaultContractInfo(
"https://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher/fault",
typeof(ExceptionDetail)));
this.faultContractInfos = list.ToArray();
}
可行。因 FaultFormatter 已內建對 ExceptionDetail 的序列化/反序列化支援,服務端可直接拋出 FaultException<ExceptionDetail>,無需額外套用 [FaultContract]。客戶端捕獲後可讀取 ex.Detail.Message、ex.Detail.Type 等屬性。範例輸出:
Action: https://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher/fault
Code: https://www.w3.org/2003/05/soap-envelope:Sender
Detail:
Message: 試圖除以零。
Type: System.DivideByZeroException