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

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

对于最新版本的WCF编程人员来说,你也可以采用无配置的服务寄宿了,这主要得益于WCF提供的默认终结点机制。所谓默认终结点,顾名思义,就是在你尚未为寄宿的服务添加任何终结点的时候,WCF会自动根据服务的基地址(Base Address)为你创建一个或者多个默认的终结点。

我们举个简单的例子,现在我们具有一个服务叫做GreetingService的服务,它实现了两个服务契约IHello和IGoodbye。下面的代码片断提供了服务类型GreetingService和服务契约接口的定义。

   1: [ServiceContract]
   2: public interface IHello
   3: {
   4:     [OperationContract]
   5:     void SayHello(string name);
   6: }
   7: [ServiceContract]
   8: public interface IGoodbye
   9: {
  10:     [OperationContract]
  11:     void SayGoodbye(string name);
  12: }
  13: public class GreetingService : IHello, IGoodbye 
  14: {
  15:     public void SayHello(string name)
  16:     {
  17:         //省略实现
  18:     }
  19:     public void SayGoodbye(string name)
  20:     {
  21:         //省略实现
  22:     }
  23: }

现在我们创建一个简单的控制台程序作为服务的宿主,在不提供任何配置文件的情况下调用如下的代码对服务进行自我寄宿。当用于寄宿服务的ServiceHost被开启之后,打印出其具有的终结点信息。

   1: Uri baseHttpAddress = new Uri("http://127.0.0.1/greetingservice ");
   2: Uri baseTcpAddress = new Uri("net.tcp://127.0.0.1/greetingservice ");
   3: ServiceHost host = new ServiceHost(typeof(GreetingService), baseHttpAddress, baseTcpAddress);
   4: host.Open();
   5: int index = 0;
   6: foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
   7: {
   8:     Console.WriteLine("Endpoint {0}",++index);
   9:     Console.WriteLine("\tAddress: {0}\n\tBinding: {1}\n\tContract: {2}",
  10:         endpoint.Address, endpoint.Binding, endpoint.Contract.Name);
  11: }

输出结果:

   1: Endpoint 1
   2:         Address: http://127.0.0.1/greetingservice
   3:         Binding: System.ServiceModel.BasicHttpBinding
   4:         Contract: IHello
   5: Endpoint 2
   6:         Address: http://127.0.0.1/greetingservice
   7:         Binding: System.ServiceModel.BasicHttpBinding
   8:         Contract: IGoodbye
   9: Endpoint 3
  10:         Address: net.tcp://127.0.0.1/greetingservice
  11:         Binding: System.ServiceModel.NetTcpBinding
  12:         Contract: IHello
  13: Endpoint 4
  14:         Address: net.tcp://127.0.0.1/greetingservice
  15:         Binding: System.ServiceModel.NetTcpBinding
  16:         Contract: IGoodbye

从输出的结果我们不难看出,虽然我们没有以任何形式为寄宿的服务提供终结点,但是WCF会自动为之添加四个默认的终结点。之所以是四个默认终结点,其原因在于:WCF会为服务实现的每一个服务契约基于指定的每一个基地址创建一个终结点。在本例中,服务GreetingService实现了两个服务契约,在寄宿过程中又为它指定了两个基地址,所以最终被自动创建的默认终结点是四个。对于自动创建的终结点,其地址和服务契约分别来源于指定的基地址和服务实现的契约,那么采用的绑定又是如何确定的呢?

一、默认终结点的绑定是如何确定的?

从上面的例子我们可以看到,对于自动创建的四个默认终结点,如果采用基于HTTP协议的地址,则采用BasicHttpBinding作为其终结点绑定;如果地址是基于TCP协议的,作为终结点绑定的则为NetTcpBinding。所以说定义在基地址中用以表示传输协议的前缀(Scheme)最终决定了采用的绑定类型。

但是,为什么基于HTTP协议的地址采用BasicHttpBinding,而不是WSHttpBinding或者WS2007HttpBinding呢?实际上,基地址的协议类型和最终作为默认终结点的类型之间的匹配关系是通过配置决定的。在<system.serviceModel>配置节中具有一个名为<protocolMapping>的子结点。它包含了一系列用以定义传输协议类型(scheme)和绑定类型匹配关系的配置元素。

