Message类概述
Message类是WCF的基本类。
客户端与服务之间的所有通信最终都会产生要进行发送和接收的Message实例。
通常不会与Message类直接进行交互。相反,需要使用WCF服务模型构造(如数据协定、消息协定和操作协定)来描述传入消息和传出消息。
在以下情况下可能需要使用Message类:
1) 需要一种替代方式来创建传出的消息内容(例如:从磁盘上的文件直接创建消息),而不是序列化.NET Framework对象。
2) 需要一种替代方式来使用传入的消息内容(例如:需要将XSLT转换应用于原始的XML内容),而不是反序列化成为.NET Framework对象。
3) 无论消息内容怎样都需要使用常规方式来处理消息(例如,在生成路由器、负载平衡器或发布-订阅系统时对消息进行路由或转发)。
在操作中使用Message类
可以将Message类用作操作的输入参数和/或操作的返回值。只要在操作中的任何位置使用了Message,就必须遵守以下限制:
1) 操作不能具有任何out或ref参数。
2) 不能有一个以上的input参数。如果该参数存在,其类型必须为Message或消息协定。
3) 返回类型必须为void、Message或消息协定类型。
创建简单消息
1. Message类提供了静态CrateMessage工厂方法
1) 所有CreateMessage重载都采用了一个类型为MessageVersion的版本参数,该参数只是要用于消息的SOAP和WS-Addressing版本。如果要使用与传入消息相同的协议版本,则可以使用OperationContext实例(从Current属性获取)上的IncomingMessageVersion属性。
2) 大多数CreateMessage重载还具有一个字符串参数,该参数只是要用于消息的SOAP操作。
3) 可以将版本设置为None以金庸SOAP信封生成;消息将仅包含正文。
2. 另一种重载采用一个附加的Object参数;此重载所创建的消息的正文是给定对象的序列化表示。
从XML读取器创建消息
有些CreateMessage重载采用一个XmlReader或一个XmlDictionaryReader而不是对象作为正文。
创建错误消息
可以使用某些CreateMessage重载创建SOAP错误信息。其中一个最简单的重载采用一个用于描述错误的MessageFault对象作为参数。
DEMO
1) 新建一个WCF Service Application——“Video8.Demo1.XmlReader”,删除默认生成的服务后,添加WCF Service——“CalculatorService”,在WCF服务接口中定义WCF服务,定义Message
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
namespace Video8.Demo1.XmlReader
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ICalculatorService" in both code and config file together.
[ServiceContract(Namespace = "http://Video8.Demo1.XmlReader")]
public interface ICalculatorService
{
[OperationContract]
Message Sum(Message request);
[OperationContract]
Message GetFirst();
//[OperationContract]
//Message GetData();
//[OperationContract]
//Message GetDataStream();
//[OperationContract]
//Message GetDataFault();
}
}
2) 在CalculatorService中实现ICalculatorService这个WCF服务类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
using System.Xml;
using System.IO;
using System.Globalization;
namespace Video8.Demo1.XmlReader
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "CalculatorService" in code, svc and config file together.
public class CalculatorService : ICalculatorService
{
public Message Sum(Message request)
{
int sum = 0;
string text = "";
//以读取器的方式拿到Message内容
System.Xml.XmlReader body = request.GetReaderAtBodyContents();
//循环获取Messagebody里的值
while (body.Read())
{
text = body.ReadString().Trim();
if (text.Length > 0)
{
sum += Convert.ToInt32(text, CultureInfo.InvariantCulture);
}
}
body.Close();
//由于这个是有传入消息,就可以使用request.Version来获得SOAP协议的版本了
Message response = Message.CreateMessage(request.Version, "http://Video8.Demo1.XmlReader/ICalculatorService/SumResponse", sum);
return response;
}
public Message GetFirst()
{
//创建一个最简单的消息,首先获得当前上下文传入的Message版本,由于是没有传入消息所以要使用上下文来获取Message版本信息
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
//使用静态方法创建Message,http会序列化成客户端的ReplyActionAttribute属性内容
return Message.CreateMessage(ver, "http://Video8.Demo1.XmlReader/ICalculatorService/GetFirstResponse");
}
}
}
3) 配置Web.config信息:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Video8.Demo1.XmlReader.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="PortSharingBinding" contract="Video8.Demo1.XmlReader.ICalculatorService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="PortSharingBinding">
<security mode="None"/>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
4) 部署配置到IIS上后,创建客户端应用程序Client,添加该WCF服务,打开Reference.cs客户端代理类可以看到这里生成的GetFirst()方法标记了ReplyAction="http://Video8.Demo1.XmlReader/ICalculatorService/GetFirstResponse"这个正式我们在服务端使用了return Message.CreateMessage(ver, "http://Video8.Demo1.XmlReader/ICalculatorService/GetFirstResponse");而自动生成的ReplayAction。
[System.ServiceModel.OperationContractAttribute(Action="http://Video8.Demo1.XmlReader/ICalculatorService/GetFirst", ReplyAction="http://Video8.Demo1.XmlReader/ICalculatorService/GetFirstResponse")]
System.ServiceModel.Channels.Message GetFirst();
5) 然后再Main方法中进行测试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
namespace Client
{
class Program
{
static void Main(string[] args)
{
ServiceReference1.CalculatorServiceClient client = new ServiceReference1.CalculatorServiceClient();
Message Replay1 = client.GetFirst();
Console.WriteLine(Replay1.ToString());
client.Close();
Console.ReadKey();
}
}
}
6) 运行一下该客户端程序,在客户端生成一个新的消息Replay1,然后我们打印出来可以看到,这是一个空的消息类,只有信封信息。
7) 然后我们在WCF服务里增加Sum方法,在ICalculatorService里增加:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
namespace Video8.Demo1.XmlReader
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ICalculatorService" in both code and config file together.
[ServiceContract(Namespace = "http://Video8.Demo1.XmlReader")]
public interface ICalculatorService
{
[OperationContract]
Message Sum(Message request);
[OperationContract]
Message GetFirst();
//[OperationContract]
//Message GetData();
//[OperationContract]
//Message GetDataStream();
//[OperationContract]
//Message GetDataFault();
}
}
8) 在CalculatorService类里实现WCF服务接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
using System.Xml;
using System.IO;
using System.Globalization;
namespace Video8.Demo1.XmlReader
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "CalculatorService" in code, svc and config file together.
public class CalculatorService : ICalculatorService
{
public Message Sum(Message request)
{
int sum = 0;
string text = "";
//以读取器的方式拿到Message内容
System.Xml.XmlReader body = request.GetReaderAtBodyContents();
//循环获取Messagebody里的值
while (body.Read())
{
text = body.ReadString().Trim();
if (text.Length > 0)
{
sum += Convert.ToInt32(text, CultureInfo.InvariantCulture);
}
}
body.Close();
//由于这个是有传入消息,就可以使用request.Version来获得SOAP协议的版本了
Message response = Message.CreateMessage(request.Version, "http://Video8.Demo1.XmlReader/ICalculatorService/SumResponse", sum);
return response;
}
public Message GetFirst()
{
//创建一个最简单的消息,首先获得当前上下文传入的Message版本,由于是没有传入消息所以要使用上下文来获取Message版本信息
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
//使用静态方法创建Message,http会序列化成客户端的ReplyActionAttribute属性内容
return Message.CreateMessage(ver, "http://Video8.Demo1.XmlReader/ICalculatorService/GetFirstResponse");
}
}
}
9) 编译发布到IIS上后,更新客户端的服务代理类。更新后可以看到在Reference.cs这个代理类里,已经有Sum方法了,注意这里的ReplayAction也是在服务端指定的。
[System.ServiceModel.OperationContractAttribute(Action="http://Video8.Demo1.XmlReader/ICalculatorService/Sum", ReplyAction="http://Video8.Demo1.XmlReader/ICalculatorService/SumResponse")]
System.ServiceModel.Channels.Message Sum(System.ServiceModel.Channels.Message request);
10) 然后再Main方法中进行测试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel;
namespace Client
{
class Program
{
static void Main(string[] args)
{
ServiceReference1.CalculatorServiceClient client = new ServiceReference1.CalculatorServiceClient();
Message Replay1 = client.GetFirst();
Console.WriteLine(Replay1.ToString());
Console.WriteLine("————————————————");
using (new OperationContextScope(client.InnerChannel))
{
//定义一个数组
int[] values = { 1, 2, 3, 4, 5 };
//生成一个Message对象,用于传入参数使用,
//Message版本为当前上下文的输出信息的标头的版本信息,Message的action要与代理类调用该方法的action要一致。
//然后再传入values作为Message的参数
Message request = Message.CreateMessage(OperationContext.Current.OutgoingMessageHeaders.MessageVersion, "http://Video8.Demo1.XmlReader/ICalculatorService/Sum", values);
//调用服务端sum方法,传入参数为上面生成的消息实例
Message replay = client.Sum(request);
//Console.WriteLine(replay.ToString());
int sum = replay.GetBody<int>();
Console.WriteLine("Sum(1,2,3,4,5)={0}", sum);
client.Close();
}
Console.ReadKey();
}
}
}
11) 测试结果计算出了sum的值,这就是传入一个Message类型的参数后,在返回一个Message类型的参数。
12) 我们在来试试如何从一个对象类型来创建一个消息。在ICalculatorService里增加新的接口GetData:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
namespace Video8.Demo1.XmlReader
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ICalculatorService" in both code and config file together.
[ServiceContract(Namespace = "http://Video8.Demo1.XmlReader")]
public interface ICalculatorService
{
[OperationContract]
Message Sum(Message request);
[OperationContract]
Message GetFirst();
//从一个对象来创建一个消息
[OperationContract]
Message GetData();
//[OperationContract]
//Message GetDataStream();
//[OperationContract]
//Message GetDataFault();
}
}
13) 添加一个消息协定Person类,用于在消息中使用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;
namespace Video8.Demo1.XmlReader
{
[MessageContract]
public class Person
{
[MessageBodyMember]
public string name;
[MessageBodyMember]
public int age;
}
}
14) 在CalculatorService里实现新增的WCF服务。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
using System.Xml;
using System.IO;
using System.Globalization;
namespace Video8.Demo1.XmlReader
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "CalculatorService" in code, svc and config file together.
public class CalculatorService : ICalculatorService
{
public Message Sum(Message request)
{
int sum = 0;
string text = "";
//以读取器的方式拿到Message内容
System.Xml.XmlReader body = request.GetReaderAtBodyContents();
//循环获取Messagebody里的值
while (body.Read())
{
text = body.ReadString().Trim();
if (text.Length > 0)
{
sum += Convert.ToInt32(text, CultureInfo.InvariantCulture);
}
}
body.Close();
//由于这个是有传入消息,就可以使用request.Version来获得SOAP协议的版本了
Message response = Message.CreateMessage(request.Version, "http://Video8.Demo1.XmlReader/ICalculatorService/SumResponse", sum);
return response;
}
public Message GetFirst()
{
//创建一个最简单的消息,首先获得当前上下文传入的Message版本,由于是没有传入消息所以要使用上下文来获取Message版本信息
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
//使用静态方法创建Message,http会序列化成客户端的ReplyActionAttribute属性内容
return Message.CreateMessage(ver, "http://Video8.Demo1.XmlReader/ICalculatorService/GetFirstResponse");
}
//从一个对象类型来创建消息
public Message GetData()
{
Person p = new Person();
p.name = "wang";
p.age = 20;
//服务端使用OperationContext.Current.IncomingMessageVersion来获取Message版本
//客户端使用OperationContext.Current.OutgoingMessageHeaders.MessageVersion来获取Message版本。
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
//返回一个静态生成的Message实例,参数为版本信心;action;Person类的参数实例p。
return Message.CreateMessage(ver, "http://Video8.Demo1.XmlReader/ICalculatorService/GetDataResponse", p);
}
}
}
15) 部署到IIS上后,更新client端的WCF服务。可以打开客户端代理类Reference.cs来看到,已经生成了我们添加的方法GetData,该方法的ReplayAction就是我们在WCF服务端定义的参数。
[System.ServiceModel.OperationContractAttribute(Action="http://Video8.Demo1.XmlReader/ICalculatorService/GetData", ReplyAction="http://Video8.Demo1.XmlReader/ICalculatorService/GetDataResponse")]
System.ServiceModel.Channels.Message GetData();
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace Client
{
[MessageContract]
public class Person
{
[MessageBodyMember]
public string name;
[MessageBodyMember]
public int age;
}
}
17) 这里还要注意的是要把客户端项目Client里的命名空间都改成与服务器端的命名空间一致:namespace Video8.Demo1.XmlReader
这样就可以进行在Main方法中测试了:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel;
namespace Video8.Demo1.XmlReader
{
class Program
{
static void Main(string[] args)
{
ServiceReference1.CalculatorServiceClient client = new ServiceReference1.CalculatorServiceClient();
Message Replay1 = client.GetFirst();
Console.WriteLine(Replay1.ToString());
Console.WriteLine("————————————————");
using (new OperationContextScope(client.InnerChannel))
{
//定义一个数组
int[] values = { 1, 2, 3, 4, 5 };
//生成一个Message对象,用于传入参数使用,
//Message版本为当前上下文的输出信息的标头的版本信息,Message的action要与代理类调用该方法的action要一致。
//然后再传入values作为Message的参数
Message request = Message.CreateMessage(OperationContext.Current.OutgoingMessageHeaders.MessageVersion, "http://Video8.Demo1.XmlReader/ICalculatorService/Sum", values);
//调用服务端sum方法,传入参数为上面生成的消息实例
Message replay = client.Sum(request);
//Console.WriteLine(replay.ToString());
int sum = replay.GetBody<int>();
Console.WriteLine("Sum(1,2,3,4,5)={0}", sum);
Console.WriteLine("————————————————");
//GetData方法的调用
Message reply1 = client.GetData();
Console.WriteLine(reply1.ToString());
//获取GetBody类后转换成Person类赋值给Person类的实例p
Person p = reply1.GetBody<Person>();
Console.WriteLine(p.name + " " + p.age);
client.Close();
}
Console.ReadKey();
}
}
}
18) 运行结果如下:可以看到在客户端调用该WCF服务后,获得了一个Message类,该Message类是由一个对象类型来创建的。
19) 我们添加一个xml文件来让Message读取后返回给客户端,首先在服务端项目里添加一个xml文件“myfile.xml”,然后再ICalculatorService里添加一个WCF服务接口:
//从一个XML文件读取创建一个消息
[OperationContract]
Message GetDataStream();
20) 实现该WCF服务:
public Message GetDataStream()
{
FileStream stream = new FileStream(@"E:\开发知识\9. WCF\从零开始学WCF系列\DEMO\Video8.Demo1.XmlReader\Video8.Demo1.XmlReader\myfile.xml", FileMode.Open);
//xml读取器来创建一个从没有file读取内容的读取器
XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver, "http://Video8.Demo1.XmlReader/ICalculatorService/GetDataStreamResponse", xdr);
}
21) 编译WCF服务后,更新到IIS上,在client项目里进行更新Service Reference。然后再Main方法里加入测试代码:
//从服务端的XML文件里读取Message
Message reply2 = client.GetDataStream();
Console.WriteLine(reply2.ToString());
Console.WriteLine("+++++++++++++++++++");
//把从服务器端读取过来的Message存在客户端本地XML里
FileStream stream = new FileStream(@"C:\log.xml", FileMode.Create);
XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(stream);
reply2.WriteBodyContents(xdw);
Console.WriteLine("+++++++++++++++++++");
reply2.WriteBody(xdw);
Console.WriteLine("+++++++++++++++++++");
reply2.WriteMessage(xdw);
xdw.Flush();
运行结果如下:
22) 下一步我们来测试一下,如何从服务器端通过Message传递一个Fault错误消息给客户端,这里要注意的是所传递的Fault也是一个Message类,他并不是一个异常信息,所以无法在客户端中通过Catch来捕获。先在ICalculatorService里添加一个接口:
//把一个Fault创建成消息传递给客户端
[OperationContract]
Message GetDataFault();
23) 实现该接口:
public Message GetDataFault()
{
//创建一个FaultCode实例,用来承载所要传递的Fault
FaultCode fc = new FaultCode("Receiver");
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
//重载CreateMessage(版本,FaultCode实例,错误原因信息,action);
return Message.CreateMessage(ver, fc, "Bad data", "http://Video8.Demo1.XmlReader/ICalculatorService/GetDataFaultResponse");
}
24) 编译该WCF服务后,部署到IIS上,然后再client客户端更新Service Reference。在Main方法中加入测试代码:
//把从服务器端传过来的Message类型的Fault读取出来,这里虽然使用Try Catch,但是是无法补货到的,对于客户端来说
//Fault也只是一个Message而已。
try
{
Message reply3 = client.GetDataFault();
Console.WriteLine(reply3.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
运行结果如下:源代码: http://download.youkuaiyun.com/detail/eric_k1m/6402289
提取消息正文数据
Message类支持多种从其正文提取信息的方式。他们可以分为以下几类:
1) 将整个消息正文一次性写出到XML编写器(例如:XmlDictionaryWriter)。这称为“写入消息”。
2) 将XML读取器放在消息正文上。这使的可以在以后根据需要逐段访问消息正文。这成为“读取消息”。
3) 可以将整个消息(包括它的正文)复制到类型为MessageBuffer的内存中缓冲区。这成为“复制消息”。
写入消息
WriteBodyContents方法将给定Message实例的正文内容写出到给定XML编写器。
WriteBody方法进行相同的操作,不同之处在于该方法将正文内容封装在适当的包装元素(如<soap:body>)中。
最后,WriteMessage写出整个消息,包括SOAP包装信封和标头。
需要记住的是,如果SOAP被禁用(Version为MessageVersion.None),则所有这三个方法都进行相同的操作:仅仅写出消息正文内容。
所谓的写入消息是指把XML类型的文件也好流也好,通过服务器端提供的Message类(该实例中已经有XML文件或流文件)的写出到客户端的FileStream里去。
读取消息
读取消息是指把Message类中的消息读取出来,以供使用。
读取消息正文的主要方式是调用 GetReaderAtBodyContents
使用GetBody方法还可以将消息正文作为类型化对象进行访问。GetBody<T>() T类是已知的类就可以读取到对象中去。
将消息复制到缓冲区中
通过调用CreateBufferedCopy在内存中缓冲整个消息(包括正文)。
缓冲区作为一个MessageBuffer实例返回。可以通过几种方式访问缓冲区的数据。主要方式是调用CreateMessage以便从缓冲区创建Message实例。
访问消息缓冲区内容的另一种方式是使用WriteMessage将缓冲区的内容写出到流中。
DEMO
1) “写入消息”的测试;该Demo也使用上面的Demo,只是在客户端Main方法中,使用如下测试:
//从服务端的XML文件里读取Message
Message reply2 = client.GetDataStream();
Console.WriteLine(reply2.ToString());
Console.WriteLine("+++++++++++++++++++");
//把从服务器端读取过来的Message存在客户端本地XML里
FileStream stream = new FileStream(@"C:\log.xml", FileMode.Create);
XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(stream);
//只把MessageBody里的内容写入到xml文件里
reply2.WriteBodyContents(xdw);
Console.WriteLine("+++++++++++++++++++");
//把body标记和body内部的内容一起写入到xml文件里
reply2.WriteBody(xdw);
Console.WriteLine("+++++++++++++++++++");
//把整个消息都写入到xml文件里,包括标头,正文等全部信息。
reply2.WriteMessage(xdw);
xdw.Flush();
Console.WriteLine("————————————————");
2) “读取消息”的方式,也是一样在客户端Main方法中:
//GetData方法的调用
Message reply1 = client.GetData();
Console.WriteLine(reply1.ToString());
//获取GetBody类后转换成Person类赋值给Person类的实例p
Person p = reply1.GetBody<Person>();
Console.WriteLine(p.name + " " + p.age);
Console.WriteLine("————————————————");
3) “写入到缓冲区”
//把Message写入到缓冲区
Message reply4 = client.GetDataStream();
//把消息拷贝进缓冲区,并设置该缓冲区大小为65536
MessageBuffer mb = reply4.CreateBufferedCopy(65536);
//从缓冲区里的消息写入到XML文件里
FileStream st = new FileStream(@"C:\test\log.xml", FileMode.Append);
mb.WriteMessage(st); //使用缓冲区.WriteMessage()方法写入到XML文件
st.Flush();
访问其他消息部分
该类提供了各种属性,以便访问除正文内容以外的其他与消息有关的信息。但是,一旦关闭了消息,将无法调用这些属性:
1) Headers属性表示消息标头。
2) Properties属性表示消息属性,这些属性是附加到消息的命名数据段,且通常不会在发送消息时发出。
3) Version属性指示与消息相关联的SOAP和WS-Addressing版本;如果禁用了SOAP,则该属性为None。
4) IsFault属性在消息为SOAP错误消息时返回true。
5) IsEmpty属性在消息为空时返回true。
DEMO
也是在之前我们所创建的DEMO之上来测试,在客户端Main方法中添加:
//访问消息的其他部分
Message reply5 = client.GetData();
//打印出整个消息
Console.WriteLine(reply5.ToString());
Console.WriteLine("+++++++++++++++++++");
//使用Message的Headers属性循环访问该Message的Header
foreach (MessageHeaderInfo mhi in reply5.Headers)
{
Console.WriteLine(mhi.Name); //输出Header的Name
}
输出的结果:
以上所有DEMO源代码: http://download.youkuaiyun.com/detail/eric_k1m/6402559