﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-TerryLee's Tech Space-随笔分类-[04]&amp;nbsp;&amp;nbsp;WCF后传</title><link>http://www.cnblogs.com/Terrylee/category/36734.html</link><description>TerryLee技术专栏</description><language>zh-cn</language><lastBuildDate>Thu, 20 Nov 2008 16:38:29 GMT</lastBuildDate><pubDate>Thu, 20 Nov 2008 16:38:29 GMT</pubDate><ttl>60</ttl><item><title>WCF后传系列（10）：消息处理功能核心</title><link>http://www.cnblogs.com/Terrylee/archive/2008/11/17/WCF-Messaging-Features-Core.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Mon, 17 Nov 2008 15:46:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/11/17/WCF-Messaging-Features-Core.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1335498.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/11/17/WCF-Messaging-Features-Core.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1335498.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1335498.html</trackback:ping><description><![CDATA[摘要: <div style="float:right;padding-right:5px;"><img src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/120066/o_wcf.png" alt=""/></div>WCF是一个通信框架，同时也可以将它看成是一个消息处理或者传递的基础框架，它可以接收消息、对消息做处理，或者根据客户端给定的数据构造消息并将消息发送到目标端点，在这个过程中，一切都是围绕“消息”而展开的。WCF在消息处理体系结构提供统一编程模型的同时，还允许灵活的表示数据和传递消息，本文将介绍如何配置消息支持各个SOAP和WS-Addressing版本或者不用任何SOAP和WS-Addressing，以及如何控制消息状态等。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2008/11/17/WCF-Messaging-Features-Core.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/1335498.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（9）：深度通道编程模型Part 2—实例篇</title><link>http://www.cnblogs.com/Terrylee/archive/2008/11/14/WCF-Channel-Programming-Model-Example.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Thu, 13 Nov 2008 16:22:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/11/14/WCF-Channel-Programming-Model-Example.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1333195.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/11/14/WCF-Channel-Programming-Model-Example.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1333195.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1333195.html</trackback:ping><description><![CDATA[<h2>引言</h2> <p>从本质上说，WCF是一个通信服务框架，它允许我们使用不同的传输协议，使用不同的消息编码形式，跟不同的WS-*系列规范交互，而所有这些细节都是由通道堆栈来处理的。在《<a href="http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html">WCF专题系列（8）：深度通道编程模型Part 1—设计篇</a>》中，对于WCF中的通道模型有了深入的认识，本文中，我将通过实例来说明在通道模型中，服务端是如何接收消息，客户端是如何发送消息的。  <h2>服务端通道</h2> <p>本文将不使用WCF的编程模型，而直接利用通道模型来进行通信，这样有助于我们更进一步加深对服务端处理消息的认识，在服务端侦听并接收消息的第一步需要创建绑定，我们既可以使用WCF中内置的绑定或者使用自定义的绑定，如下代码所示，创建一个CustomBinding：<pre class="code"><span style="color: green">// 创建自定义绑定
</span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();

<span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);</pre><a href="http://11011.net/software/vspaste"></a>
<p>此处添加了HttpTransportBindingElement，所以生成的通道堆栈具有HTTP传输通道，另外采用了文本消息编码器。接下来调用刚才创建的CustomBinding的BuildChannelListener方法来构造通道侦听器，需要指定侦听基地址以及绑定参数，另外调用Open()方法打开通道监听器，相信大家一定还记得Open()方法是在接口ICommunicationObject中定义的，如下代码所示：<pre class="code"><span style="color: green">// 使用自定义绑定创建通道侦听器         
</span><span style="color: #2b91af">IChannelListener</span>&lt;<span style="color: #2b91af">IReplyChannel</span>&gt; listener =
      binding.BuildChannelListener&lt;<span style="color: #2b91af">IReplyChannel</span>&gt;(
         <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>),
         <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());

<span style="color: green">// 监听消息
</span>listener.Open();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Listening for incoming channel connections"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<p>现在侦听传入的消息，由于我们使用请求了响应消息交换模式，此处侦听器返回一个实现了IReplyChannel的通道，为了在此通道上接收消息，我们首先对其调用Open()方法（该方法仍然是在ICommunicationObject中定义），以便将其置于一个准备进行通信的状态。 然后，我们调用ReceiveRequest()方法，它会处于阻止状态，直到消息达到，如下代码所示：<pre class="code"><span style="color: green">// 创建Reply通道
</span><span style="color: #2b91af">IReplyChannel </span>channel = listener.AcceptChannel();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel accepted. Listening for messages"</span>);
channel.Open();

<span style="color: #2b91af">RequestContext </span>request = channel.ReceiveRequest();</pre><a href="http://11011.net/software/vspaste"></a>
<p>当ReceiveRequest()方法返回一个RequestContext时，再使用其RequestMessage属性获取接收到的消息。输出消息的操作（Action）和内容。为了发送答复，在此例中创建一个新的答复消息，它会将我们在请求中接收到的字符串数据，添加一段字符后再传递回去。然后，调用Reply()方法以发送答复消息，如下代码所示：<pre class="code"><span style="color: green">// 读取请求的消息
</span><span style="color: #2b91af">Message </span>message = request.RequestMessage;
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Received"</span>);
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Action: {0}"</span>, message.Headers.Action);
<span style="color: blue">string </span>body = message.GetBody&lt;<span style="color: blue">string</span>&gt;();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Content: {0}"</span>, body);

<span style="color: green">// 发送响应消息
</span><span style="color: #2b91af">Message </span>replymessage = <span style="color: #2b91af">Message</span>.CreateMessage(
    binding.MessageVersion,
    <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
     <span style="color: #a31515">"Hello : " </span>+ body);

request.Reply(replymessage);</pre><a href="http://11011.net/software/vspaste"></a>
<p>最后别忘了做资源释放工作，关闭通道侦听器、通道、请求消息、请求上下文等，如下代码所示：<pre class="code"><span style="color: green">// 释放对象
</span>message.Close();
request.Close();
channel.Close();
listener.Close();</pre><a href="http://11011.net/software/vspaste"></a>
<p>完整的代码如下所示：<pre class="code"><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author:TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url:http://www.cnblogs.com/terrylee
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">static void </span>Main()
{
    <span style="color: green">// 创建自定义绑定
    </span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
    bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
    bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();

    <span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);

    <span style="color: green">// 使用自定义绑定创建通道侦听器         
    </span><span style="color: #2b91af">IChannelListener</span>&lt;<span style="color: #2b91af">IReplyChannel</span>&gt; listener =
          binding.BuildChannelListener&lt;<span style="color: #2b91af">IReplyChannel</span>&gt;(
             <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>),
             <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());

    <span style="color: green">// 监听消息
    </span>listener.Open();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Listening for incoming channel connections"</span>);

    <span style="color: green">// 创建Reply通道
    </span><span style="color: #2b91af">IReplyChannel </span>channel = listener.AcceptChannel();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel accepted. Listening for messages"</span>);
    channel.Open();

    <span style="color: #2b91af">RequestContext </span>request = channel.ReceiveRequest();

    <span style="color: green">// 读取请求的消息
    </span><span style="color: #2b91af">Message </span>message = request.RequestMessage;
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Received"</span>);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Action: {0}"</span>, message.Headers.Action);
    <span style="color: blue">string </span>body = message.GetBody&lt;<span style="color: blue">string</span>&gt;();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Message Content: {0}"</span>, body);

    <span style="color: green">// 发送响应消息
    </span><span style="color: #2b91af">Message </span>replymessage = <span style="color: #2b91af">Message</span>.CreateMessage(
        binding.MessageVersion,
        <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
         <span style="color: #a31515">"Hello : " </span>+ body);

    request.Reply(replymessage);

    <span style="color: green">// 释放对象
    </span>message.Close();
    request.Close();
    channel.Close();
    listener.Close();

    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Press Enter to exit"</span>);
    <span style="color: #2b91af">Console</span>.ReadLine();
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>现在运行服务端如图1所示，由于没有消息到达，所以ReceiveRequest()方法会阻塞： 
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="236" alt="TerryLee_WCF_31" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_31_3.png" width="561" border="0"> 
<p>图 1 
<h2>客户端通道</h2>
<p>前面完成了服务端的工作，接下来我们看看如何在客户端直接使用通道模型进行通信。与服务端一致，请求消息的第一步是创建绑定，因为双方需要通过绑定就通信的细节达成一致。创建自定义绑定与服务端一致，如下代码所示：<pre class="code"><span style="color: green">// 创建绑定
</span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();

