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

今天介绍WCF 4.0的另外两个新特性:标准终结点(Standard Endpoint)和无(.SVC)文件服务激活(File-Less Activation)。前者实现了针对典型通信场景对终结点的定制,后者让你在进行IIS/WAS的服务寄宿中无须定义.svc文件。

一、标准终结点

我们知道,绑定的本质就是一系列相关绑定元素的有序集合,而系统绑定就是基于若干典型的通信场景对相关绑定元素的整合。WCF通过系统绑定对绑定元素进行了定制,那么能否在终结点级别对组成该终结点的ABC(地址、绑定和契约)也进行相应的定制呢?实际上这对于最新版本的WCF是可行的,我们将这个机制称为“标准终结点”。

所谓标准终结点,就是针对典型的通信场景选择组成终结点的要素(主要是绑定和契约)进而创建出一个标准的终结点。在使用的时候,如果你需要的终结点要素和标准终结点完全一致,就无需进行重复的设置;如果不一致,则只需要单独对此进行重新设置以覆盖定义在标准终结点的默认设置。

比如说,对于用于发布元数据的终结点总是将IMetadataExchange作为其契约,并且在大部分情况下使用MexHttpBinding。如果我们基于这两个元素创建一个标准的MexEndpoint,那么在为服务配置发布元数据的终结点的时候就只需要指定地址就可以了。实际上,WCF确实为我们创建了这么一个标准的MexEndpoint终结点。包含MexEndpoint终结点在内,WCF总共为我们定义了如下面的列表所示的9个标准终结点。

  • mexEndpoint:用于公开服务元数据的标准终结点;
  • dynamicEndpoint:使用 WS-Discovery 在运行时动态查找终结点地址的标准终结点;
  • discoveryEndpoint:由服务用于发送发现消息的标准终结点;
  • udpDiscoveryEndpoint:通过 UDP 多播绑定为发现操作预配的标准终结点;
  • announcementEndpoint:由服务用于发送公告消息的标准终结点;
  • udpAnnouncementEndpoint:由服务用于通过 UDP 绑定发送公告消息的标准终结点;
  • workflowControlEndpoint:可用于对工作流实例调用控制操作的标准终结点;
  • webHttpEndpoint:带有自动添加 WebHttpBehavior行为的WebHttpBinding绑定的标准终结点;
  • webScriptEndpoint:带有自动添加 WebScriptEnablingBehavior行为的WebHttpBinding绑定的标准终结点。

如果你希望直接为某个服务配置一个标准终结点,可以借助于WCF4.0为终结点的配置节添加的一个新的配置属性kind,该属性表示标准终结点名称。在上面的配置中,我为服务配置了一个标准终结点mexEndpoint以实现基于MEX终结点形式的元数据发布。

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <system.serviceModel>
   4:     ...
   5:     <services>      
   6:       <service name="Artech.WcfServices.Service.CalculatorService" >
   7:         <host>
   8:           <baseAddresses>
   9:             <add baseAddress="http://127.0.0.1:3721/calculatorservice"/>
  10:           </baseAddresses>
  11:         </host>
  12:         <endpoint binding="ws2007HttpBinding" contract="Artech.WcfServices.Contract.ICalculator" />
  13:         <endpoint kind="mexEndpoint" address="mex"/>
  14:       </service>
  15:     </services>  
  16:   </system.serviceModel>
  17: </configuration>

对于系统绑定来说,WCF允许你通过配置的方式对其进行定制,标准终结点也不例外。如果标准的终结点默认配置不能满足你的要求,你可以在配置中对其进行相应的定制。在WCF配置节下添加了一个新的子结点<standardEndpoints>,用于对这9个标准终结点进行定制。和自定义绑定一样,你需要为自定义的标准终结点起一个名字。如果某个终结点需要使用到自定义的标准终结点,标准终结点的名称需要设置到终结点配置节的另一个额外的配置属性endpointConfiguration上。

在下面的配置中,我们自定义了一个基于WS-Discovery 1.1的udpDiscoveryEndpoint,并起名为“wsd11”。而这个标准终结点通过终结点配置节的两个属性kind(kind="udpDiscoveryEndpoint")和endpointConfiguration(endpointConfiguration="wsd11")被添加到寄宿的CalculatorService服务的终结点列表中。

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <system.serviceModel>
   4:     <services>      
   5:       <service name="Artech.WcfServices.Service.CalculatorService" >
   6:         <endpoint address="http://127.0.0.1:3721/calculatorservice" binding="ws2007HttpBinding" contract="Artech.WcfServices.Contract.ICalculator" />
   7:         <endpoint kind="udpDiscoveryEndpoint" endpointConfiguration="wsd11"/>
   8:       </service>
   9:     </services>
  10:     <standardEndpoints>
  11:       <udpDiscoveryEndpoint>
  12:         <standardEndpoint name="wsd11" discoveryVersion="WSDiscovery11"/>
  13:       </udpDiscoveryEndpoint>
  14:     </standardEndpoints>
  15:   </system.serviceModel>
  16:   ...
  17: </configuration>

二、无.svc文件服务激活

我们都知道,在采用IIS/WAS进行服务寄宿的情况下,我们需要为寄宿的服务创建一个.svc文件。在通常的情况下(当然你也可以以内联的形式将整个服务类型也定义其中),我们仅仅在该.svc文件中定义基本的<%@ServiceHost%>指令信息。其中最重要的指令信息自然是通过Service属性指定的寄宿服务的类型(实际上调用ServiceHostFactory的CreateServieHost方法传入的第一个参数值)。如果采用自定义ServiceHost,我们还需要定义用于创建ServiceHost的ServiceHostFactory的类型(通过Factory属性)。

在《通过自定义ServiceHost实现对WCF的扩展[实例篇]》中,我们介绍了如何通过自定义ServiceHost的方式实现WCF与Unity这个IoC框架进行集成。我们为此创建了自定义的ServiceHost(UnityServiceHost)和相应的ServiceHostFactory(UnityServiceHostFactory)。下面就是采用了UnityServiceHostFactory这个自定义ServiceHostFactory创建的.svc的内容。

   1: <%@ ServiceHost Service="Artech.WcfServices.Servicies.ResourceService: defaultContainer" 
   2: Factory="Artech.WcfExtensions.IoC.UnityServiceHostFactory, Artech.WcfExtensions"%>

从消息交换的角度来说,客户端对IIS/WAS寄宿下服务的调用本质上体现在对.svc这个真实存在的物理文件的访问。如果服务尚未激活,WCF最终根据读取请求的物理文件来激活相应的服务。具体来说,就是获取用于创建ServiceHost的ServiceHostFactory的类型(如果没有通过<%@ServiceHost%>指令的Factory进行显式设置,默认使用的ServiceHostFactory的类型为System.ServiceModel.Activation.ServiceHostFactory)。在正确解析出ServiceHostFactory类型之后,通过反射创建用于寄宿服务的ServiceHost对象。

如果WCF的服务端能够根据请求正确地创建出基于目标服务的ServiceHost,就能解决服务的激活问题。进一步来说,如果服务端能够维护一个Service/ServiceHostFactory与请求地址之间的映射关系,我们就可以不再需要.svc文件,因为.svc对于服务激活来说就是起到了这么一个映射的作用。在最新的WCF中,这么一个映射关系可以在配置文件中进行设置。换言之,如果在配置对这个映射关系进行了相应设置之后,我们将不再需要为服务定义了.svc文件了。

