[WCF 4.0新特性] 路由服务[实例篇]

在本篇文章中,我们将通过一个具体的实例来演示如何通过路由服务。在这个例子中,我们会创建连个简单的服务HelloServie和GoodbyeService。假设客户端不能直接调用这两个服务,需要使用到路由服务作为两者之间的中介。整个消息路由的场景如下图所示,中间的GreetingService.svc就是代表路由服务,而两个目标服务则通过HelloServie.svc和GoodbyeService.svc表示。路由服务使用的消息筛选器EndpointAddressMessageFilter,即根据包含在消息中的目标地址来决定应该将请求消息转发给HelloServie.svc还是GoodbyeService.svc。[源代码从这里下载]

步骤一、构建解决方案

首先我们创建一个空的解决方案,并如下图所示添加三个项目并添加相应的引用。其中类库项目Service.Interface和Service分别用于定义服务契约和服务类型,而控制台项目Client用作为进行服务调用的客户端。

步骤二、定义服务

在Service.Interface项目中为两个服务创建服务契约接口:IHello和IGoodbye,两个接口定义如下。

   1: using System.ServiceModel;
   2: namespace Artech.RoutingServiceDemo.Service.Interface
   3: {
   4:     [ServiceContract(Namespace="http://www.artech.com/")]
   5:     public interface IHello
   6:     {
   7:         [OperationContract]
   8:         string SayHello(string userName);
   9:     }
  10:     [ServiceContract(Namespace = "http://www.artech.com/")]
  11:     public interface IGoodbye
  12:     {
  13:         [OperationContract]
  14:         string SayGoodbye(string userName);
  15:     }
  16: }

然后在Service项目中定义实现两个服务契约接口的服务类型:HelloService和GoodbyeService,具体定义如下。

   1: using Artech.RoutingServiceDemo.Service.Interface;
   2: namespace Service
   3: {
   4:     public class HelloService: IHello
   5:     {
   6:         public string SayHello(string userName)
   7:         {
   8:             return string.Format("Hello, {0}", userName);
   9:         }
  10:     }
  11:     public class GoodbyeService : IGoodbye
  12:     {
  13:         public string SayGoodbye(string userName)
  14:         {
  15:             return string.Format("Goodbye, {0}", userName);
  16:         }
  17:     }
  18: }

步骤三、寄宿目标服务和路由服务

我们将上面定义的两个服务HelloService和GoodbyeService,以及路由服务RoutingService寄宿在IIS下。为此,我们直接在IIS管理器中创建一个Web应用(起名为“RoutingServiceDemo”),其物理地址之上Service项目的根目录。然后,不要忘了将该项目的编译后的输出目录从默认的\bin\Debug\改为\bin。接下来在Service项目中添加一个Web.config, 并完成如下的配置。

   1: <configuration>
   2:     <system.serviceModel>
   3:         <behaviors>
   4:             <serviceBehaviors>
   5:                 <behavior name="routingBehavior">
   6:                     <routing filterTableName="greetingFilterTable" routeOnHeadersOnly="true" soapProcessingEnabled="true" />
   7:                 </behavior>
   8:             </serviceBehaviors>
   9:         </behaviors>
  10:         <services>
  11:             <service name="Service.HelloService">
  12:                 <endpoint binding="ws2007HttpBinding" contract="Artech.RoutingServiceDemo.Service.Interface.IHello" />
  13:             </service>
  14:             <service name="Service.GoodbyeService">
  15:                 <endpoint binding="ws2007HttpBinding" contract="Artech.RoutingServiceDemo.Service.Interface.IGoodbye" />
  16:             </service>
  17:             <service behaviorConfiguration="routingBehavior" name="System.ServiceModel.Routing.RoutingService">
  18:                 <endpoint binding="ws2007HttpBinding" contract="System.ServiceModel.Routing.IRequestReplyRouter" />
  19:             </service>
  20:         </services>
  21:       <client>
  22:         <endpoint name="helloService" address="http://127.0.0.1/RoutingServiceDemo/HelloService.svc" binding="ws2007HttpBinding" contract="*"/>
  23:         <endpoint name="goodbyeService" address="http://127.0.0.1/RoutingServiceDemo/GoodbyeService.svc" binding="ws2007HttpBinding" contract="*"/>
  24:       </client>
  25:       <routing>
  26:         <filters>
  27:           <filter name ="Address4HelloService" filterType ="EndpointAddress" filterData="http://127.0.0.1/RoutingServiceDemo/HelloService.svc"/>
  28:           <filter name ="Address4GoodbyeService" filterType ="EndpointAddress" filterData="http://127.0.0.1/RoutingServiceDemo/GoodbyeService.svc"/>
  29:         </filters>
  30:         <filterTables>
  31:           <filterTable name="greetingFilterTable">
  32:             <add filterName="Address4HelloService" endpointName="helloService"/>
  33:             <add filterName="Address4GoodbyeService" endpointName="goodbyeService"/>            
  34:           </filterTable>
  35:         </filterTables>
  36:       </routing> 
  37:       <serviceHostingEnvironment>
  38:         <serviceActivations>
  39:           <add relativeAddress="HelloService.svc" service="Service.HelloService"/>
  40:           <add relativeAddress="GoodbyeService.svc" service="Service.GoodbyeService"/>
  41:           <add relativeAddress="GrettingService.svc" service="System.ServiceModel.Routing.RoutingService, 
  42: System.ServiceModel.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  43:         </serviceActivations>
  44:       </serviceHostingEnvironment>
  45:     </system.serviceModel>
  46: </configuration>

我们对上述的这段配置进行一下简单的分析。首先,我们按照“无.svc文件服务激活”方式(《标准终结点与无(.SVC)文件服务激活》)对服务HelloService、GoodbyeService和路由服务RoutingService进行寄宿,它们的相对地址分别为HelloService.svc、GoodbyeService.svc和GreetingService.svc。它们都具有一个唯一的基于WS2007HttpBinding的终结点。由于我们需要路由服务采用请求/回复模式进行消息路由,我们将契约指定为IRequestReplyRouter。

   1: <configuration>
   2:     <system.serviceModel>        
   3:         <services>
   4:             <service name="Service.HelloService">
   5:                 <endpoint binding="ws2007HttpBinding" contract="Artech.RoutingServiceDemo.Service.Interface.IHello" />
   6:             </service>
   7:             <service name="Service.GoodbyeService">
   8:                 <endpoint binding="ws2007HttpBinding" contract="Artech.RoutingServiceDemo.Service.Interface.IGoodbye" />
   9:             </service>
  10:             <service behaviorConfiguration="routingBehavior" name="System.ServiceModel.Routing.RoutingService">
  11:                 <endpoint binding="ws2007HttpBinding" contract="System.ServiceModel.Routing.IRequestReplyRouter" />
  12:             </service>
  13:         </services>      
  14:       <serviceHostingEnvironment>
  15:         <serviceActivations>
  16:           <add relativeAddress="HelloService.svc" service="Service.HelloService"/>
  17:           <add relativeAddress="GoodbyeService.svc" service="Service.GoodbyeService"/>
  18:           <add relativeAddress="GrettingService.svc" service="System.ServiceModel.Routing.RoutingService, 
  19: System.ServiceModel.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  20:         </serviceActivations>
  21:       </serviceHostingEnvironment>
  22:       ...
  23:     </system.serviceModel>
  24: </configuration>

路由服务上应用了服务行为RoutingBehavior,配置在该行为上名称为greetingFilterTable的筛选器表定义如下。该筛选器表它具有两个基于EndpointAddressMessageFilter的消息筛选器,配置名称分别为“Address4HelloService”和“Address4GoodbyeService”,它们分别将目标服务HelloService和GoodbyeService的地址作为筛选条件。而这两个筛选器对应着指向目标服务的客户端终结点“helloService”和“goodbyeService”。

   1: <configuration>   
   2: <system.serviceModel>
   3:        <client>
   4:         <endpoint name="helloService" address="http://127.0.0.1/RoutingServiceDemo/HelloService.svc" binding="ws2007HttpBinding" contract="*"/>
   5:         <endpoint name="goodbyeService" address="http://127.0.0.1/RoutingServiceDemo/GoodbyeService.svc" binding="ws2007HttpBinding" contract="*"/>
   6:       </client>
   7:       <routing>
   8:         <filters>
   9:           <filter name ="Address4HelloService" filterType ="EndpointAddress" filterData="http://127.0.0.1/RoutingServiceDemo/HelloService.svc"/>
  10:           <filter name ="Address4GoodbyeService" filterType ="EndpointAddress" filterData="http://127.0.0.1/RoutingServiceDemo/GoodbyeService.svc"/>
  11:         </filters>
  12:         <filterTables>
  13:           <filterTable name="greetingFilterTable">
  14:             <add filterName="Address4HelloService" endpointName="helloService"/>
  15:             <add filterName="Address4GoodbyeService" endpointName="goodbyeService"/>            
  16:           </filterTable>
  17:         </filterTables>
  18:       </routing> 
  19:     </system.serviceModel>
  20: </configuration>

