原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[编程篇]

对于WCF服务端元数据架构体系来说,通过MetadataExporter将服务的终结点导出成MetadataSet(参考《如何导出WCF服务的元数据》),仅仅是完成了一半的工作。被成功导出的以MetadataSet对象表示的元数据需要最终作为可被访问的网络资源发布出来,才能被服务消费者获取,进而有效地帮助他们进行服务调用。元数据的发布最终是通过ServiceMetadataBehavior这样一个服务行为实现的,我们先来认识一下ServiceMetadataBehavior

一、 元数据发布的实现者:ServiceMetadataBehavior

ServiceMetadataBehavior是一个实现了IServiceBehavior的服务行为,它实现了基于如下两种协议的元数据发布模式:

  • HTTP-GET:采用HTTP协议的Get操作,向元数据目标地址发送HTTP请求,并以查询字符串(QueryString)的形式表示相应的查询参数。元数据最终以HTTP回复的形式返回;
  • WS-MEX:元数据提供者按照WS-MEX规范创建终结点发布元数据,元数据消费者创建同样基于WS-MEX的终结点与之交互,并最终通过SOAP的形式获取元数据。关于WS-MEX,可以参考我的文章《元数据(Metadata)架构体系全景展现[WS标准篇]

我们首先通过如下得代码来看看ServiceMetadataBehavior的定义,ServiceMetadataBehavior实现IServiceBehavior接口,并将所有发布元数据的行为定义在ApplyDispatchBehavior方法中。

   1: public class ServiceMetadataBehavior : IServiceBehavior

   2: {

   3:    

   4:     //其他成员

   5:     void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters);

   6:     void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase);

   7:     void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase);

   8:  

   9:     public Uri ExternalMetadataLocation { get; set; }    

  10:  

  11:     //HTTP

  12:     public bool HttpGetEnabled { get; set; }

  13:     public Uri HttpGetUrl { get; set; }

  14:     public Binding HttpGetBinding { get; set; }

  15:  

  16:     //HTTPS

  17:     public bool HttpsGetEnabled { get; set; }

  18:     public Binding HttpsGetBinding { get; set; }

  19:     public Uri HttpsGetUrl { get; set; }

  20:  

  21:     public MetadataExporter MetadataExporter { get; set; }

  22: }

ServiceMetadataBehavior定义了一系列的属性用于控制具体的元数据发布行为,其中绝大部分是基于HTTP-GET发布模式的。ExternalMetadataLocation表示返回给客户端的一个外部元数据地址,可以是绝对地址,也可以是基于HttpGetUrl或者HttpsGetUrl表述的相对地址;基于HTTP-GET的元数据发布同时支持HTTP和HTTPS两种形式,Http(s)GetEnabled是控制是否允许基于HTTP(s)进行元数据发布的开关,Http(s)GetUrl和Http(s)GetBinding这指定了采用的地址和绑定;MetadataExporter属性表示的MetadataExporter对象用于进行元数据的导出,默认为WsdlExporter

