Message小结(一)
一、消息版本
为了区别消息的结构和寻址机制,W3C定制了SOAP1.1和SOAP1.2定义消息的结构,WS-Addressing 2004和WS-Addressing 1.0定义消息的寻址机制。
它们对应的命名空间如下:
SOAP1.1:http://schemas.xmlsoap.org/soap/envelope/
SOAP1.2:http://www.w3.org/2003/05/soap-envelope
WS-Addressing 2004:http://schemas.xmlsoap.org/ws/2004/08/addressing
WS-Addressing 1.0:http://www.w3.org/2005/08/addressing
Soap12WSAddressingAugust2004版本的消息:
<s:Envelope xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope"> <s:Header> <a:Action s:mustUnderstand="1">http://www.cnblogs.com/</a:Action> </s:Header> <s:Body> <Order xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication4"> <Name>Order</Name> <Price>85</Price> </Order> </s:Body> </s:Envelope>
Soap11WSAddressing10版本消息:
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header> <a:Action s:mustUnderstand="1">http://www.cnblogs.com/</a:Action> </s:Header> <s:Body> <Order xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication4"> <Name>Order</Name> <Price>85</Price> </Order> </s:Body> </s:Envelope>
详情看MessageVersion类,可以通过CreateVersion(EnvelopeVersion envelopeVersion, AddressingVersion addressingVersion)创建对于的消息版本,以及已经定义好的Soap11WSAddressing10、Soap11WSAddressingAugust2004、Soap11、Soap12等消息版本。
二、创建消息
先定义如下一个将消息写入指定文本的方法。writer.Formatting = Formatting.Indented;的作用是使文本Message缩进显示。
public static void WriteMessage(Message msg, string path) { using (XmlTextWriter writer = new XmlTextWriter(path,Encoding.UTF8)) { writer.Formatting = Formatting.Indented; msg.WriteMessage(writer); } }
(1)创建空白消息
Message的静态方法:public static Message CreateMessage(MessageVersion version, string action);
static void Main(string[] args) { Message msg = Message.CreateMessage(MessageVersion.Soap12WSAddressingAugust2004, "http://www.cnblogs.com/"); WriteMessage(msg, @"D:\1.txt"); }
空消息为:
<s:Envelope xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope"> <s:Header> <a:Action s:mustUnderstand="1">http://www.cnblogs.com/</a:Action> </s:Header> <s:Body /> </s:Envelope>
(2)消息内容为可序列化的对象
class Program { static void Main(string[] args) { Order order = new Order() { Name = "Order", Price = 88 };
Message msg = Message.CreateMessage(MessageVersion.Soap12, "http://www.cnblogs.com/", order); WriteMessage(msg, @"D:\1.txt"); } } [DataContract] public class Order { [DataMember] public string Name; [DataMember] public int Price; }
1.txt中的消息为:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"> <s:Header> <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.cnblogs.com/</Action> </s:Header> <s:Body> <Order xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication4"> <Name>Order</Name> <Price>85</Price> </Order> </s:Body> </s:Envelope>
(3)通过XmlReader将文件中的内容读取到消息中
static void Main(string[] args) { Message msg = Message.CreateMessage(MessageVersion.Soap12, "http://www.cnblogs.com/", new XmlTextReader(@"D:\1.txt")); WriteMessage(msg, @"D:\2.txt"); }
(4)通过XmlElement构造消息Body
static void Main(string[] args) { XNamespace ns = "msdn.microsoft.com"; XElement Body = new XElement(new XElement(ns + "Order", new XElement(ns + "Name", "JDTmall"), new XElement(ns + "Price", "85") )); Message msg = Message.CreateMessage(MessageVersion.Soap12, "http://www.cnblogs.com/", Body); WriteMessage(msg, @"D:\1.txt"); }
1.txt中的消息为:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"> <s:Header> <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.cnblogs.com/</Action> </s:Header> <s:Body> <Order xmlns="msdn.microsoft.com"> <Name>JDTmall</Name> <Price>85</Price> </Order> </s:Body> </s:Envelope>
三、消息的状态
指定消息的状态,消息只能被操作一次,从Created到Read、Written、Copied、Closed。操作过一次的消息后无法还原,即不可能再转变成Created状态。
public enum MessageState { //消息已创建。 Created = 0, //消息正在被读取。 Read = 1, //消息已写入。 Written = 2, //消息已复制。 Copied = 3, // 消息已关闭,无法再进行访问。 Closed = 4, }
(1)Created到Read
如果消息Body是一个可序列化的对象,可以通过public T GetBody<T>();将Body内容反序列化为对象,也可以通过public T GetBody<T>(XmlObjectSerializer serializer);指定序列化器。
static void Main(string[] args) { Order order = new Order() { Name = "Order", Price = 88 }; Message msg = Message.CreateMessage(MessageVersion.Soap12, "http://www.cnblogs.com/", order); Console.WriteLine("MessageState :{0}", msg.State); Order o2 = msg.GetBody<Order>(); Console.WriteLine("MessageState After Read :{0}", msg.State); Console.WriteLine("Message Body:{0} {1}", o2.Name, o2.Price); }
(2)Created到Written
WriteMessage函数内会调用public void WriteMessage(XmlWriter writer);方法。
static void Main(string[] args) { Order order = new Order() { Name = "Order", Price = 88 }; Message msg = Message.CreateMessage(MessageVersion.Soap12, "http://www.cnblogs.com/", order); Console.WriteLine("MessageState :{0}", msg.State); WriteMessage(msg,@"D:\1.txt"); Console.WriteLine("MessageState After Write :{0}", msg.State); }
(3)Created到Copied
public MessageBuffer CreateBufferedCopy(int maxBufferSize);
static void Main(string[] args) { Order order = new Order() { Name = "Order", Price = 88 }; Message msg = Message.CreateMessage(MessageVersion.Soap12, "http://www.cnblogs.com/", order); Console.WriteLine("MessageState :{0}", msg.State); MessageBuffer buffer = msg.CreateBufferedCopy(int.MaxValue); Console.WriteLine("MessageState After Copy :{0}", msg.State); Message msgClone = buffer.CreateMessage(); Console.WriteLine("MessageState After Createbybuffer :{0}", msgClone.State); }
可以将Message变为MessageBuffer,随后Message变为Copied状态。通过MessageBuffer可以无限次的复制消息。