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

Posted on 2009-12-17 22:49 Frank Xu Lei 阅读(84) 评论(0)   编辑 收藏 网摘 所属分类: 《WCF技术内幕》翻译, SOA and EAI

                 WS-Addressing 和MessageHeaders类型

EndpointAddress类型

AddressHeader类型

序列化一个EndpointAddress对象

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规范。

老徐的博客
【作      者】:Frank Xu Lei
【地      址】:http://www.cnblogs.com/frank_xl/
【中文论坛】:微软WCF中文技术论坛
【英文论坛】:微软WCF英文技术论坛

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值