<span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);</pre><a href="http://11011.net/software/vspaste"></a>
<p>接下来需要使用刚才创建的绑定来构造通道工厂，在上一篇中我们提到，消息的接收方使用通道侦听器，而消息的请求方使用通道工厂，这次使用BuildChannelFactory()方法构造通道工厂并打开，如下代码所示：<pre class="code"><span style="color: green">// 使用绑定创建通道工厂
</span><span style="color: #2b91af">IChannelFactory</span>&lt;<span style="color: #2b91af">IRequestChannel</span>&gt; factory =
binding.BuildChannelFactory&lt;<span style="color: #2b91af">IRequestChannel</span>&gt;(
                 <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());
<span style="color: green">// 打开通道工厂
</span>factory.Open();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel factory opened"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<p>现在使用通道工厂的CreateChannel()方法来创建IRequestChannel，得到通道后，调用它的Open()方法以使其处于通信就绪状态，如下代码所示：<pre class="code"><span style="color: green">// 创建Request通道
</span><span style="color: #2b91af">IRequestChannel </span>channel = factory.CreateChannel(
   <span style="color: blue">new </span><span style="color: #2b91af">EndpointAddress</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>));
channel.Open();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Request channel opened"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<p>打开通道之后，就可以创建消息并使用通道的 Request()方法发送请求并等待响应，这里我们发送的消息内容是“TerryLee”，当此方法返回时，我们将能够得到回复消息，可以读取该消息以发现终结点回复的内容，如下代码所示：<pre class="code"><span style="color: green">// 创建请求消息
</span><span style="color: #2b91af">Message </span>requestmessage = <span style="color: #2b91af">Message</span>.CreateMessage(
    binding.MessageVersion,
    <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
     <span style="color: #a31515">"TerryLee"</span>);

<span style="color: green">// 发送请求消息并接收响应消息
</span><span style="color: #2b91af">Message </span>replymessage = channel.Request(requestmessage);
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply message received"</span>);
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply action: {0}"</span>,
                      replymessage.Headers.Action);
<span style="color: blue">string </span>data = replymessage.GetBody&lt;<span style="color: blue">string</span>&gt;();
<span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply content: {0}"</span>, data);</pre><a href="http://11011.net/software/vspaste"></a>
<p>最后仍然是资源释放工作，关闭通道工厂、通道以及请求消息，如下代码所示：<pre class="code">replymessage.Close();
channel.Close();
factory.Close();</pre><a href="http://11011.net/software/vspaste"></a>
<p>完整的客户端代码为：<pre class="code"><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author:TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url:http://www.cnblogs.com/terrylee
</span><span style="color: gray">/// &lt;/summary&gt;
</span><span style="color: blue">public static void </span>Main()
{
    <span style="color: green">// 创建绑定
    </span><span style="color: #2b91af">BindingElement</span>[] bindingElements = <span style="color: blue">new </span><span style="color: #2b91af">BindingElement</span>[2];
    bindingElements[0] = <span style="color: blue">new </span><span style="color: #2b91af">TextMessageEncodingBindingElement</span>();
    bindingElements[1] = <span style="color: blue">new </span><span style="color: #2b91af">HttpTransportBindingElement</span>();

    <span style="color: #2b91af">CustomBinding </span>binding = <span style="color: blue">new </span><span style="color: #2b91af">CustomBinding</span>(bindingElements);

    <span style="color: green">// 使用绑定创建通道工厂
    </span><span style="color: #2b91af">IChannelFactory</span>&lt;<span style="color: #2b91af">IRequestChannel</span>&gt; factory =
    binding.BuildChannelFactory&lt;<span style="color: #2b91af">IRequestChannel</span>&gt;(
                     <span style="color: blue">new </span><span style="color: #2b91af">BindingParameterCollection</span>());
    <span style="color: green">// 打开通道工厂
    </span>factory.Open();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Channel factory opened"</span>);

    <span style="color: green">// 创建Request通道
    </span><span style="color: #2b91af">IRequestChannel </span>channel = factory.CreateChannel(
       <span style="color: blue">new </span><span style="color: #2b91af">EndpointAddress</span>(<span style="color: #a31515">"http://localhost:8887/StringService"</span>));
    channel.Open();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Request channel opened"</span>);

    <span style="color: green">// 创建请求消息
    </span><span style="color: #2b91af">Message </span>requestmessage = <span style="color: #2b91af">Message</span>.CreateMessage(
        binding.MessageVersion,
        <span style="color: #a31515">"http://www.cnblogs.com/TerryLee/Encode"</span>,
         <span style="color: #a31515">"TerryLee"</span>);

    <span style="color: green">// 发送请求消息并接收响应消息
    </span><span style="color: #2b91af">Message </span>replymessage = channel.Request(requestmessage);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply message received"</span>);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply action: {0}"</span>,
                          replymessage.Headers.Action);
    <span style="color: blue">string </span>data = replymessage.GetBody&lt;<span style="color: blue">string</span>&gt;();
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Reply content: {0}"</span>, data);

    replymessage.Close();
    channel.Close();
    factory.Close();

    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Press Enter to exit"</span>);
    <span style="color: #2b91af">Console</span>.ReadLine();
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>最后运行时服务端如图2所示： 
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="266" alt="TerryLee_WCF_33" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_33_3.png" width="580" border="0">&nbsp; <p>图 2 
<p>客户端如图3所示： 
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="280" alt="TerryLee_WCF_32" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_32_3.png" width="580" border="0"> 
<p>图 3 
<h2>温故知新</h2>
<p>现在我们再回顾一下<a href="http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html">上一篇</a>中所讲的知识，通道对象模型是实现通道、通道侦听器和通道工厂所必需的一组核心接口。还提供一些基类以辅助自定义实现。可以看到通道模型中最重要的有三组接口：通道、通道侦听器和通道工厂。每个通道均实现一个或多个接口，称为通道形状接口或通道形状；通道侦听器负责侦听传入消息，即在消息的接收端，然后通过由通道侦听器创建的通道将这些消息传送到上面的层；通道工厂负责创建通道用于发送消息，即在消息的发送方，并在通道工厂关闭时，关闭通道工厂创建的所有通道。如图4所示： 
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="381" alt="TerryLee_WCF_24" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF9Part2_243/TerryLee_WCF_24_3.png" width="494" border="0"> 
<p>图 4 
<p>对照本文的示例代码，相信大家对于图4能够有更深的认识。 
<h2>总结</h2>
<p>本文我们通过一个简单的示例介绍了在通道模型中服务端是如何接收消息以及客户端是如何发送消息的，希望对大家有所帮助。</p><img src ="http://www.cnblogs.com/Terrylee/aggbug/1333195.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（8）：深度通道编程模型Part 1—设计篇</title><link>http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Tue, 11 Nov 2008 14:36:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1331035.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html#Feedback</comments><slash:comments>35</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1331035.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1331035.html</trackback:ping><description><![CDATA[摘要: <div style="float:right;padding-right:5px;"><img src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/120066/o_wcf.png" alt=""/></div>从本质上说，WCF是一个通信服务框架，它允许我们使用不同的传输协议，使用不同的消息编码形式，跟不同的WS-*系列规范交互，而所有这些细节都是由通道堆栈来处理的。为了简化这些处理，在WCF中提供了两种模型，一是针对开发者的应用程序编程模型；二是用来通信的通道模型，这样对于开发者来说，只要了解应用程序编程模型就足够了，而不会涉及到通道模型，然而，对于通道模型进行必要的学习，可以让我们真正理解WCF中“通信”概念，了解WCF的 整个架构体系，从而构建出更加健壮的WCF服务或者对WCF框架进行扩展。在本文中，我们将进行深度了解WCF中的通道模型是如何设计的。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2008/11/11/WCF-Channel-Programming-Model-Design.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/1331035.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（7）：消息如何传递之绑定Part 2</title><link>http://www.cnblogs.com/Terrylee/archive/2008/11/06/WCF-Binding-Elements.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Thu, 06 Nov 2008 15:56:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/11/06/WCF-Binding-Elements.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1328513.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/11/06/WCF-Binding-Elements.html#Feedback</comments><slash:comments>16</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1328513.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1328513.html</trackback:ping><description><![CDATA[摘要: <div style="float:right;padding-right:5px;"><img src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/120066/o_wcf.png" alt=""/></div>在WCF专题系列（6）：消息如何传递之绑定Part 1一文中，我提到绑定由绑定元素组成，每个绑定元素用来描述终结点与客户端通信方式中的某个方面，在发送或接收消息时，每个绑定元素都表示一个处理步骤；运行时，绑定元素会创建必要的通道和侦听器，用以生成传出和传入通道堆栈。本文为消息如何传递之绑定第二部分，将详细介绍WCF内置的各种绑定元素，绑定元素之间的顺序以及如何创建一个自定义的绑定元素。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2008/11/06/WCF-Binding-Elements.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/1328513.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（6）：消息如何传递之绑定Part 1</title><link>http://www.cnblogs.com/Terrylee/archive/2008/11/05/WCF-Binding-Overview.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Wed, 05 Nov 2008 14:44:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/11/05/WCF-Binding-Overview.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1327676.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/11/05/WCF-Binding-Overview.html#Feedback</comments><slash:comments>22</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1327676.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1327676.html</trackback:ping><description><![CDATA[摘要: <div style="float:right;padding-right:5px;"><img src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/120066/o_wcf.png" alt=""/></div>每个服务终结点都包含一个地址Address、一个绑定Binding 和一个契约Contract。契约指定可用的操作，绑定指定如何与服务进行通信，而地址指定查找服务的位置，在WCF专题系列前5篇中，深入了解了WCF中寻址的细节；从本文开始，将深入了解经典“ABC”中的B，即绑定Binding，了解它的原理，如何使用绑定通信以及在元数据中如何公开。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2008/11/05/WCF-Binding-Overview.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/1327676.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（5）：深入WCF寻址Part 5—逻辑地址和物理地址</title><link>http://www.cnblogs.com/Terrylee/archive/2008/10/31/WCF-Addressing-ListenUri-and-EndpointAddress.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Thu, 30 Oct 2008 16:16:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/10/31/WCF-Addressing-ListenUri-and-EndpointAddress.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1323370.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/10/31/WCF-Addressing-ListenUri-and-EndpointAddress.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1323370.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1323370.html</trackback:ping><description><![CDATA[摘要: <div style="float:right;padding-right:5px;"><img src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/120066/o_wcf.png" alt=""/></div>在WCF中，每个服务终结点都与两个地址相关联，一个逻辑地址和一个物理地址，逻辑地址就是SOAP消息的目标地址，即前面不止一次提到的“To”地址，而物理地址是WCF侦听器真正监听的地址。在WCF中，逻辑地址称之为终结点地址Endpoint Address，而物理地址则称之为监听地址ListenUri。

本文将详细介绍WCF中的物理地址和逻辑地址，以及如何使用tcpTrace来进行SOAP消息的跟踪。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2008/10/31/WCF-Addressing-ListenUri-and-EndpointAddress.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/1323370.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（4）：深入WCF寻址Part 4—自定义消息筛选器</title><link>http://www.cnblogs.com/Terrylee/archive/2008/10/30/WCF-Addressing-Part3-Customize-Message-Filter.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Wed, 29 Oct 2008 16:44:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/10/30/WCF-Addressing-Part3-Customize-Message-Filter.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1322616.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/10/30/WCF-Addressing-Part3-Customize-Message-Filter.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1322616.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1322616.html</trackback:ping><description><![CDATA[摘要: <div style="float:right;padding-right:5px;"><img src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/120066/o_wcf.png" alt=""/></div>在WCF专题系列（3）：深入WCF寻址Part 3—消息过滤引擎一文中，详细介绍了WCF中的消息筛选引擎，包括消息筛选器和筛选器表，每个EndpointDispatcher都包含了两个消息筛选器，默认的地址过滤器是EndpointAddressMessageFilter，默认的契约过滤器是ActionMessageFilter，这些是可以通过Behavior来改变的。本文我们将学习如何创建一个自定义的消息过滤器，并通过自定义Behavior来改变EndpointDispatcher的默认过滤器。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2008/10/30/WCF-Addressing-Part3-Customize-Message-Filter.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/1322616.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（3）：深入WCF寻址Part 3—消息过滤引擎</title><link>http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Mon, 27 Oct 2008 15:58:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1320874.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1320874.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1320874.html</trackback:ping><description><![CDATA[摘要: <div style="float:right;padding-right:5px;"><img src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/120066/o_wcf.png" alt=""/></div>通过前面两篇的介绍，对Web服务寻址规范以及在WCF开发中终结点地址有了深入的认识。本文我们继续深入WCF寻址第三部分内容，当消息传入时，如何来确定匹配的终结点，就是我们本文要讲到的消息筛选引擎，在WCF中，消息筛选器引擎包括两个重要的组成部分：筛选器和筛选器表。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/1320874.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（2）：深入WCF寻址Part 2—自定义寻址报头</title><link>http://www.cnblogs.com/Terrylee/archive/2008/10/26/WCF-Addressing-part2.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Sun, 26 Oct 2008 07:52:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/10/26/WCF-Addressing-part2.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1319852.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/10/26/WCF-Addressing-part2.html#Feedback</comments><slash:comments>24</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1319852.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1319852.html</trackback:ping><description><![CDATA[<h2>概述</h2> <p>在<a href="http://www.cnblogs.com/Terrylee/archive/2008/10/25/wcf-addressing-part1.html">WCF专题系列（1）：深入WCF寻址Part1</a>一文中，我们对Web服务寻址规范做了一些认识，了解了终结点引用和消息信息报头两种结构，该规范在Web服务中的地位举足轻重，后续我们会经常提到该规范。在本文中，我们将继续深入WCF寻址的内容，包括元数据中的终结点地址，自定义寻址标头等相关信息。  <h2>终结点地址定义</h2> <p>了解了Web服务寻址规范，再回到WCF，在WCF中，终结点地址是由EndpointAddress类来表示的，它其中很重要的几个部分是：一个表示服务地址的统一资源定位符 (URI)，一个表示服务的安全标识的 Identity 和一个可选的 Headers 集合，其中Headers用于标识终结点或与终结点交互的更多详细寻址信息。如图1所示： <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="190" alt="TerryLee_WCF_02" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF2WCFPart2_DD41/TerryLee_WCF_02_3.png" width="496" border="0">&nbsp;&nbsp; <p>图1  <p>记的我在<a href="http://www.cnblogs.com/Terrylee/archive/2008/10/25/wcf-addressing-part1.html">WCF专题系列（1）：深入WCF寻址Part1</a>一文提到过，每个终结点引用都可以包含一些添加额外标识信息的引用参数，即寻址标头，在 WCF 中，将这些引用参数建模为 AddressHeader 类的实例，这里的Headers属性就是这些实例的集合，可以通过AddressHeader类提供的静态方法CreateAddressHeader来创建一个AddressHeader实例，如下代码所示： <pre class="code"><span style="color: #2b91af">AddressHeader </span>header = <span style="color: #2b91af">AddressHeader</span>.CreateAddressHeader(<span style="color: #a31515">"basic"</span>,
                        <span style="color: #a31515">"http://www.cnblogs.com/terrylee"</span>, <span style="color: #a31515">"Terrylee"</span>);</pre><a href="http://11011.net/software/vspaste"></a>
<h2>指定终结点地址</h2>
<p>在WCF中提供了基址技术，这使的我们在指定终结点地址时可以酌情选用相对地址或者绝对地址，指定绝对地址的方法是在终结点定义中提供完全限定的地址，如下代码所示： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
         <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;

  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/CalculatorService</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">basicHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<p>使用绝对地址固然简单，但是如果我们的服务需要公开多个终结点，而这些终结点地址又具有相同的基地址时，也许相对地址是更好的选择。在创建服务宿主对象时，提供一个基地址，如下代码所示： <pre class="code"><span style="color: blue">using </span>(<span style="color: #2b91af">ServiceHost </span>calculatorServiceHost =
        <span style="color: blue">new </span><span style="color: #2b91af">ServiceHost</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">CalculatorService</span>),
        <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/CalculatorService"</span>)))
{
    calculatorServiceHost.Opened += <span style="color: blue">delegate
    </span>{
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Service begin to listen via the Address:{0}"</span>,
            calculatorServiceHost.BaseAddresses[0].ToString());
    };

    calculatorServiceHost.Open();
    <span style="color: #2b91af">Console</span>.Read();
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>又或者同时在配置文件中指定基地址，这样就无须在每个终结点中指定绝对地址了，如下代码所示： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
         <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/Calculator</span>"<span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">myservice1</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">basicHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">myservice2</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<p>但请注意，基址技术是为我们在配置终结点时提供了方便，客户端对它是毫无所知的，客户端看到的仍然是绝对地址，在打开服务宿主时，它会匹配所有的相对地址，从而为每个终结点提供相应的绝对地址，如上面的示例，可以在WSDL中看到： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">wsdl:service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">CalculatorService</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsdl:port </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">BasicHttpBinding_ICalculator</span>" <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">tns:BasicHttpBinding_ICalculator</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">soap:address </span><span style="color: red">location</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/Calculator/myservice1</span>" <span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">wsdl:port</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsdl:port </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">WSHttpBinding_ICalculator</span>" <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">tns:WSHttpBinding_ICalculator</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">soap12:address </span><span style="color: red">location</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/Calculator/myservice2</span>" <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;</span>http://localhost:8887/Calculator/myservice2<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Identity </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://schemas.xmlsoap.org/ws/2006/02/addressingidentity</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Upn</span><span style="color: blue">&gt;</span>TerryLee-PC\TerryLee<span style="color: blue">&lt;/</span><span style="color: #a31515">Upn</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">Identity</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">wsdl:port</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">wsdl:service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<p>如果在指定了基地址的情况下，有以下几种情况：指定相对地址为空，终结点地址与基地址相同；指定相对地址不为空，追加相对地址到基地址上；指定一个绝对地址，基地址不起作用，终结点地址仍然为指定的绝对地址；指定一个绝对地址和一个与基地址不同的绑定，基地址不起作用。现在有这样一段配置信息： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
         <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/Calculator</span>"<span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>""
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">myservice2</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8886/CalculatorService</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>"<span style="color: blue">net.tcp://localhost:8885/Calculator</span>"
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">netTcpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<p>可以在ServiceHost启动后，输出所有的终结点地址和绑定信息，如下代码： <pre class="code"><span style="color: #2b91af">ServiceDescription </span>desc = calculatorServiceHost.Description;
<span style="color: blue">foreach </span>(<span style="color: #2b91af">ServiceEndpoint </span>endpoint <span style="color: blue">in </span>desc.Endpoints)
{
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Endpoint - address:  {0}"</span>, endpoint.Address);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"           binding:  {0}"</span>, endpoint.Binding.Name);
    <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"           contract: {0}"</span>, endpoint.Contract.Name);
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>输出结果如图2所示：
<p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="314" alt="TerryLee_WCF_05" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF2WCFPart2_DD41/TerryLee_WCF_05_3.png" width="580" border="0">&nbsp;&nbsp; <p>图2 
<h2>元数据中终结点地址</h2>
<p>终结点地址在WSDL中表示为对应终结点的 wsdl:port元素内的终结点引用（EndpointReference）元素。终结点引用包含终结点的地址以及所有的地址属性，如下示例代码所示： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">wsdl:service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">CalculatorService</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsdl:port </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">WSHttpBinding_ICalculator</span>" <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">tns:WSHttpBinding_ICalculator</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">soap12:address </span><span style="color: red">location</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/Calculator</span>" <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;</span>http://localhost:8887/Calculator<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Identity </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://schemas.xmlsoap.org/ws/2006/02/addressingidentity</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Upn</span><span style="color: blue">&gt;</span>TerryLee-PC\TerryLee<span style="color: blue">&lt;/</span><span style="color: #a31515">Upn</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">Identity</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">wsdl:port</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">wsdl:service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<h2>自定义寻址报头</h2>
<p>在本文的终结点定义一节，我们提到了寻址报头，在某些情况下，我们可能希望通过自定义寻址报头来解决一些复杂的问题，如根据根据传入的寻址报头中是否包含某些信息，将其转发到不同的终结点，通过自定义寻址报头，可以实现SOAP消息的无限扩展，放置任何希望的控制信息到SOAP消息。如下面的代码： <pre class="code"><span style="color: blue">using </span>(<span style="color: #2b91af">ServiceHost </span>calculatorServiceHost =
    <span style="color: blue">new </span><span style="color: #2b91af">ServiceHost</span>(<span style="color: blue">typeof</span>(<span style="color: #2b91af">CalculatorService</span>),
    <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/CalculatorService"</span>)))
{
    calculatorServiceHost.Opened += <span style="color: blue">delegate
    </span>{
        <span style="color: #2b91af">Console</span>.WriteLine(<span style="color: #a31515">"Service begin to listen via the Address:{0}"</span>,
            calculatorServiceHost.BaseAddresses[0].ToString());
    };

    <span style="color: #2b91af">AddressHeader </span>header =
        <span style="color: #2b91af">AddressHeader</span>.CreateAddressHeader(<span style="color: #a31515">"basic"</span>,
        <span style="color: #a31515">"http://www.cnblogs.com/terrylee"</span>, <span style="color: #a31515">"Terrylee"</span>);

    <span style="color: #2b91af">EndpointAddress </span>ea = <span style="color: blue">new </span><span style="color: #2b91af">EndpointAddress</span>(
        <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"http://localhost:8887/CalculatorService"</span>), header);

    calculatorServiceHost.Description.Endpoints.Add(
        <span style="color: blue">new </span><span style="color: #2b91af">ServiceEndpoint</span>(
            <span style="color: #2b91af">ContractDescription</span>.GetContract(<span style="color: blue">typeof</span>(<span style="color: #2b91af">ICalculator</span>)),
            <span style="color: blue">new </span><span style="color: #2b91af">WSHttpBinding</span>(),
            ea));

    <span style="color: #2b91af">ServiceMetadataBehavior </span>behavior = <span style="color: blue">new </span><span style="color: #2b91af">ServiceMetadataBehavior</span>();
    behavior.HttpGetEnabled = <span style="color: blue">true</span>;
    calculatorServiceHost.Description.Behaviors.Add(behavior);

    calculatorServiceHost.Open();
    <span style="color: #2b91af">Console</span>.Read();
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>我们在WSDL中可以看到该自定义的报头，它作为终结点引用的引用参数： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">wsdl:service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">CalculatorService</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsdl:port </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">WSHttpBinding_ICalculator</span>" <span style="color: red">binding</span><span style="color: blue">=</span>"<span style="color: blue">tns:WSHttpBinding_ICalculator</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">soap12:address </span><span style="color: red">location</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/CalculatorService</span>" <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;</span>http://localhost:8887/CalculatorService<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa10:Address</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">wsa10:ReferenceParameters</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">basic </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://www.cnblogs.com/terrylee</span>"<span style="color: blue">&gt;</span>Terrylee<span style="color: blue">&lt;/</span><span style="color: #a31515">basic</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">wsa10:ReferenceParameters</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">Identity </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://schemas.xmlsoap.org/ws/2006/02/addressingidentity</span>"<span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Upn</span><span style="color: blue">&gt;</span>TerryLee-PC\TerryLee<span style="color: blue">&lt;/</span><span style="color: #a31515">Upn</span><span style="color: blue">&gt;
      &lt;/</span><span style="color: #a31515">Identity</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">wsa10:EndpointReference</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">wsdl:port</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">wsdl:service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<p>截获到SOAP消息可以看到，在消息报头中添加了basic这样的信息，如下代码所示： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">s:Envelope </span><span style="color: red">xmlns:s</span><span style="color: blue">=</span>"<span style="color: blue">http://schemas.xmlsoap.org/soap/envelope/</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">basic </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://www.cnblogs.com/terrylee</span>"<span style="color: blue">&gt;</span>Terrylee<span style="color: blue">&lt;/</span><span style="color: #a31515">basic</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">To </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">&gt;</span>http://localhost:8887/CalculatorService<span style="color: blue">&lt;/</span><span style="color: #a31515">To</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Action </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">&gt;</span>http://tempuri.org/ICalculator/Add<span style="color: blue">&lt;/</span><span style="color: #a31515">Action</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Add </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://tempuri.org/</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">x</span><span style="color: blue">&gt;</span>1<span style="color: blue">&lt;/</span><span style="color: #a31515">x</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">y</span><span style="color: blue">&gt;</span>2<span style="color: blue">&lt;/</span><span style="color: #a31515">y</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Add</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">s:Envelope</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<p>当然我们也可以通过配置的方式来自定义寻址报头，如下代码所示： <pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">service </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Service.CalculatorService</span>"
         <span style="color: red">behaviorConfiguration</span><span style="color: blue">=</span>"<span style="color: blue">calculatorBehavior</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">add </span><span style="color: red">baseAddress</span><span style="color: blue">=</span>"<span style="color: blue">http://localhost:8887/Calculator</span>"<span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">baseAddresses</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">host</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">endpoint </span><span style="color: red">address</span><span style="color: blue">=</span>""
            <span style="color: red">binding </span><span style="color: blue">=</span>"<span style="color: blue">wsHttpBinding</span>"
            <span style="color: red">contract</span><span style="color: blue">=</span>"<span style="color: blue">TerryLee.WCFAddressing.Contract.ICalculator</span>"<span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">headers</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">basic </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://www.cnblogs.com/terrylee</span>"<span style="color: blue">&gt;</span>Terrylee<span style="color: blue">&lt;/</span><span style="color: #a31515">basic</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">headers</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">endpoint</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">service</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<h2>结束语</h2>
<p>本文相对于<a href="http://www.cnblogs.com/Terrylee/archive/2008/10/25/wcf-addressing-part1.html">WCF专题系列（1）：深入WCF寻址Part1</a>来说，注重于实际的使用，介绍了指定终结点地址、元数据中的终结点地址、自定义消寻址报头等，在下一篇中，我们将继续深入WCF寻址，探讨消息筛选器等问题。WCF寻址相关文章：</p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/31/WCF-Addressing-ListenUri-and-EndpointAddress.html">WCF专题系列（5）：深入WCF寻址Part 5—逻辑地址和物理地址</a> </p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/30/WCF-Addressing-Part3-Customize-Message-Filter.html">WCF专题系列（4）：深入WCF寻址Part 4—自定义消息筛选器</a> </p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html">WCF专题系列（3）：深入WCF寻址Part 3—消息过滤引擎</a> </p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/25/WCF-addressing-part1.html">WCF专题系列（1）：深入WCF寻址Part 1—Web服务寻址规范</a></p><img src ="http://www.cnblogs.com/Terrylee/aggbug/1319852.html?type=1" width = "1" height = "1" />]]></description></item><item><title>WCF后传系列（1）：深入WCF寻址Part 1—Web服务寻址规范</title><link>http://www.cnblogs.com/Terrylee/archive/2008/10/25/WCF-addressing-part1.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Fri, 24 Oct 2008 16:08:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2008/10/25/WCF-addressing-part1.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/1319127.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2008/10/25/WCF-addressing-part1.html#Feedback</comments><slash:comments>32</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/1319127.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/1319127.html</trackback:ping><description><![CDATA[<h2>概述</h2> <p>众所周知，WCF服务的所有通信都是通过服务的终结点发生的，每个 服务终结点都包含一个地址Address、一个绑定Binding 和一个契约Contract。契约指定可用的操作，绑定指定如何与服务进行通信，而地址指定查找服务的位置，即非常经典的“ABC”。WCF用多种不同的通信协议为公开服务终结点和与其通信提供了灵活的模式，在WCF专题系列的第一部分，我将围绕终结点的寻址细节展开讨论，再此之前，我们先看一下WCF的编程模型，如图1所示：  <p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="389" alt="TerryLee_WCF_01" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF1WCFPart1_EC2/TerryLee_WCF_01_5.png" width="447" border="0">  <p>图1  <h2>Web服务寻址规范</h2> <p>在 WCF 中，终结点地址是按照Web服务寻址 WS-Addressing 规范中的定义建立终结点引用（Endpoint Reference，EPR）的模型，我们有必要对Web服务寻址规范来做一个认识，这里先提出一个问题，为什么需要Web服务寻址？一方面SOAP如果要做到真正的与传输协议无关，就要以一种与传输协议无关的方式来定义消息的接收者与消息返回的地址；另一方面，定义寻址信息有助于在发生网络错误或丢失响应的情况下将消息返回给请求者；最后一套完善的寻址机制使的复杂的交互模式成为可能，如图2所示：  <p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="532" alt="TerryLee_WCF_04" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF1WCFPart1_EC2/TerryLee_WCF_04_3.png" width="532" border="0">  <p>图2  <p>在WS-Addressing中，其实就两个概念：终结点引用（Endpoint Reference）和SOAP结构的消息信息报头（Message Information Headers）。如下面的示例表示将一条SOAP 1.2的消息发送到http://fabrikam123.com/Purchasing。：<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">S:Envelope </span><span style="color: red">xmlns:S</span><span style="color: blue">=</span>"<span style="color: blue">http://www.w3.org/2002/12/soap-envelope</span>"
   <span style="color: red">xmlns:wsa</span><span style="color: blue">=</span>"<span style="color: blue">http://schemas.xmlsoap.org/ws/2003/03/addressing</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">S:Header</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">wsa:ReplyTo</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">wsa:Address</span><span style="color: blue">&gt;</span>http://business456.com/client1<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa:Address</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">wsa:ReplyTo</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">wsa:To</span><span style="color: blue">&gt;</span>http://fabrikam123.com/Purchasing<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa:To</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">wsa:Action</span><span style="color: blue">&gt;</span>http://fabrikam123.com/SubmitPO<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa:Action</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">S:Header</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">S:Body</span><span style="color: blue">&gt;
    </span>......
  <span style="color: blue">&lt;/</span><span style="color: #a31515">S:Body</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">S:Envelope</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<h2>终结点引用</h2>
