首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 訊息傳遞架構深度解析:從 XML InfoSet 到 Message 類別完整指南

     編輯:關於.NET

Windows Communication Foundation (WCF) 建立在 XML InfoSet、SOAP 與 WS-Addressing 之上,提供統一程式模型下的極致靈活性:支援文字、二進位、MTOM 三種 XML 表示形式,允許自由選擇 SOAP 版本 (1.1/1.2/None) 與 WS-Addressing 版本,並透過 Message 類別統一建模訊息結構。本文系統梳理 WCF 訊息傳遞核心概念與實作細節。

XML 表示形式三選一

WCF 擴充 System.Xml 引入 XmlDictionaryReader/Writer,提供三種表示形式的工廠方法:

形式建立方法適用場景
文字 (XML 1.0)CreateTextReader/Writer最大互通性、除錯、記錄
二進位CreateBinaryReader/Writer.NET 專有、高效能、低頻寬
MTOMCreateMtomReader/Writer互通性 + 二進位負載優化、W3C 標準

同一 XML InfoSet 可在三種形式間無損轉換,程式碼僅需切換 Reader/Writer 實作。

Message 類別核心成員

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)

建立與序列化訊息本文

三種方式提供本文內容:

  1. XmlReader:Message.CreateMessage(version, action, xmlReader)
  2. 可序列化物件 (預設 DataContractSerializer):Message.CreateMessage(version, action, customerObject)
  3. MessageFault:建立錯誤訊息

讀取本文:GetReaderAtBodyContents() 取得 XmlDictionaryReader,或 GetBody<T>() 直接反序列化。

訊息狀態機與一次性本文

MessageState 確保串流本文只能被處理一次:

Created → (GetBody/WriteMessage) → Read/Written → Close → Closed
                    → (CreateBufferedCopy) → Copied

狀態離開 Created 後,再次存取本文將拋出例外。需多次處理時,使用 CreateBufferedCopy 或載入 XmlDocument/反序列化物件。

標頭與屬性

  • Headers:隨訊息傳輸的 SOAP 標頭,MessageHeader.CreateHeader(name, ns, value) 建立,中介處理常用
  • Properties:本地處理階段的名稱/物件對,不隨訊息傳輸 (如 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;
}

端點、綁定與訊息編碼器

端點 = 位址 + 綁定 + 合約。綁定決定傳輸、編碼、協議堆疊。三大內建編碼器:

編碼器對應綁定預設訊息版本
TextMessageEncoderBasicHttpBinding, WSHttpBindingSoap11 / Soap12WSAddressing10
BinaryMessageEncoderNetTcpBinding, NetNamedPipeBinding, NetMsmqBindingSoap12WSAddressing10
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());

完整範例:MTOM 編碼的通用服務與客戶端

服務端使用 IUniversalOneWay 接收任意訊息,客戶端以 Customer 物件建立訊息透過 ChannelFactory 發送,雙方皆使用自訂 CustomBinding + MtomMessageEncodingBindingElement。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved