说明:本内容来自微软的webcast,讲师为徐长龙。为了用手机阅读方便点,抄录存为txt。
本次课程内容包括
- Message 类概述
- 使用 Message 类创建消息
- 读取 Message 类消息
Message 类概述
- Message 类是 WCF 的基本类
- 客户端与服务之间的所有通讯最终都会产生要进行发送和接收的 Message 实例。
- 通常不会与 Message 类直接进行交互。相反,您需要使用 WCF 服务模型构造(如数据协定、消息协定和操作协定)来描述传入消息和传出消息。
- 在以下情况下可能需要使用 Message 类
- 需要一种替代方式来创建传出的消息内容(例如,从磁盘上的文件直接创建消息),而不是序列化.NET Framework 对象。
- 需要一种替代方式来使用传入的消息内容(例如,需要将 XSLT 转换应用于原始 XML 内容),而不是反序列化为.NET Framework 对象。
- 无论消息内容怎样都需要使用常规方式来处理消息(例如,在生成路由器、负载平衡器或发布-订阅系统时对消息进行路由或转发)。
在操作中使用 Message 类
- 可以将 Message 类用作操作的输入参数和/或操作的返回值。只要在操作中的任何位置使用了 Message,就必须遵从以下限制:
- 操作不能具有任何 out 或 ref 参数。
- 不能有一个以上的 input 参数。如果该参数存在,其类型必须为 Message 或消息协定。
- 返回类型必须为void、Message 或消息协定类型
[ServiceContract]
public interface IMyService
{
[OperationContract]
Message GetData();
[OperationContract]
void PutData(Message m);
}
创建简单消息
- Message 类提供了静态 CreateMessage 工厂方法
- 所有 CreateMessage 重载都采用一个类型为 MessageVersion 的版本参数,该参数指示要用于消息的 SOAP 和 WS-Addressing 版本。如果要使用与传入消息相同的协议版本,则可以用 OperationContext(从 Current 属性获取) 实例上的 IncomingMessageVersion 属性。
- 大多数 CreateMessage 重载还具有一个字符串参数,该参数指示要用于消息的 SOAP 操作。
- 可以将版本设置为 None 以禁用 SOAP 信封生成;消息将仅包含正文
从对象创建消息
- 另一种重载采用一个附加的 Object 参数;此重载所创建的消息的正文是给定对象的序列化表示
public Message GetData()
{
Person p = new Person();
p.name="John Doe";
p.age=42;
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver,"GetDataResponse",p);
}
从 XML 读取器创建消息
- 有些 CreateMessage 重载采用一个 XmlReader 或一个 XmlDicitionaryReader 而不是对象作为正文
public Message GetData()
{
FileStream stream = new FileStream("myfile.xml",FileMode.Open);
XmlDictionaryReader xdr = new XmlDictionaryReader.CreateTextReader(stream,new XmlDictionaryReaderQuotas());
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver,"GetDataResponse",xdr);
}
创建错误消息
- 可以使用某些 CreateMessage 重载创建 SOAP 错误消息。其中一个最简单的重载采用一个用于描述错误的 MessageFault 对象作为参数
public Message GetData()
{
FaultCode fc = new FaultCode("Receiver");
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver,fc,"Bad data","GetDataResponse");
}
提取消息正文数据
- Message 类支持多种从其正文提取信息的方式。它们可以分为以下几类:
- 将整个消息正文一次性写出到 XML 编写器。这称为“写入消息”。
- 将 XML 读取器放在消息正文上。这使您可以在以后根据需要逐段访问消息正文。这称为“读取消息”。
- 可以将整个消息(包括他的正文)复制到类型为 MessageBuffer 的内存中缓存区。这称为“复制消息”。
写入消息
- WriteBodyContents 方法将给定 Message 实例的正文内容写出到给定 XML 编写器。
- WriteBody 方法进行相同的操作,不同之处在于该方法将正文内容封装在适当的包装元素(如<soap:body>)中。
- 最后,WriteMessage 写出整个消息,包括SOAP包装信封和标头。请记住,如果SOAP被禁用(Version 为 MessageVersion.None ),则所有这三个方法都进行相同的操作:仅仅写出消息正文内容。
public void PutData(Message m)
{
FileStream stream = new FileStream("myfile.xml",FileMode,Create);
XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(stream);
m.WriterBodyContents(xdw);
xdw.Flush();
}
读取消息
- 读取消息正文的主要方式是调用GetReaderAtBodyContents.
- 使用 GetBody 方法还可以将消息正文作为类型化对象进行访问。
public void PutData(Message m)
{
Persion p = m.GetBody<Person>();
Console.WriteLine(p.name);
}
将消息复制到缓冲区中
- 通过调用 CreateBufferedCopy 在内存中缓冲整个消息(包括正文)。
- 缓冲区作为一个 MessageBuffer 实例返回。可以通过几种方式访问缓冲区的数据。主要方式是调用 CreateMessage 以便从缓冲区创建 Message 实例。
- 访问消息缓冲区内容的另一种方式是是 WriteMessage 将缓冲区的内容写出流中
[OperationContract]
public void ForwardMessage(Message m)
{
//Compy the message to a buffer
MessageBuffer mb = m.CreateBufferedCopy(65536);
//Forward to multipel recipients
foreach (IOutputChannel channel in forwardingAddresses)
{
Message copy = mb.CreateMessage();
channel.Send(copy);
}
//Log to a file.
FileStream stream = new FileStream("log.xml",FileMode.Append);
mb.WriteMessage(stream);
stream.Flush();
}
访问其他消息部分
- 该类提供了各种属性,以便访问除正文内容之外的其他与消息有关的信息。但是,一旦关闭了消息,将无法调用这些属性:
- Headers 属性表示消息标头。请参见本主题稍后关于“使用标头”的部分。
- Properties 属性表示消息属性,这些属性是附加到消息的命名数据段,且通常不会在发送消息时发出。请参见本主题稍后关于“使用属性”的部分。
- Version 属性指示与消息相关联的SOAP 和 WS-Addressing 版本;如果禁用了 SOAP,则该属性为 None。
- IsFault 属性在消息为 SOAP 错误消息时返回true。
- IsEmpty 属性在消息为空时返回 true。
使用标头
public class MyService6:IMyService
{
public void PutData(Message m)
{
foreach (MessageHeaderInfo mhi in m.Headers)
{
Console.WriteLine(mhi.Name);
}
}
public Message GetData()
{
throw new NotImplmentedException();
}
}