<p>Web 服务终结点是一个可以引用的实体、处理器或可以作为 Web 服务消息目标的资源，而终结点引用传达了标识或者引用一个 Web 服务终结点所需的信息，它的使用方式可以有多种：终结点引用适用于传达访问 Web 服务终结点所需的信息，也可以在 Web 服务间往返的各条消息提供地址。如下面的代码表示了终结点引用的信息集：<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">wsa:EndpointReference</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsa:Address</span><span style="color: blue">&gt;xs:anyURI&lt;/</span><span style="color: #a31515">wsa:Address</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsa:ReferenceProperties</span><span style="color: blue">&gt;... &lt;/</span><span style="color: #a31515">wsa:ReferenceProperties</span><span style="color: blue">&gt; ?
  &lt;</span><span style="color: #a31515">wsa:ReferenceParameters</span><span style="color: blue">&gt;... &lt;/</span><span style="color: #a31515">wsa:ReferenceParameters</span><span style="color: blue">&gt; ?
  &lt;</span><span style="color: #a31515">wsa:PortType</span><span style="color: blue">&gt;xs:QName&lt;/</span><span style="color: #a31515">wsa:PortType</span><span style="color: blue">&gt; ?
  &lt;</span><span style="color: #a31515">wsa:ServiceName </span><span style="color: red">PortName</span><span style="color: blue">="xs:NCName"?&gt;xs:QName&lt;/</span><span style="color: #a31515">wsa:ServiceName</span><span style="color: blue">&gt; ?
  &lt;</span><span style="color: #a31515">wsa:Policies</span><span style="color: blue">&gt; ... &lt;/</span><span style="color: #a31515">wsa:Policies</span><span style="color: blue">&gt;?
  &lt;</span><span style="color: #a31515">xs:any</span><span style="color: blue">/&gt;*
