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"/>
<