在WCF中客户端与服务端都是靠消息进行传输的,消息格式和SOAP一样,具有消息标头和正文。客户端和服务端之间的所有通讯最终都会产生System.ServiceModel.Channels. Message

实例。在平时操作中,很少直接操作Message类型,而是通过WCF服务模型构造(如数据契约、消息契约和操作契约)来描述传入消息和传出消息。所以,要想透彻的理解WCF有必要对Message多些了解。下面看一个简单的类,来了解一下Message用到的类。

using System;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.IO;
using System.Xml;
using System.Text;
using System.ServiceModel.Channels;

namespace WcfMessage
{
[DataContract(Namespace
="http://www.cnblogs.com/qiuwuyu")]
public class Fruit
{
private string m_Name = string.Empty;
private string m_Price = string.Empty;
public Fruit(string name, string price)
{
m_Name
= name;
m_Price
= price;
}
[DataMember]
public string Name
{
get{ return m_Name; }
set{ m_Name = value; }
}
[DataMember]
public string Price
{
get { return m_Price; }
set { m_Price = value; }
}
}
[DataContract(Namespace
= "http://www.cnblogs.com/qiuwuyu")]
public class FruitHeader
{
private string m_HeaderKey = string.Empty;
[DataMember]
public string HeaderKey
{
get { return m_HeaderKey; }
set { m_HeaderKey = value; }
}
public FruitHeader(string key)
{
m_HeaderKey
=key;
}
}
class Program
{
static void Main(string[] args)
{
Fruit fruit
= new Fruit("banana", "6.00");
//把Fruit类型序列化为xml文件
using (FileStream fs = new FileStream("Fruit.xml", FileMode.Create))
{
DataContractSerializer dataSer
= new DataContractSerializer(typeof(Fruit));
dataSer.WriteObject(fs, fruit);
}

XmlDocument xmlDoc
= new XmlDocument();
xmlDoc.Load(
"Fruit.xml");
//用二进制编码的xml文档
using (FileStream binStream = new FileStream("Fruit.bin", FileMode.Create))
{
using (XmlWriter xw = XmlDictionaryWriter.CreateBinaryWriter(binStream))
{
xmlDoc.WriteContentTo(xw);
}
}
//用mtom编码的xml文档
using (FileStream mtomStream = new FileStream("Fruit.mtom", FileMode.Create))
{
using (XmlWriter xw = XmlDictionaryWriter.CreateMtomWriter(mtomStream, Encoding.UTF8, 1024, "text/xml"))
{
xmlDoc.WriteTo(xw);
}
}

//创建一消息,并用文本编码的消息
Message message1 = Message.CreateMessage(MessageVersion.Soap11WSAddressingAugust2004, "*", fruit);
MessageHeader mHeader
= MessageHeader.CreateHeader("FruitHeader", "http://www.cnblogs.com/qiuwuyu",
 
new FruitHeader("password"));
message1.Headers.Add(mHeader);
using (FileStream stream = new FileStream("FruitMessageHeader.xml", FileMode.Create))
{
using (XmlWriter xw = XmlDictionaryWriter.CreateTextWriter(stream))
{
message1.WriteMessage(xw);
}
}
//创建一个没有消息版本,并用文本编码的消息
Message message = Message.CreateMessage(MessageVersion.None, "*", new XmlNodeReader(xmlDoc));
using (FileStream stream = new FileStream("FruitMessageNone.xml", FileMode.Create))
{
using (XmlWriter xw = XmlDictionaryWriter.CreateTextWriter(stream))
{
message.WriteMessage(xw);
}
}
}
}
}

XmlDictionary是定义了一个私有的可以表示SOAP消息中元素名字、属性和XML namespace声明的key-value列表的字典结构。字典在常见文本字符串和整数之间建立映射,并为压缩和解压缩XML提供一种有效机制。XmlDictionaryWriter是WCF中一个优化的读取XML编写器。

执行上述代码后,查看生成文件。

Fruit.xml文件:

WCF之消息

二进制编码的Fruit.xml文件:

WCF之消息

MTOM编码的Fruit.xml文件:

WCF之消息

文本编码的消息:

WCF之消息

无消息版本信息本文本编码的消息:

WCF之消息

下面看一个直接用Message写的小实例,从整体上感觉下。

服务契约:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using FruitModel;

namespace IFruitService
{
[ServiceContract(Namespace
= "http://www.cnblogs.com/qiuwuyu")]
public interface IFruitPriceService
{
[OperationContract(Action
="*",ReplyAction="*")]
Message GetFruit(Message m);
}
}
Action指定为“*”表示可以处理服务端接收到的任何消息。如果没有指定Action值,则默认为服务约定命名空间/约定名称(默认为接口名称)/操作名称(默认为方法名称)。
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using IFruitService;
using FruitModel;

namespace FruitPriceService
{
public class FruitPriceService : IFruitPriceService
{
public Message GetFruit(Message m)
{
if ( OperationContext.Current.IncomingMessageHeaders.GetHeader<FruitHeader>(0).HeaderKey!="password" )
{
FaultCode faultCode
= new FaultCode("Invalid Key");
return Message.CreateMessage(m.Version, faultCode, "Invalid Key", "*");
}
return Message.CreateMessage(m.Version, "*", new Fruit("banana", "6.00"));
}
}
}

相关文章: