Windows Communication Foundation (WCF) 建立在 XML InfoSet、SOAP 與 WS-Addressing 之上,提供統一程式模型下的極致靈活性:支援文字、二進位、MTOM 三種 XML 表示形式,允許自由選擇 SOAP 版本 (1.1/1.2/None) 與 WS-Addressing 版本,並透過 Message 類別統一建模訊息結構。本文系統梳理 WCF 訊息傳遞核心概念與實作細節。
WCF 擴充 System.Xml 引入 XmlDictionaryReader/Writer,提供三種表示形式的工廠方法:
| 形式 | 建立方法 | 適用場景 |
|---|---|---|
| 文字 (XML 1.0) | CreateTextReader/Writer | 最大互通性、除錯、記錄 |
| 二進位 | CreateBinaryReader/Writer | .NET 專有、高效能、低頻寬 |
| MTOM | CreateMtomReader/Writer | 互通性 + 二進位負載優化、W3C 標準 |
同一 XML InfoSet 可在三種形式間無損轉換,程式碼僅需切換 Reader/Writer 實作。
public abstract class Message : IDisposable {
public static Message CreateMessage(...); // 多重載建立訊息
public MessageBuffer CreateBufferedCopy(int maxBufferSize); // 緩衝副本
public void Close(); // 關閉釋放
public XmlDictionaryReader GetReaderAtBodyContents(); // 讀取本文
public T GetBody<T>(); // 反序列化本文
public void WriteMessage(XmlDictionaryWriter writer); // 寫入整個訊息
public void WriteBody(XmlDictionaryWriter writer); // 僅寫入本文
public MessageHeaders Headers { get; } // 標頭集合
public MessageProperties Properties { get; } // 本地屬性集合
public MessageState State { get; } // Created/Read/Written/Copied/Closed
public MessageVersion Version { get; } // SOAP + WS-Addressing 版本
}
MessageVersion 封裝 EnvelopeVersion (SOAP) 與 AddressingVersion:
// 手動組合
var version = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.WSAddressing10);
// 內建快取組合
MessageVersion.Soap12WSAddressing10 // 等同 Default
MessageVersion.Soap11WSAddressingAugust2004
MessageVersion.None // 無 SOAP、無 WS-Addressing (純 XML)
三種方式提供本文內容:
Message.CreateMessage(version, action, xmlReader)DataContractSerializer):Message.CreateMessage(version, action, customerObject)讀取本文:GetReaderAtBodyContents() 取得 XmlDictionaryReader,或 GetBody<T>() 直接反序列化。
MessageState 確保串流本文只能被處理一次:
Created → (GetBody/WriteMessage) → Read/Written → Close → Closed
→ (CreateBufferedCopy) → Copied
狀態離開 Created 後,再次存取本文將拋出例外。需多次處理時,使用 CreateBufferedCopy 或載入 XmlDocument/反序列化物件。
MessageHeader.CreateHeader(name, ns, value) 建立,中介處理常用HttpRequestMessageProperty)透過 OperationContract.Action 將訊息動作對應到方法:
[ServiceContract]
public interface IUniversalOneWay {
[OperationContract(Action = "*")] // 收攏所有動作
void ProcessMessage(Message msg);
}
[ServiceContract]
public interface ICustomer {
[OperationContract(Action = "urn:add-customer")]
void AddCustomer(Customer cust); // 自動反序列化
}
MessageContract 進一步控制標頭/本文映射:
[MessageContract(IsWrapped = false)]
public class AddCustomerRequest {
[MessageHeader(Name = "ContextId", Namespace = "...")] public Guid ContextId;
[MessageBodyMember] public Customer Customer;
}
端點 = 位址 + 綁定 + 合約。綁定決定傳輸、編碼、協議堆疊。三大內建編碼器:
| 編碼器 | 對應綁定 | 預設訊息版本 |
|---|---|---|
| TextMessageEncoder | BasicHttpBinding, WSHttpBinding | Soap11 / Soap12WSAddressing10 |
| BinaryMessageEncoder | NetTcpBinding, NetNamedPipeBinding, NetMsmqBinding | Soap12WSAddressing10 |
| MtomMessageEncoder | 自訂綁定 | 可配置 |
切換編碼器範例:
var binding = new BasicHttpBinding();
binding.MessageEncoding = WSMessageEncoding.Mtom; // 切換為 MTOM
// 或完全自訂
var custom = new CustomBinding();
custom.Elements.Add(new MtomMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8));
custom.Elements.Add(new HttpTransportBindingElement());
服務端使用 IUniversalOneWay 接收任意訊息,客戶端以 Customer 物件建立訊息透過 ChannelFactory 發送,雙方皆使用自訂 CustomBinding + MtomMessageEncodingBindingElement。