&lt;/</span><span style="color: #a31515">wsa:EndpointReference</span><span style="color: blue">&gt;</pre><a href="http://11011.net/software/vspaste"></a></span>
<p>从最简单的意义上来说，终结点引用就是一些使用XML元素来包装的URL，如下面的代码：<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">wsa:myLocation</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">wsa:Address</span><span style="color: blue">&gt;http://localhost:8887/CalculatorService&lt;/</span><span style="color: #a31515">wsa:Address</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">wsa:myLocation</span><span style="color: blue">&gt;</pre><a href="http://11011.net/software/vspaste"></a></span>
<p>这里wsa:myLocation就是终结点引用，在它的内部是一个Web服务寻址规范定义的元素，用它来指定当访问CalculatorService服务时所用的地址。作为终结点引用模型的一部分，每个终结点引用都可以包含一些添加额外标识信息的引用参数。 
<h2>消息信息报头</h2>
<p>消息信息报头（Message Information Headers）是Web 服务寻址规范定义了一些附加的也是标准的SOAP头，它们用于帮助传送关于消息的信息，它与终结点引用不同，消息信息报头将作为SOAP Head的扩展包含在SOAP消息中，它的信息集如下所示：<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">wsa:To</span><span style="color: blue">&gt;xs:anyURI&lt;/</span><span style="color: #a31515">wsa:To</span><span style="color: blue">&gt; ?
&lt;</span><span style="color: #a31515">wsa:From</span><span style="color: blue">&gt;wsa:EndpointReferenceType&lt;/</span><span style="color: #a31515">wsa:From</span><span style="color: blue">&gt; ?
&lt;</span><span style="color: #a31515">wsa:ReplyTo</span><span style="color: blue">&gt;wsa:EndpointReferenceType&lt;/</span><span style="color: #a31515">wsa:ReplyTo</span><span style="color: blue">&gt; ?
&lt;</span><span style="color: #a31515">wsa:FaultTo</span><span style="color: blue">&gt;wsa:EndpointReferenceType&lt;/</span><span style="color: #a31515">wsa:FaultTo</span><span style="color: blue">&gt; ?
&lt;</span><span style="color: #a31515">wsa:Action</span><span style="color: blue">&gt;xs:anyURI&lt;/</span><span style="color: #a31515">wsa:Action</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">wsa:MessageID</span><span style="color: blue">&gt;xs:anyURI&lt;/</span><span style="color: #a31515">wsa:MessageID</span><span style="color: blue">&gt; ?
&lt;</span><span style="color: #a31515">wsa:RelatesTo </span><span style="color: red">RelationshipType</span><span style="color: blue">="xs:anyURI"?&gt;xs:anyURI&lt;/</span><span style="color: #a31515">wsa:RelatesTo</span><span style="color: blue">&gt; *
&lt;</span><span style="color: #a31515">wsa:ReferenceParameters</span><span style="color: blue">&gt;xs:any*&lt;/</span><span style="color: #a31515">wsa:ReferenceParameters</span><span style="color: blue">&gt; ?</pre><a href="http://11011.net/software/vspaste"></a></span>
<p>下面我们对其做一些解释： 
<p><b>To</b>：表示目标 Web 服务的 URL，当使用端点引用（EPR）时，To 头应该与 &lt;wsa:Address&gt; 元素具有相同的值。 
<p><b>From</b>：表示消息发送方的终结点引用，如果消息接收方需要向发送消息的终结点发送回消息，那么它应该使用这个终结点引用。 
<p><b>ReplyTo</b>：表示来自于Web服务的任何响应都应该被发送给ReplyTo终结点引用，即消息的发送方并不一定是要接收响应消息的终结点，这和From是有区别的。 
<p><b>FaultTo</b>：如果消息的响应是SOAP错误，那么这个错误应该在 FaultTo头中发送给终结点引用。 
<p><b>MessageID</b>：用来唯一的识别消息。 
<p><b>Action</b>：对于Action可以这么理解，当消息发送的服务时，指定如何处理该消息，更简单一点，就是希望服务调用哪个方法来处理消息。如下代码所示，希望消息到达服务时，调用Add方法来处理。<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">wsa:Action</span><span style="color: blue">&gt;</span>http://tempuri.org/ICalculator/Add<span style="color: blue">&lt;/</span><span style="color: #a31515">wsa:Action</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a>
<p><b>RelatesTo</b>：RelatesTo常用在响应消息中，用来指示它与先前知道的消息相关并且定义这种关系的URI。这在请求响应模式中非常关键，尤其是异步消息传递中，响应消息的接收方必须能够将它与原始请求消息相关联。 
<p>我们把消息信息报头Message Information Headers与SOAP用图3来清晰的表示： 
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="552" alt="TerryLee_WCF_03" src="http://www.cnblogs.com/images/cnblogs_com/Terrylee/WindowsLiveWriter/WCF1WCFPart1_EC2/TerryLee_WCF_03_5.png" width="400" border="0"> 
<p>图3 
<p>有关WS-Addressing规范的详细信息大家可以参考<a href="http://www.w3.org/Submission/ws-addressing/">http://www.w3.org/Submission/ws-addressing/</a>。 
<h2>分析WCF消息</h2>
<p>上面我介绍了Web服务寻址规范，现在我们截获一下WCF的消息，来看看它是如何符合WS-Addressing的。现在编写一个简单的WCF服务：<pre class="code"><span style="color: gray">/// &lt;summary&gt;
/// </span><span style="color: green">Author: TerryLee
</span><span style="color: gray">/// </span><span style="color: green">Url:http://www.cnblogs.com/terrylee
</span><span style="color: gray">/// &lt;/summary&gt;
</span>[<span style="color: #2b91af">ServiceContract</span>]
<span style="color: blue">public interface </span><span style="color: #2b91af">ICalculator
</span>{
    [<span style="color: #2b91af">OperationContract</span>]
    <span style="color: blue">int </span>Add(<span style="color: blue">int </span>x, <span style="color: blue">int </span>y);
}

<span style="color: blue">public class </span><span style="color: #2b91af">CalculatorService </span>: <span style="color: #2b91af">ICalculator
</span>{
    <span style="color: blue">public int </span>Add(<span style="color: blue">int </span>x, <span style="color: blue">int </span>y)
    {
        <span style="color: blue">return </span>x + y;
    }
}</pre><a href="http://11011.net/software/vspaste"></a>
<p>我们可以用跟踪诊断的方式来截获到SOAP消息，如下所示，可以看到这个调用服务过程中，消息报头中的To地址以及Action，这里的Action就是我们在服务中定义的Add方法，以及消息的Body：</p><span style="color: blue"><pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">s:Envelope </span><span style="color: red">xmlns:s</span><span style="color: blue">=</span>"<span style="color: blue">http://schemas.xmlsoap.org/soap/envelope/</span>"<span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">To </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">&gt;</span>http://localhost:8887/CalculatorService<span style="color: blue">&lt;/</span><span style="color: #a31515">To</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Action </span><span style="color: red">s:mustUnderstand</span><span style="color: blue">=</span>"<span style="color: blue">1</span>"<span style="color: blue">&gt;</span>http://tempuri.org/ICalculator/Add<span style="color: blue">&lt;/</span><span style="color: #a31515">Action</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Header</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">Add </span><span style="color: red">xmlns</span><span style="color: blue">=</span>"<span style="color: blue">http://tempuri.org/</span>"<span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">x</span><span style="color: blue">&gt;</span>1<span style="color: blue">&lt;/</span><span style="color: #a31515">x</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">y</span><span style="color: blue">&gt;</span>2<span style="color: blue">&lt;/</span><span style="color: #a31515">y</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">Add</span><span style="color: blue">&gt;
  &lt;/</span><span style="color: #a31515">s:Body</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">s:Envelope</span><span style="color: blue">&gt;</span></pre><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></span>
