前言
本次记录主要记录三个重要的内容:
- Message类概述
- 使用Message类创建消息
- 读取Message类消息
第一部分--Message类概述
Message类是WCF的基本类。客户端与服务之间的所有通信最终都会产生要进行发送和接收的Message实例,通常不会与Message里直接进行交互。相反,您需要使用WCF服务
模型构造(如数据协定、消息协定和操作协定)来描述传入消息和传出协定。在以下情况下可能需要使用Message类:
需要一种替代方式来创建传出的消息内容(例如,从磁盘上的文件直接创建消息),而不是序列化.NET Framework对象。
需要一种替代方式来使用传入的消息内容(例如,需要将XSLT转换应用于原始XML内容),而不是反序列化为.NET Framework对象。
无论消息内容怎样都需要使用常规方式来处理消息(例如,在生成路由器、负载平衡器或发布-订阅系统时对消息进行路由或转发)。
在操作中使用Message类
可以将Message类用作操作的输入参数或操作的返回值。只要在操作中的任何位置使用了Message,就必须遵从以下限制:
操作不能具有任何out或ref参数。
如果该参数存在,其类型必须为Message或消息协定。
返回类型必须为void、Message或消息协定类型
第二部分--创建简单消息
Message类提供了静态CreateMessage工厂方法,所有CreateMessage重载都采用一个类型为MessageVersion的版本参数,该参数指示要用于消息的SOAP和WS-Addressing版本。如果要使用与传入消息相同的协议版本,则可以使用OperaionContext实例(从Current属性获取)上的IncomingMessageVersion属性。大多数CreateMessage重载还具有一个字符串参数,该参数指示要用于消息的SOAP操作。可以将版本设置为None以禁用SOAP信封生成:消息将仅包含正文。
从对象创建消息
另一种重载采用一个附加的Object参数;此重载所创建的消息的正文是给定对象的序列化表示
public Message GetData() { Person p = new Person(); p.name = "wang"; p.age = 20; MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://Microsoft.ServiceModel.Samples/ICalculator/GetDataResponse", p); }
从XML读取器创建消息
有些CreateMessage重载采用一个XmlReader或一个XmlDictionaryReader而不是对象作为正文
public Message GetDataStream() { FileStream stream = new FileStream(@"C:\myfile.xml", FileMode.Open); XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()); MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, "http://Microsoft.ServiceModel.Samples/ICalculator/GetDataStreamResponse", xdr); }
创建错误消息
可以使用某些CreateMessage重载创建SOAP错误消息。其中一个最简单的重载采用一个用于描述错误的MessageFault对象作为参数
public Message GetDataFault() { FaultCode fc = new FaultCode("Receiver"); MessageVersion ver = OperationContext.Current.IncomingMessageVersion; return Message.CreateMessage(ver, fc, "Bad data", "http://Microsoft.ServiceModel.Samples/ICalculator/GetDataFaultResponse"); }
第三部分--读取Message类消息
Message类支持多种从其正文提取消息的方式。他们可以分为以下几类:
- 将整个消息正文一次性写出到XML编写器。这称为“写入消息”。
- 将XML读取器放在消息正文上。这使您可以在以后根根据需要逐段访问消息正文。这称为“读取消息”。
- 可以将整个消息(包括它的正文)复制到类型为MessageBuffer的内存中缓冲区。这称为“复制消息”。
1.写入消息
WriteBodyContents 方法将给定Message实例的正文内容写出到给定XML编写器。
WriteBody写法进行相同的操作,不同之处在于该方法将正文内容封装在适当的包装元素中。
最后WriteMessage写出整个消息,包括SOAP包装信封和标头。请记住,如果SOAP被禁用(Version为MessageVersion.None),则所有这三个方法都进行相同的操作:仅仅写出消息正文内容。
Message reply1 = client.GetDataStream(); Console.WriteLine(reply1.ToString()); FileStream stream = new FileStream(@"c:\log.xml", FileMode.Create); XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(stream); reply1.WriteBodyContents(xdw); reply1.WriteBody(xdw); reply1.WriteMessage(xdw); xdw.Flush();
2.读取消息
读取消息正文的主要方式是调用GetReaderAtBodyContents.
使用GetBody方法还可以将消息振文作为类型化对象进行访问
Message reply1 = client.GetData(); Person p = reply1.GetBody<Person>(); Console.WriteLine(p.name + " " + p.age.ToString());
3.复制消息
通过调用CreateBufferedCopy在内存中缓冲整个消息(包括正文)
缓冲区作为一个MessageBuffer实例返回。可以通过几种方式访问缓冲区中的数据。主要方式是调用CreateMessage以便从缓冲区创建Message实例
访问消息缓冲区内容的另一种方式是使用WriteMessage将缓冲区的内容写出到流中
Message reply1 = client.GetDataStream(); //Copy the message to a buffer. MessageBuffer mb = reply1.CreateBufferedCopy(65536);
访问其他消息部分
该类提供了各种属性,以便访问除曾文内容之外的其他与消息有关的信息。但是,一旦关闭了消息,将无法调用这些属性:
Headers属性表示消息标头。
Properties属性表示消息属性,这些属性是附加到消息的命名数据段,且通常不会在发送消息时发出。
Version属性指示与消息相关联的SOAP和WS-Addressing版本;如果禁用了SOAP,则该属性为None.
IsFault属性在消息为SOAP错误消息时返回true.
IsEmpty属性在消息为空时返回true.
总结
本次课程主要了解Message的概述,以及简单的使用Message类创建消息,以及读取Message类消息。