CreateMessage 工廠方法建立。XmlReader 擷取、放入資料、產生 SOAP Fault。傳送端:建立 Message → 序列化/編碼為 Stream/Byte[] → 發送。
接收端:接收 Stream/Byte[] → 解碼/反序列化為 Message → 轉換為業務物件(亦屬反序列化)。
MessageVersion 封裝 EnvelopeVersion(SOAP 規範)與 AddressingVersion(WS-Addressing 規範),建立時設定後不可變更。
Name=Default
Envelope=Soap12 (https://www.w3.org/2003/05/soap-envelope)
Addressing=Addressing10 (https://www.w3.org/2005/08/addressing)
Name=Soap11WSAddressing10
Envelope=Soap11 (https://schemas.xmlsoap.org/soap/envelope/)
Addressing=Addressing10 (https://www.w3.org/2005/08/addressing)
Name=Soap12WSAddressingAugust2004
Envelope=Soap12 (https://www.w3.org/2003/05/soap-envelope)
Addressing=Addressing200408 (https://schemas.xmlsoap.org/ws/2004/08/addressing)
警示:MessageVersion.Default 會隨 WCF 版本遷移(預設對應 Soap12WSAddressing10),升級可能導致訊息語義變更,跨版本互通需謹慎使用。
Message msg = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:SomeAction", "Hello There");
// 或傳入可序列化物件(需標記 [Serializable] 或資料契約)
Message msg = Message.CreateMessage(version, action, purchaseOrderObject);
預設使用資料契約序列化器,亦可傳入自訂 XmlObjectSerializer。物件與所有參考型別必須可序列化,否則拋出 InvalidDataContractException。
// 完整訊息
Message msg = Message.CreateMessage(envelopeReader, MAXHEADERSIZE, version);
// 僅本文
Message msg = Message.CreateMessage(version, action, bodyReader);
BodyWriter 為抽象類別,覆寫 OnWriteBodyContents(XmlDictionaryWriter) 可完全控制本文產生過程,適合從檔案/串流直接寫入 XML 節點:
sealed class MyBodyWriter : BodyWriter {
private String m_fileName;
internal MyBodyWriter(String fileName) : base(true) { this.m_fileName = fileName; }
protected override void OnWriteBodyContents(XmlDictionaryWriter writer) {
using (FileStream stream = File.Open(m_fileName, FileMode.Open)) {
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
reader.ReadStartElement();
while (reader.NodeType != XmlNodeType.EndElement) writer.WriteNode(reader, true);
}
}
}
// 使用
Message msg = Message.CreateMessage(version, action, new MyBodyWriter("bodyContent.xml"));
下半部將介紹 SOAP Fault 與 MessageFault。