你可以通过配置的方式来设置除MetadataExporter之外的所有ServiceMetadataBehavior的属性,此外,WCF还提供给你一些额外的配型项供你更好地控制元数据的发布行为。对于WCF的开发者或者实施者来说,当你没有一份完备的文档指导你进行基于服务行为或者终结点行为的配置时,你可以查看该行为对应的BehaviorExtensionElement的定义获取与该行为相关的所有配置信息。ServiceMetadataBehavior相关的配置项全部定义在ServiceMetadataPublishingElement中,下面给出了ServiceMetadataPublishingElement的定义:

   1: public sealed class ServiceMetadataPublishingElement : BehaviorExtensionElement

   2: {

   3:     //其他成员

   4:     public override Type BehaviorType { get; }

   5:     [ConfigurationProperty("externalMetadataLocation")]

   6:     public Uri ExternalMetadataLocation { get; set; }

   7:  

   8:     //HTTP

   9:     [ConfigurationProperty("httpGetEnabled", DefaultValue = false)]

  10:     public bool HttpGetEnabled { get; set; }

  11:     [ConfigurationProperty("httpGetUrl")]

  12:     public Uri HttpGetUrl { get; set; }

  13:     [StringValidator(MinLength=0), ConfigurationProperty("httpGetBinding", DefaultValue="")]

  14:     public string HttpGetBinding { get; set; }

  15:     [ConfigurationProperty("httpGetBindingConfiguration", DefaultValue=""), StringValidator(MinLength=0)]

  16:     public string HttpGetBindingConfiguration { get; set; }

  17:  

  18:     //HTTPS

  19:     [ConfigurationProperty("httpsGetEnabled", DefaultValue = false)]

  20:     public bool HttpsGetEnabled { get; set; }

  21:     [ConfigurationProperty("httpsGetUrl")]

  22:     public Uri HttpsGetUrl { get; set; }

  23:     [StringValidator(MinLength=0), ConfigurationProperty("httpsGetBinding", DefaultValue="")]

  24:     public string HttpsGetBinding { get; set; }

  25:     [StringValidator(MinLength=0), ConfigurationProperty("httpsGetBindingConfiguration", DefaultValue="")]

  26:     public string HttpsGetBindingConfiguration { get; set; }

  27:  

  28:     [ConfigurationProperty("policyVersion", DefaultValue="Default"), TypeConverter(typeof(PolicyVersionConverter))]

  29:     public PolicyVersion PolicyVersion { get; set; }

  30: }

通过对ServiceMetadataPublishingElement的定义我们可以看出:我们可以通过除MetadataExporter之外的所有ServiceMetadataBehavior的属性,还可以通过policyVersion配置向指定具体采用的WS-Policy的版本。下面是一个ServiceMetadataBehavior配置的例子:

   1: <?xml version="1.0" encoding="utf-8" ?>

   2: <configuration>

   3:     <system.serviceModel>

   4:         <services>

   5:             <service behaviorConfiguration="MetadataPublishBehavior" name=" Artech.Services.CalculatorService">

   6:                 <endpoint address="http://127.0.0.1:3721/calcuulatorservice"

   7:                     binding="basicHttpBinding" bindingConfiguration="" contract=" Artech.Contracts.ICalculator" />                

   8:             </service>

   9:         </services>

  10:  

  11:       <behaviors>

  12:         <serviceBehaviors>

  13:           <behavior name="MetadataPublishBehavior">

  14:             <serviceMetadata externalMetadataLocation="http://127.0.1/mex/calculatorservice"

  15:                 httpGetEnabled="true" httpGetUrl="http://127.0.0.1/calculatorservice/mex"

  16:                 httpsGetEnabled="true" httpsGetUrl="https://127.0.0.1/calculatorservice/mex"

  17:                 policyVersion="Policy15" />

  18:           </behavior>

  19:         </serviceBehaviors>

  20:       </behaviors>

  21: </system.serviceModel>

  22: </configuration>

如果你希望通过WS-MEX的方式进行元数据的发布,你需要为服务添加一个基于WS-MEX的终结点。基于WS-MEX的终结点和一般意义上的终结点一样由地址、绑定和契约三部分组成。其中,地址表示发布元数据的目标地址,而绑定和契约因为需要按照WS-MEX规范进行消息的交换,所以对绑定和契约具有特殊的要求。在具体对MEX终结点展开介绍之前,我们不妨先来看看如何通过配置的方式为服务添加MEX终结点:

   1: <?xml version="1.0" encoding="utf-8" ?>

   2: <configuration>

   3:     <system.serviceModel>

   4:         <services>

   5:             <service name="Artech.Services.CalculatorService">

   6:                 <endpoint address="http://127.0.0.1:3721/calcuulatorservice"

   7:                     binding="basicHttpBinding" bindingConfiguration="" contract="Artech.Contracts.ICalculator" />

   8:                 <endpoint address="http://127.0.0.1:3721/calcuulatorservice/mex"

   9:                     binding="mexHttpBinding" bindingConfiguration="" contract="IMetadataExchange" />               

  10:             </service>

  11:         </services> 

  12:     </system.serviceModel>

  13: </configuration>

二、MEX 终结点有何不同?

我们通过为服务添加基于WS-MEX的终结点(以下简称MEX终结点)实现支持WS-MEX的元数据发布方式。总的来说,MEX终结点和一般意思上的终结点并没有本质的不同,也是由地址、绑定和契约三要素构成。但是,为了支持WS-MEX规定的消息交换模式和请求/回复消息的结构,对契约和绑定具有一些特殊的要求,先来看看MEX终结点的契约。