对于上述的配置,细心的读者也许发现一个特殊之处:定义在<client>配置节下的被路由服务使用的终结点的契约被设置成“*”(contract=”*”)。照理说,这里的契约应该设置成路由服务实现的服务契约System.ServiceModel.Routing.IRequestReplyRouter才对。但是你真的进行了如此的设置,因为将路由服务使用的客户端终结点契约设置成“*”是个强制性的规定。

步骤四、服务调用

由于调用服务的消息需要通过路由服务这个中介才能抵达真正的目标服务,所以客户端我们需要将路由服务的地址作为消息发送的目标地址。在这里,我们通过ClientViaBehavior这个终结点行为实现了物理地址(消息真正发送的目标地址)和逻辑地址(终结点地址)的分离,将消息发送给路由服务的地址:http://127.0.0.1/RoutingServiceDemo/GrettingService.svc。下面的XML片断代表整个客户端的配置,而ClientViaBehavior被定义成默认的终结点行为。

   1: <configuration>
   2:   <system.serviceModel>
   3:     <behaviors>
   4:       <endpointBehaviors>
   5:         <behavior>
   6:           <clientVia viaUri="http://127.0.0.1/RoutingServiceDemo/GrettingService.svc"/>
   7:         </behavior>
   8:       </endpointBehaviors>
   9:     </behaviors>
  10:     <client>
  11:       <endpoint name="helloService" 
  12:                 address="http://127.0.0.1/RoutingServiceDemo/HelloService.svc" 
  13:                 binding="ws2007HttpBinding" 
  14:                 contract="Artech.RoutingServiceDemo.Service.Interface.IHello"/>
  15:       <endpoint name="goodbyeService" 
  16:                 address="http://127.0.0.1/RoutingServiceDemo/GoodbyeService.svc" 
  17:                 binding="ws2007HttpBinding" 
  18:                 contract="Artech.RoutingServiceDemo.Service.Interface.IGoodbye"/>      
  19:     </client>
  20:   </system.serviceModel>
  21: </configuration>

借助于这样的配置,你可以按照传统的编程方式进行服务的调用,无需再考虑底层消息路由机制的存在。

   1: using (ChannelFactory<IHello> channelFactoryHello = new ChannelFactory<IHello>("helloService"))
   2: using (ChannelFactory<IGoodbye> channelFactoryGoodbye = new ChannelFactory<IGoodbye>("goodbyeService"))
   3: {
   4:     IHello helloProxy = channelFactoryHello.CreateChannel();
   5:     IGoodbye goodbyeProxy = channelFactoryGoodbye.CreateChannel();
   6:     Console.WriteLine(helloProxy.SayHello("Zhang San"));
   7:     Console.WriteLine(goodbyeProxy.SayGoodbye("Li Si"));
   8: }

输出结果:

   1: Hello, Zhang San
   2: Goodbye, Li Si

 

[WCF 4.0新特性] 路由服务[原理篇]

[WCF 4.0新特性] 路由服务[实例篇]

作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2024-11-02 16:44:43

[WCF 4.0新特性] 路由服务[实例篇]的相关文章

[WCF 4.0新特性] 路由服务[原理篇]

在一个典型的服务调用场景中,具有两个基本的角色,即服务的消费者和服务的提供者.从消息交换的角度讲前者一般是消息的最初发送者,而后者则是消息的最终接收者.在很多情况下,由于网络环境的局限,消息的最初发送者和最终接收者不能直接进行消息交换,这就需要一个辅助实现消息路由的中介服务,这就是我们接下来要介绍的路由服务. 目录 一.路由服务就是一个WCF服务       路由服务契约的定义       路由服务契约的定义 二.基于消息内容的路由策略       RoutingBehavior服务行为    

WCF 4.0新特性汇总[共12篇]

