上篇介紹了 SOAP Fault 與 FaultException 兩種視角。服務端拋出 FaultException 經序列化成 Fault 訊息,客戶端接收後反序列化重建異常。WCF 自動完成這一切,讓開發者以本地編程模式處理異常。核心在於實現 FaultException 與 Fault 訊息雙向轉換,關鍵中介物件是 MessageFault。
MessageFault 定義於 System.ServiceModel.Channels,其屬性與 SOAP Fault 五大子元素一一對應:Code、Reason、Node、Actor/Role、Detail。透過多載 CreateFault 靜態方法可靈活建構。GetDetail<T>() 反序列化錯誤明細,預設用 DataContractSerializer。WriteTo 方法支援 SOAP 1.1/1.2 不同版本輸出。

圖 1 Message、MessageFault、FaultException 三角轉換關係
範例建立 MessageFault 並分別輸出 SOAP 1.1/1.2 格式,差異明顯:SOAP 1.1 用 faultcode/faultstring/faultactor,SOAP 1.2 用 Code/Reason/Node/Role。
MessageFault.CreateFault(Message, maxBufferSize) 從 Fault 訊息提取 SOAP Fault 建立 MessageFault。反之 Message.CreateMessage(MessageVersion, MessageFault, action) 從 MessageFault 生成 Fault 訊息。範例展示同一 MessageFault 在 SOAP 1.1+WS-Addressing 2004 與 SOAP 1.2+WS-Addressing 1.0 下生成的訊息結構差異。
FaultException 定義轉換 API:靜態 CreateFault(MessageFault, ...) 將 MessageFault 轉為 FaultException;實例 CreateMessageFault() 反向轉換。範例驗證 CalculationError 明細類型的完整轉換保真。
類比正常調用的 MessageFormatter,異常轉換由 FaultFormatter 負責。但因有 MessageFault 中介,FaultFormatter 實際實現 FaultException 與 MessageFault 雙向轉換。客戶端與服務端介面分離:
internal interface IClientFaultFormatter { FaultException Deserialize(MessageFault messageFault, string action); }
internal interface IDispatchFaultFormatter { MessageFault Serialize(FaultException faultException, out string action); }
內部類 System.ServiceModel.Dispatcher.FaultFormatter 實作雙介面。再細分兩種具體實作:DataContractSerializerFaultFormatter 與 XmlSerializerFaultFormatter,分別使用對應序列化器。類圖如下:

圖 2 FaultFormatter 體系結構