1、MEX终结点的契约:IMetadataExchange

从上面给出的基于MEX终结点的配置中,我们可以看到该终结点的契约被配置成“IMetadataExchange”。实际上IMetadataExchange是WCF内部定义的一个特殊服务契约接口,定义在System.ServiceModel.Description命名空间下,下面是IMetadataExchange的定义:

   1: [ServiceContract(ConfigurationName = "IMetadataExchange", Name = "IMetadataExchange", Namespace = "http://schemas.microsoft.com/2006/04/mex")]

   2: public interface IMetadataExchange

   3: {

   4:      [OperationContract(Action = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get", ReplyAction = "http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse", AsyncPattern = true)]

   5:     IAsyncResult BeginGet(Message request, AsyncCallback callback, object state);

   6:     Message EndGet(IAsyncResult result);

   7:     [OperationContract(Action = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get", ReplyAction = "http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse")]

   8:     Message Get(Message request);

   9: }

从定义可以看出,IMetadataExchange实际上仅仅包含一个Get服务操作,其中Get方法是正常的同步模式服务操作,而BeginGet/EndGet是按照标准的异步操作模式对Get服务操作的定义(关于异步服务操作模式,在《WCF技术剖析(卷1)》的第4章有详细的介绍)。

进一步分析IMetadataExchange的定义,由于通过ServiceContractAttribute特性将ConfigurationName属性设定成“IMetadataExchange”,这也是为何在进行MEX终结点的配置的时候,契约可以直接配置成“IMetadataExchange”,而不是“System.ServiceModel.Description. IMetadataExchange”。

再来看看Get操作,通过OperationContractAttribute特性将Action和ReplyAction设置成了http://schemas.xmlsoap.org/ws/2004/09/transfer/Gethttp://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse,如果读者《元数据(Metadata)架构体系全景展现[WS标准篇]》WS-Transfer相关介绍还有印象的话,应该知道它们就是WS-Transfer Get请求和回复SOAP消息对应的Action的值。在介绍WS—MEX的时候,我们提到过WS-MEX支持两种形式的元数据获取方式:WS-Transfer Get操作请求和Get Metadata操作请求。从这里可以看出,WCF采用的是基于WS-Transfer Get操作的元数据请求方式。

2、MEX终结点的绑定:MetadataExchangeBindings

WCF专门为MEX终结点定制了一系列的绑定,以实现对不同的网络传输协议(HTTP、HTTPS、TCP或者Named Pipe)的支持。这些定制的MEX绑定定义在MetadataExchangeBindings静态类中,你可以通过相应CreateMexXxxBinding方法创建基于某种传输协议的绑定。MetadataExchangeBindings的定义如下:

   1: public static class MetadataExchangeBindings

   2: {

   3:     //其他成员

   4:     public static Binding CreateMexHttpBinding();

   5:     public static Binding CreateMexHttpsBinding();

   6:     public static Binding CreateMexTcpBinding();   

   7:     public static Binding CreateMexNamedPipeBinding(); 

   8: }

如果你采用编程的方式为服务添加MEX终结点,那么你可以直接借助MetadataExchangeBindings创建相应的MEX绑定。如果采用配置的方式,仅仅需要将终结点的binding配置成:mexHttpBinding、mexHttpsBinding、mexTcpBinding和mexNamedPipeBinding即可,具体配置可以参考下面:

   1: <?xml version="1.0" encoding="utf-8" ?>

   2: <configuration>

   3:     <system.serviceModel>

   4:         <services>

   5:             <service behaviorConfiguration="MetadataPublishBehavior" name=" Artech.Services.CalculatorService">

   6:                 <endpoint address="http://127.0.0.1:3721/calcuulatorservice"

   7:                     binding="basicHttpBinding" bindingConfiguration="" contract="Artech.Contracts.ICalculator" />                

   8:                 <endpoint address="http://127.0.0.1/calculatorservice/mex" binding="mexHttpBinding" contract="IMetadataExchange" />

   9:                 <endpoint address="https://127.0.0.1/calculatorservice/mex" binding="mexHttpsBinding" contract="IMetadataExchange" />

  10:                 <endpoint address="net.tcp://127.0.0.1/calculatorservice/mex"                    binding="mexTcpBinding" contract="IMetadataExchange" />

  11:                 <endpoint address="net.pipe://127.0.0.1/calculatorservice/mex"                    binding="mexNamedPipeBinding" contract="IMetadataExchange" />

  12:             </service>

  13:         </services>

  14:     </system.serviceModel>

  15: </configuration>

下一篇中,我们将会讨论ServiceMetadataBehavior在内部是如何实现基于HTTP-GET和WS-MEX两种协议的元数据发布的。

作者:Artech
出处:http://artech.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

WCF技术剖析之二十七: 如何将一个服务发布成WSDL[编程篇]的更多相关文章

  1. WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)

    原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序) 基于HTTP-GET的元数据发布方式与基于WS-MEX原理类似,但是ServiceMetad ...

  2. WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于WS-MEX的实现](提供模拟程序)

    原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于WS-MEX的实现](提供模拟程序) 通过<如何将一个服务发布成WSDL[编程篇]>的介绍我们知道了如何可以通过编程或者配 ...

  3. WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的?

    原文:WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的? 服务端只有抛出FaultException异常才能被正常地序列化成Fault消息,并实现向客户 ...

  4. WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]

    原文:WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-ME ...

  5. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框 ...

  6. WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇]

    原文:WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇] 在[上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常.在服务执行过 ...

  7. WCF技术剖析之二十一:WCF基本异常处理模式[中篇]

    原文:WCF技术剖析之二十一:WCF基本异常处理模式[中篇] 通过WCF基本的异常处理模式[上篇], 我们知道了:在默认的情况下,服务端在执行某个服务操作时抛出的异常(在这里指非FaultExcept ...

  8. WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

    原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码 ...

  9. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇] 通过<实现篇>对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding ...

随机推荐

  1. Maven导入时,Cannot change version of project facet Dynamic Web Module to 3.0.

    今天手贱,在eclipse里面把项目删掉了,重新maven导入时,报出Cannot change version of project facet Dynamic Web Module to 3.0. ...

  2. 【监控】使用probe对tomcat服务进行监控

    1.运行环境(博主本地) JDK:jdk1.6 Tomcat:tomcat7 OS:Windows10 2.下载 点击下载 3.安装运行 1.解压,将probe文件夹复制放进tomcat里面的weba ...

  3. [Swust OJ 801]--Ordered Fractions

    题目链接:http://acm.swust.edu.cn/problem/801/ Time limit(ms): 1000 Memory limit(kb): 10000   Description ...

  4. JavaSE学习总结第06天_Java语言基础2 & 面向对象1

      06.01 二维数组概述和格式1的讲解 二维数组概述:二维数组其实就是一个元素为一维数组的数组 格式1:数据类型[][] 变量名 = new 数据类型[m][n]; m表示这个二维数组有多少个一维 ...

  5. BZOJ 1631: [Usaco2007 Feb]Cow Party( 最短路 )

    这道题和蔡大神出的今年STOI初中组的第二题几乎一模一样... 先跑一遍最短路 , 再把所有边反向 , 再跑一遍 , 所有点两次相加的最大值即为answer --------------------- ...

  6. 初探响应式Web设计

    公司书柜有本<响应式Web设计:HTML5和CSS3实战>,大概就认真看了前面几章,后面大部分介绍css3(随便找本手册都可以了要你可用!) <响应式Web设计:HTML5和CSS3 ...

  7. HTML5 总结-Web存储-7

    HTML 5 Web 存储 在客户端存储数据 HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 ses ...

  8. FormView用法

    功能描述: 学生可以对相应学校机构进行投诉建议. form表单 class SuggestForm(forms.Form): TYPE_CHOICES = ( (0, u'学校'), (1, u'学院 ...

  9. XIV

    http://publib.boulder.ibm.com/infocenter/ibmxiv/r2/index.jsp

  10. hibernate 延长加载范围 4.2

    1. 关闭延迟加载功能 lazy="false"2.修改抓取策略 fetch="join"直接查询关联数据,一个联接查询搞定3.使用Hibernate对象的in ...