如果你打开基于.NET Framework 4.0的配置文件machine.config.comments(该配置文件所在的目录为%Windows%Microsoft.NET\Framework\v4.0.30319\Config),你会发现<protocolMapping>配置节具有如下的定义。具体来说,<protocolMapping>配置节定义了四种传输协议(HTTP、TCP、Named

Pipe和MSMQ)和对应的绑定类型(BasicHttpBinding、NetTcpBiding、NetNamedPipeBinding和NetMsmqBinding)之间的匹配关系。这实际代表了默认的协议绑定映射关系,这也是为什么在上面的例子中基于HTTP协议的默认终结点会采用BasicHttpBinding作为绑定类型的原因。除了scheme和binding这两个配置属性之外,<protocolMapping>的配置元素还具有另外一个额外的配置属性bindingConfiguration,表示对具体绑定配置的引用。

   1: <system.serviceModel>
   2:    <protocolMapping>
   3:       <add scheme="http" binding="basicHttpBinding" bindingConfiguration="" />
   4:       <add scheme="net.tcp" binding="netTcpBinding" bindingConfiguration=""/>
   5:       <add scheme="net.pipe" binding="netNamedPipeBinding" bindingConfiguration=""/>
   6:       <add scheme="net.msmq" binding="netMsmqBinding" bindingConfiguration=""/>
   7:    </protocolMapping>
   8:    ...
   9: </system.serviceModel>

如果默认的协议与绑定映射关系不满足具体应用场景的要求,你可以直接修改machine.config或者基于具体应用的App.config或者Web.config。比如,对于上面的例子,如果为之添加一个配置文件并进行如下的配置:将基于HTTP的绑定类型设置为WS2007HttpBinding。再次运行实例程序,将会发现默认创建的终结点类型发生了相应的改变。

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <system.serviceModel>
   4:     <protocolMapping>
   5:       <add scheme="http" binding="ws2007HttpBinding" />
   6:     </protocolMapping>
   7:   </system.serviceModel>
   8: </configuration>

输出结果

   1: Endpoint 1
   2:         Address: http://127.0.0.1/greetingservice
   3:         Binding: System.ServiceModel.WS2007HttpBinding
   4:         Contract: IHello
   5: Endpoint 2
   6:         Address: http://127.0.0.1/greetingservice
   7:         Binding: System.ServiceModel.WS2007HttpBinding
   8:         Contract: IGoodbye
   9: Endpoint 3
  10:         Address: net.tcp://127.0.0.1/greetingservice
  11:         Binding: System.ServiceModel.NetTcpBinding
  12:         Contract: IHello
  13: Endpoint 4
  14:         Address: net.tcp://127.0.0.1/greetingservice
  15:         Binding: System.ServiceModel.NetTcpBinding
  16:         Contract: IGoodbye

二、默认终结点是如何被添加的?

接下来我们来具体介绍默认终结点机制是如何实现的,具体来讲就是表示默认终结点的ServiceEndpoint对象是如何被添加到用于表示寄宿服务描述的ServiceDescription的终结点列表(对应于ServiceDescription的Endpoints属性)中的。要了解默认终结点自动添加的原理,需要涉及到WCF
4.0为ServiceHostBase添加的一个新方法:AddDefaultEndpoints。

   1: public abstract class ServiceHostBase : CommunicationObject, IExtensibleObject<ServiceHostBase>, IDisposable
   2: {
   3:     //其他成员
   4:     public virtual ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints();
   5: }

从方法名称我们不难看出,这个方法就是用于实现为ServiceHost添加默认终结点的。从上面给出的关于这个方法的定义我们可以知道这个方法是一个公有方法,可以在具体的服务寄宿应用中被直接调用。当这个方法被调用的时候,WCF会按照我们之前介绍的策略(为指定的每一个基地址和服务实现的契约的组合添加一个终结点,终结点绑定的类型决定于<protocolMapping>配置)进行默认终结点的添加。方法的返回值表示添加的默认终结点集合。

当ServiceHost在开启的时候,WCF会检验其Description熟悉表示的服务描述是否具有至少一个终结点。如果没有,在会自动调用这个AddDefaultEndpoints方法以添加默认的终结点。比如在下面的代码片断中,在开启ServiceHost之前调用AddServiceEndpoint方法添加了一个终结点,最终默认终结点将不会被添加,所以ServiceHost最终只会有一个唯一的终结点。

   1: Uri baseHttpAddress = new Uri("http://127.0.0.1/greetingservice ");
   2: Uri baseTcpAddress = new Uri("net.tcp://127.0.0.1/greetingservice ");
   3: ServiceHost host = new ServiceHost(typeof(GreetingService), baseHttpAddress, baseTcpAddress);
   4: host.AddServiceEndpoint(typeof(IHello), new WSHttpBinding(), "manuallyadded");
   5: host.Open();
   6: ...