在<system.serviceModel>/<serviceHostingEnvironment>配置节下,具有一个<serviceActivations>子节点。上述的关于Service/ServiceHostFactory与请求地址之间的映射关系就定义在这个配置节点下。具体来说,<serviceActivations>配置节下的配置元素具有三个基本的属性,其中service和factory对用着原来定义在.svc文件中<%@ServiceHost>指令的Service和Factory属性,而relativeAddress则表示服务相对服务寄宿的IIS站点的地址,该地址必须以.svc为后缀。下面一段配置与上面给出的.svc文件具有相同的作用,有了这段配置,.svc就不再需要了。

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:     <system.serviceModel>   
   4:       ...
   5:       <serviceHostingEnvironment>
   6:         <serviceActivations>
   7:           <add relativeAddress="ResourceService.svc" 
   8:                service="Artech.WcfServices.Servicies.ResourceService: defaultContainer" 
   9:                factory="Artech.WcfExtensions.IoC.UnityServiceHostFactory, Artech.WcfExtensions"/>
  10:         </serviceActivations>
  11:       </serviceHostingEnvironment>
  12:     </system.serviceModel>
  13: </configuration>

再举个例子,如何我们需要通过IIS的方式来寄宿我们熟悉的CalculatorService,在不需要定义.svc的情况下,下面的XML片断代表了所需的最少配置。借助于默认终结点(《[WCF 4.0新特性] 默认终结点》)的自动添加机制,WCF会为寄宿服务实现的每个服务契约针对于每一个基地址添加一个终结点。由于通过配置属性relativeAddress定义的地址就是服务的相对基地址,所以基于这个地址的终结点回自动添加。

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:     <system.serviceModel>        
   4:       <serviceHostingEnvironment>
   5:         <serviceActivations>
   6:           <add service="Artech.WcfServices.Service.CalculatorService" relativeAddress="OrderService.svc"/>
   7:         </serviceActivations>
   8:       </serviceHostingEnvironment>
   9:     </system.serviceModel>
  10: </configuration>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏王亚昌的专栏

路由查找算法优化心得

    项目代码中有一个基础类库,用于解析client到server的路由配置文件,同时管理长连接。路由配置文件格式大致如下所示:

1022
来自专栏技术随笔

[Linux] 解压zip文件中文乱码问题解决

3538
来自专栏IT可乐

Nginx(三)------nginx 反向代理

  Nginx 服务器的反向代理服务是其最常用的重要功能,由反向代理服务也可以衍生出很多与此相关的 Nginx 服务器重要功能,比如后面会介绍的负载均衡。本篇博...

1463
来自专栏你不就像风一样

Java中用final修饰参数的方法当传入i++时异常

我的项目是这样写项目运行不起来,具体原因我参考的 https://www.cnblogs.com/xiohao/p/4861500.html, 解决方法...

1053
来自专栏玄魂工作室

看代码学安全(10)程序未恰当exit导致的问题

大家好,我们是红日安全-代码审计小组。最近我们小组正在做一个PHP代码审计的项目,供大家学习交流,我们给这个项目起了一个名字叫 PHP-Audit-Labs 。...

922
来自专栏王纯的专栏

Valgrind 使用入门

Valgrind 是一套类似于 gprof 的动态检测的工具集,由于使用方便,不需修改目标程序源码,输出清晰图文并茂等优势,常被用作后台(特别是linux后台)...

2K0
来自专栏Django Scrapy

Linux 目录结构及文件基本操作

win和类unix系统的文件目录的区别 一种不同是体现在目录与存储介质(磁盘,内存,DVD 等)的关系上,以往的 Windows 一直是以存储介质为主的,主要...

3156
来自专栏Linux驱动

22.Linux-块设备驱动之框架详细分析(详解)

本节目的:     通过分析块设备驱动的框架,知道如何来写驱动 1.之前我们学的都是字符设备驱动,先来回忆一下 字符设备驱动: 当我们的应用层读写(read()...

3925
来自专栏林冠宏的技术文章

Golang, 以17个简短代码片段,切底弄懂 channel 基础

(原创出处:https://cloud.tencent.com/developer/user/1148436/activities) 前序:   因为打算自己搞...

3805
来自专栏向治洪

MIDlet工作原理

题记 :  现在的J2ME用户已经是日益减少 , 开发也在转型! 无奈之下也不得不写下这系列文章来别了j2me ,也是对过去的一些总结吧!         ...

18310

扫码关注云+社区

领取腾讯云代金券