一.简化开发体验 默认终结点 默认绑定和行为配置 标准终结点与无(.SVC)文件服务激活 二.路由服务 路由服务[原理篇] 路由服务[实例篇] 三.服务发现 WCF-Discovery的协议基础:WS-Discovery 服务如何能被"发现" 客户端如何能够"探测"到可用的服务? 实例演示:如何利用服务发现机制实现服务的"动态"调用? 让服务自动发送上/下线通知[原理篇] 让服务自动发送上/下线通知[实例篇] 如何利用"发现代理&quo

[WCF 4.0新特性] 标准终结点与无(.SVC)文件服务激活

今天介绍WCF 4.0的另外两个新特性:标准终结点(Standard Endpoint)和无(.SVC)文件服务激活(File-Less Activation).前者实现了针对典型通信场景对终结点的定制,后者让你在进行IIS/WAS的服务寄宿中无须定义.svc文件. 一.标准终结点 我们知道,绑定的本质就是一系列相关绑定元素的有序集合,而系统绑定就是基于若干典型的通信场景对相关绑定元素的整合.WCF通过系统绑定对绑定元素进行了定制,那么能否在终结点级别对组成该终结点的ABC(地址.绑定和契约)也

[WCF 4.0新特性] 默认终结点

很多WCF的初学者是从之前的Web服务上转移过来的,他们非常怀念.asmx Web服务无配置的服务寄宿方式.你只需要在定义Web服务的时候再表示服务操作的方法上应用WebMethodAttribute特性就可以了,完全可以不需要手工进行相应的配置,因为Web服务运行时会自动为你添加默认的配置.但是对于WCF来说,在进行服务寄宿的时候,你必须以编程或者配置的方式为服务添加至少一个终结点,而终结点需要具备基本的ABC三要素. 对于最新版本的WCF编程人员来说,你也可以采用无配置的服务寄宿了,这主要得

[WCF 4.0新特性] 默认绑定和行为配置

对于传统的WCF配置系统,无论是绑定的配置还是行为(服务行为和终结点行为)都必须具有一个名称.而正是通过整个配置名称,它们才能被应用到目标对象(终结点或者服务)上.而在实际的项目开发中,绝大部分服务或者终结点都具有相同的绑定和行为,如果能够定义一种默认的绑定和行为,这无疑会简化我们的配置.WCF4.0为此提供了一个新的特性以支持默认绑定和行为的配置. 一. 默认绑定配置 在传统的配置方式下,如果我们需要对终结点的绑定(不论是系统绑定还是自定义绑定)进行定制,我们都需要配置一个"具名"的

AngularJS 2.0新特性有哪些_AngularJS

AngularJS已然成为Web应用开发世界里最受欢迎的开源JavaScript框架.自成立以来,见证其成功的是惊人的经济增长以及团体的支持与采用--包括个人开发者.企业.社区. Angular已经变成一个构建复杂单页面应用的客户端MVW框架(Model-View-Whatever).它在应用测试和应用编写方面都扮演重要角色,同时简化了开发过程. Angular目前的版本为1.3,该版本稳定,并被谷歌(框架维护者)用于支持众多应用(据估计,在谷歌有超过1600个应用运行于Angular1.2或1

MySQL 5.0新特性教程 存储过程:第一讲

mysql|存储过程|教程 作者:mysql AB;翻译:陈朋奕 Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了"存储过程.触发器.视图.信息架构视图",在此感谢译者陈朋奕的努力. 希望这本书能像内行专家那样与您进行对话,用简单的问题.例子让你学到需要的知识.为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示较大的实用例,在学习之前也许大家会认为这个用例很难,但是只要跟着

返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作

原文:返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作 [索引页][源码下载] 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作

ASP.NET4.0新特性

原文:ASP.NET4.0新特性 在以前试用VS2010的时候已经关注到它在Web开发支持上的一些变化了,为此我还专门做了一个ppt,当初是计划在4月12日那天讲的,结果因为莫名其妙的原因导致没有语音以致放弃在LiveMeeting上的这次讲课,也导致了本篇的产生. 新增了项目模板 在创建Web项目时可以看到增加了更多的Web项目模板在VS2008中对应的情况如下: 在新模板中有如下改进:基础MemberShip功能.在大多数网站和应用程序中需要进行认证,因此在新模板中增加了认证功能使得用户能在