输出结果:

   1: Endpoint 1
   2:         Address: http://127.0.0.1/greetingservice/manuallyadded
   3:         Binding: System.ServiceModel.WSHttpBinding
   4:         Contract: IHello

由于公有的AddDefaultEndpoints方法可以手工被调用,所以当你在调用AddServiceEndpoint方法之后再调用该方法,ServiceHost最终将会具有

   1: Uri baseHttpAddress = new Uri("http://127.0.0.1/greetingservice ");
   2: Uri baseTcpAddress = new Uri("net.tcp://127.0.0.1/greetingservice ");
   3: ServiceHost host = new ServiceHost(typeof(GreetingService), baseHttpAddress, baseTcpAddress);
   4: host.AddServiceEndpoint(typeof(IHello), new WSHttpBinding(), "manuallyadded");
   5: host.AddDefaultEndpoints();
   6: host.Open();
   7: ...

输出结果:

   1: Endpoint 1
   2:         Address: http://127.0.0.1/greetingservice/manuallyadded
   3:         Binding: System.ServiceModel.WSHttpBinding
   4:         Contract: IHello
   5: Endpoint 2
   6:         Address: http://127.0.0.1/greetingservice
   7:         Binding: System.ServiceModel.WS2007HttpBinding
   8:         Contract: IHello
   9: Endpoint 3
  10:         Address: http://127.0.0.1/greetingservice
  11:         Binding: System.ServiceModel.WS2007HttpBinding
  12:         Contract: IGoodbye
  13: Endpoint 4
  14:         Address: net.tcp://127.0.0.1/greetingservice
  15:         Binding: System.ServiceModel.NetTcpBinding
  16:         Contract: IHello
  17: Endpoint 5
  18:         Address: net.tcp://127.0.0.1/greetingservice
  19:         Binding: System.ServiceModel.NetTcpBinding
  20:         Contract: IGoodbye

 

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

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

参考资料:《A Developer's Introduction to Windows Communication Foundation 4

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

原文链接

时间: 2024-08-02 09:56:06

[WCF 4.0新特性] 默认终结点的相关文章

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

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

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

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

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

在本篇文章中,我们将通过一个具体的实例来演示如何通过路由服务.在这个例子中,我们会创建连个简单的服务HelloServie和GoodbyeService.假设客户端不能直接调用这两个服务,需要使用到路由服务作为两者之间的中介.整个消息路由的场景如下图所示,中间的GreetingService.svc就是代表路由服务,而两个目标服务则通过HelloServie.svc和GoodbyeService.svc表示.路由服务使用的消息筛选器EndpointAddressMessageFilter,即根据

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

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

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

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

MySQL5.0新特性教程 存储过程:第三讲

The New SQL Statements 新SQL语句 Variables 变量 在复合语句中声明变量的指令是DECLARE. (1) Example with two DECLARE statements 两个DECLARE语句的例子 WHILE ... END WHILE CREATE PROCEDURE p8 () BEGIN DECLARE a INT; DECLARE b INT; SET a = 5; SET b = 5; INSERT INTO t VALUES (a); SE

PHP 5昨天隆重推出--PHP 5/Zend Engine 2.0新特性

前言    今天突然想到PHP官方网站上一转,一眼就看到PHP5推出的通告.虽然以前看到过PHP5的预告,但还是仔细看了PHP 5/Zend Engine 2.0新特性一文,一股JAVA气息扑面而来...   特将该文试译出来,首发于CSDN网站,以飨读者. PHP 5/Zend Engine 2.0新特性徐唤春 译 sfwebsite@hotmail.comhttp://www.php.net/zend-engine-2.php 全新的对象模型PHP中的对象处理部分已完全重写,具有更佳的性能和

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

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

返璞归真 asp.net mvc (12) - asp.net mvc 4.0 新特性之移动特性

原文:返璞归真 asp.net mvc (12) - asp.net mvc 4.0 新特性之移动特性 [索引页][源码下载] 返璞归真 asp.net mvc (12) - asp.net mvc 4.0 新特性之移动特性 作者:webabcd 介绍asp.net mvc 之 asp.net mvc 4.0 新特性之移动特性 为不同的客户端提供不同的视图 手动重写 UserAgent,从而强制使用对应的视图 示例1.演示如何为不同的客户端提供不同的视图Global.asax.cs /* * 为