在本篇文章中,我们将通过一个具体的实例来演示如何通过路由服务。在这个例子中,我们会创建连个简单的服务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: &