您的位置:首页 > 其它

《WCF技术内幕》翻译29:第2部分_第5章_消息:使用消息头(下)

2009-12-17 22:49 429 查看

WS-Addressing 和MessageHeaders类型

在前面“MessageHeader类型”一节,我们已经学习了使用MessageHeader表一个WS-Addressing终结点。我们会很少手动编写代码来使用一个MessageHeader去表示WS-Addressing终结点,因为MessageHeaders类型定义了几个表示一个终结点引用的属性。换句话说,MessageHeaders定义了几个可以增加、修改和删除WS-Addressing消息头块的方法,并且这个是给Message实例设置消息头块的主要方法。
更确切地说,MessageHeaders类型定义了以下与终结点相关的属性:From, ReplyTo, FaultTo, and To。From、ReplyTo和FaultTo是EndpointAddress的属性。如前面提到的一样,EndpointAddress类型是对于WS-Addressing 终结点规范定义的CLR抽象。我们会在下一节里详细学习EndpointAddress类型。根据WS-Addressing规范里的定义,To是Uri类型的属性。
MessageHeaders类型同样定义了与其它WS-Addressing规范相关的属性。例如,Action、MessageId和RelatesTo属性映射到相似名字的WS-Addressing消息头块上。Action是String类型,而且非常简单。概括地说,当属性设置完毕,WS-Addressing Action也会在Message序列化的时候序列化。
MessageId和RelatesTo属性是UniqueId类型的,而且也很简单。UniqueId类型很像GUID,但是它借助重载的构造函数,可以使用其它类型。思考下面的代码:


UniqueId uniqueId = new UniqueId();


Console.WriteLine(uniqueId.ToString());


uniqueId = new UniqueId("myuniquevalue");


Console.WriteLine(uniqueId.ToString());
运行代码,产生以下输出:
urn:uuid:
myuniquevalue

注意UniqueId对象的值可以是GUID类型的值,也可以是任意String的值。这是个必要的功能,因为MessageId 和RelatesTo WS-Addressing消息头块是xs:Uri类型。换句话说,任何值都可以在这里替换。因为WCF遵循WS-Addressing规范,System.Guid不能表示这些属性。

EndpointAddress类型

EndpointAddress类型由两个功能:它可以方便地保存目标地址的信息,并且它是一个序列化WS-Addressing终结点到Message里的方式。换句换说,EndpointAddress类型是经常使用的API之一,但是它同样在Message序列化和反序列化里起着重要作用。
EndpointAddress包装了一个System.Uri对象。因此,所有的EndpointAddress构造函数某些形式上,都接受一个System.Uri参数。更进一步说,6个构造函数里有5个接受一个Uri参数,另外一个接受String参数。但是这个构造函数会从此String参数来构造一个Uri然后调用其它的一个构造函数。EndpointAddress这个特性使得类型更加好用,如下所示:
EndpointAddress address1 = new
EndpointAddress("http://wintellect.com/OrderStuff");
Console.WriteLine("Address1: {0}",address1.ToString());

EndpointAddress address2 = new EndpointAddress(
new Uri("http://wintellect.com/OrderStuff"));
Console.WriteLine("Address2: {0}", address2.ToString());

Console.WriteLine("address1 {0} address2",
(address1 == address2) ? "equals" : "does not equal");

运行代码,产生以下输出:
Address1: http://wintellect.com/OrderStuff Address2: http://wintellect.com/OrderStuff Address1 equals Address2

注意到ToString方法返回是Uri的String形式,而不是一个序列化的EndpointAddress。同样也看到2个构造函数创建了等价的EndpointAddress对象。(在EndpointAddress类型上的重载操作符为了相等性检查对象的内部状态。)
还有几个其它的重载构造函数接受一个AddressHeader、AddressHeaderCollection、EndpointIdentity和 XmlDictionaryReader类型的参数。最值得注意的是AddressHeader类型的参数,而这个就是我们接下来的内容。

AddressHeader类型

AddressHeader类型是CLR对于一个WS-Addressing参数的抽象,它简化在序列化之前,添加参数到Message的工作,同样也包括反序列化之后获取引用参数的值。当第一次接触AddressHeader类型的时候,可能会和MessageHeader类型
从对象模型角度来看,AddressHeader类型与Message和MessageHeader很相似,因为它也是一个抽象类型,并且定义了几个工厂方法,Write 和Get 方法。(MessageHeader没有定义Get方法。)AddressHeader类型里的这些方法是为了与Message 和MessageHeader保持一致性,但是不能保证重复。如果你愿意的话,我会把这些方法的实验任务留给你。

序列化一个EndpointAddress对象

当被Message 对象引用的时候,EndpointAddress非常有用。这经常是通过Message类型的Headers属性来完成。比如,我们可以实例化一个EndpointAddress并且赋值给Message的FaultTo属性。例如:

String uriValue = "http://wintellect.com/someService";
AddressHeader header = AddressHeader.CreateAddressHeader("ref param");
EndpointAddress address = new EndpointAddress(new Uri(uriValue),
new AddressHeader[1] { header }); // notice the use of the AddressHeader

Message myMessage = Message.CreateMessage(
MessageVersion.Soap12WSAddressing10, "urn:SomeAction", "Hello There");
myMessage.Headers.FaultTo = address;
Console.WriteLine(myMessage.ToString());
运行代码,产生以下输出:

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/
05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">urn:SomeAction</a:Action>
<a:FaultTo>
<a:Address>http://wintellect.com/someService</a:Address>
<a:ReferenceParameters>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
ref param
</string>
</a:ReferenceParameters>
</a:FaultTo>
</s:Header>
<s:Body>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
Hello There
</string>
</s:Body>
</s:Envelope>
<string a:IsReferenceParameter="true"
xmlns="http://schemas.microsoft.com/203/10/Serialization/">
ref param
</string>
</s:Header>
<s:Body>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
Hello There
</string>
</s:Body>
</s:Envelope>
注意到AddressHeader 赋值给WS-Addressing终结点的FaultTo属性。

因为WS-Addressing里的To消息头块是一个xs:uri,想知道如何在至关重要的消息头里使用EndpointAddress类型也很正常。正如你之前看到的,MessageHeaders的To属性接受一个System.Uri参数,所以我们不能使用EndpointAddress直接设置To属性。EndpointAddress 定义了ApplyTo实例方法来解决这个问题。ApplyTo方法接受一个Message类型的参数,并且把EndpointAddress的值赋值给Message,如下所示:

String uriValue = "http://wintellect.com/someService";

AddressHeader header = AddressHeader.CreateAddressHeader("ref param");
EndpointAddress address = new EndpointAddress(new Uri(uriValue),
new AddressHeader[1] { header }); // notice the use of the AddressHeader

Message myMessage = Message.CreateMessage(
MessageVersion.Soap12WSAddressing10, "urn:SomeAction", "Hello There");

address.ApplyTo(myMessage);
Console.WriteLine(myMessage);
运行代码,产生以下输出:

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:s="http://www.3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">urn:SomeAction</a:Action>
<a:To s:mustUnderstand="1">http://wintellect.com/someService</a:To>
<string a:IsReferenceParameter="true"
xmlns="http://schemas.microsoft.com/203/10/Serialization/">
ref param
</string>
</s:Header>
<s:Body>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
Hello There
</string>
</s:Body>
</s:Envelope>
注意到EndpointAddress(包括AddressHeader)赋值给Message对象,并且每个引用参数都符合WS-Addressing规范。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