<h2>结束语</h2>
<p>Web服务寻址规范带来了Web服务世界的寻址标准，它通过定义终结点引用（Endpoint Reference）和消息信息报头（Message Information Headers）来提供了一种统一的机制。在下一篇中，我将继续深入分析WCF中的寻址，WCF寻址相关文章：</p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/31/WCF-Addressing-ListenUri-and-EndpointAddress.html">WCF专题系列（5）：深入WCF寻址Part 5—逻辑地址和物理地址</a> </p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/30/WCF-Addressing-Part3-Customize-Message-Filter.html">WCF专题系列（4）：深入WCF寻址Part 4—自定义消息筛选器</a> </p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/27/WCF-Addressing-Part3-Message-Filter.html">WCF专题系列（3）：深入WCF寻址Part 3—消息过滤引擎</a> </p>
<p><a href="http://www.cnblogs.com/Terrylee/archive/2008/10/26/WCF-Addressing-part2.html">WCF专题系列（2）：深入WCF寻址Part 2—自定义寻址报头</a> </p><img src ="http://www.cnblogs.com/Terrylee/aggbug/1319127.html?type=1" width = "1" height = "1" />]]></description></item><item><title>Windows Communication Foundation环境安装篇</title><link>http://www.cnblogs.com/Terrylee/archive/2006/12/18/Windows_Communication_Foundation_Setup.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Mon, 18 Dec 2006 15:38:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2006/12/18/Windows_Communication_Foundation_Setup.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/596278.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2006/12/18/Windows_Communication_Foundation_Setup.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/596278.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/596278.html</trackback:ping><description><![CDATA[摘要: .NET Framework 3.0发布有一段时间了，惫懒的我是不是也该动手学习点新东西呢？那就先从WCF开始吧。WCF（Windows Communication Foundation）作为.NET Framework 3.0的一部分，随着Windows Vista一起而Release，但是并不是说只有在Windows Vista下才可以使用WCF。除了Vista之外的操作系统要安装WCF的开发环境，需要具备如下条件：<br><br>1．  操作系统：Windows XP或者Windows 2003<br><br>2．  由于WCF构建于.NET Framework 2.0之上，所以需要安装.NET Framework 2.0。<br><br>3．  下载安装.NET Framework 3.0<br><br>Microsoft .NET Framework 3.0 Redistributable Package<br><br>4．使用Visual Studio 2005开发，还需要下载VS2005扩展<br><br>Microsoft Visual Stud&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2006/12/18/Windows_Communication_Foundation_Setup.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/596278.html?type=1" width = "1" height = "1" />]]></description></item><item><title>微软发布WF教程及大量示例</title><link>http://www.cnblogs.com/Terrylee/archive/2006/12/05/Tutorials_And_Samples_for_Windows_Workflow_Foundation.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Tue, 05 Dec 2006 04:55:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2006/12/05/Tutorials_And_Samples_for_Windows_Workflow_Foundation.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/582704.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2006/12/05/Tutorials_And_Samples_for_Windows_Workflow_Foundation.html#Feedback</comments><slash:comments>32</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/582704.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/582704.html</trackback:ping><description><![CDATA[摘要: 继前面微软公司发布Windows Communication Foundation (WCF)和Windows CardSpace的示例程序之后，微软今天又发布了WF的教程和大量示例，对于学习WF的朋友来说，是一份很好的学习资料。下载包括教程和示例两个压缩包，在示例部分包括如下的Application：<br><br>下载地址：<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c1863e23-482c-4b79-9f3c-417a92d8d1d9&DisplayLang=en">http://www.microsoft.com/downloads/details.aspx?FamilyID=c1863e23-482c-4b79-9f3c-417a92d8d1d9&DisplayLang=en</a><br>&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2006/12/05/Tutorials_And_Samples_for_Windows_Workflow_Foundation.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/582704.html?type=1" width = "1" height = "1" />]]></description></item><item><title>深入学习Web Service系列之异步开发模式</title><link>http://www.cnblogs.com/Terrylee/archive/2005/12/05/290845.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Mon, 05 Dec 2005 04:05:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2005/12/05/290845.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/290845.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2005/12/05/290845.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/290845.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/290845.html</trackback:ping><description><![CDATA[摘要: 在本篇随笔中，通过一些简单的示例来说一下Web Service中的异步调用模式。<br>概述<br>客户端异步调用方法<br>服务端使用Soap One-Way方法<br>服务端使用WSE SoapSender和SoapRecevier<br>服务端使用WSE 自定义SoapMSMQ传输&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2005/12/05/290845.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/290845.html?type=1" width = "1" height = "1" />]]></description></item><item><title>使用.NET Remoting开发分布式应用——基于租约的生存期</title><link>http://www.cnblogs.com/Terrylee/archive/2005/11/28/285809.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Mon, 28 Nov 2005 00:47:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2005/11/28/285809.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/285809.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2005/11/28/285809.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/285809.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/285809.html</trackback:ping><description><![CDATA[摘要: 知名类型的SingleCall对象可以在客户程序的方法调用之后被垃圾收集器清理掉，因为它没有保持状态，属于无状态的。而客户激活的类型的对象和知名类型的SingleTon对象都属于生存期长的对象，如果在客户程序停止使用远程对象之前，远程对象被禁用了，则客户程序会得到一个RemotingException异常。因为该对象已经和下一个方法调用（从客户程序进行的方法调用）断开了连接，只要客户程序需要该对象，它就必须被激活。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2005/11/28/285809.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/285809.html?type=1" width = "1" height = "1" />]]></description></item><item><title> 使用.NET Remoting开发分布式应用——配置文件篇 </title><link>http://www.cnblogs.com/Terrylee/archive/2005/11/17/278366.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Thu, 17 Nov 2005 02:09:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2005/11/17/278366.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/278366.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2005/11/17/278366.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/278366.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/278366.html</trackback:ping><description><![CDATA[摘要: 我们已经知道可以通过编码的方式配置服务器通道和远程客户机，除此之外，还可以使用配置文件对服务器通道和远程客户机进行配置。使用远程客户机和服务器对象的配置文件的优点在于，用户无需修改任何一行代码，也无需进行重新编译，便可以配置通道和远程对象。<br><br>.NET提供了Remoting配置文件的标准，基于XML格式。<br>&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2005/11/17/278366.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/278366.html?type=1" width = "1" height = "1" />]]></description></item><item><title>初识用.NET Remoting来开发分布式应用</title><link>http://www.cnblogs.com/Terrylee/archive/2005/11/03/267621.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Thu, 03 Nov 2005 00:34:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2005/11/03/267621.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/267621.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2005/11/03/267621.html#Feedback</comments><slash:comments>27</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/267621.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/267621.html</trackback:ping><description><![CDATA[摘要: .NET Remoting从某种意义上讲是DCOM的替代品。ASP.NET Web服务十分有用，但是这项技术在企业内联网的解决方案中，对于某些业务请求来说并不快，也没有足够的灵活性，而且，ASP.NET Web服务需要有运行时的支持。使用.NET Remoting技术后，可以将Web服务提供给世界上的任何地方。而且可以在所有的应用程序类型中运行Web服务。<br><br>点击<a href="http://Terrylee.cnblogs.com/archive/2005/11/03/267621.html"><font color=red>这里</font></a>阅读全文<br>&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2005/11/03/267621.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/267621.html?type=1" width = "1" height = "1" />]]></description></item><item><title> Web Services的魅力</title><link>http://www.cnblogs.com/Terrylee/archive/2005/09/29/246352.html</link><dc:creator>TerryLee</dc:creator><author>TerryLee</author><pubDate>Thu, 29 Sep 2005 00:36:00 GMT</pubDate><guid>http://www.cnblogs.com/Terrylee/archive/2005/09/29/246352.html</guid><wfw:comment>http://www.cnblogs.com/Terrylee/comments/246352.html</wfw:comment><comments>http://www.cnblogs.com/Terrylee/archive/2005/09/29/246352.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/Terrylee/comments/commentRss/246352.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Terrylee/services/trackbacks/246352.html</trackback:ping><description><![CDATA[摘要: WebServices是当今最热门的企业级技术，越来越多的媒体热衷于谈论这个领域不断涌现的创新成果和各种联盟，已有的厂商纷纷宣布进入WebServices市场，新兴的公司则从一开始就打起了实施W...&nbsp;&nbsp;<a href='http://www.cnblogs.com/Terrylee/archive/2005/09/29/246352.html'>阅读全文</a><img src ="http://www.cnblogs.com/Terrylee/aggbug/246352.html?type=1" width = "1" height = "1" />]]></description></item></channel></rss>