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

元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-MEXHTTP-GET的元数据发布,针对这两种不同的协议,元数据获取的实现方式也是不同的。我们首先来实现基于WS-MEX的元数据获取方式。 [Source Code从这里下载]

一、 基于WS-MEX的元数据获取

ServiceMetadataBehavior通过创建MEX终结点实现了基于WS-MEX的元数据的发布,从《如何将一个服务发布成WSDL》系列文章的介绍我们知道:元数据的发布实际上可以看成是在服务端寄宿一个元数据提供服务,我们通过服务调用的形式获取元数据。

由于MEX终结点与一般意义上的终结点并没有本质的不同,我们只需要创建服务元数据发布方相匹配的终结点,相目标地址发送期望的请求消息,即可通过回复消息的形式获取元数据信息。现在以我们熟悉的计算服务为例,在服务寄宿的时候通过以下的配置为该服务添加一个MEX终结点,采用的MEX绑定和地址分别问:mexHttpBinding和http://127.0.0.1:9999/calculatorservice/mex

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <system.serviceModel>
   4:     <services>
   5:       <service name="Artech.MetataRetrieval.Services.CalculatorService" behaviorConfiguration="mexBehavior">        
   6:         <endpoint address=" http://127.0.0.1:9999/calculatorservice" binding="ws2007HttpBinding" contract="Artech.MetataRetrieval.Services.ICalculator"/>
   7:         <endpoint address="http://127.0.0.1:9999/calculatorservice/mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
   8:       </service>
   9:     </services>
  10:     <behaviors>
  11:       <serviceBehaviors>
  12:         <behavior name="mexBehavior">
  13:           <serviceMetadata  httpGetEnabled="true" httpGetUrl="http://127.0.0.1:3721/calculatorservice/metadata"/>
  14:         </behavior>
  15:       </serviceBehaviors>
  16:     </behaviors>
  17:   </system.serviceModel>
  18: </configuration>

下面的代码展现了客户端获取元数据的程序,这和一般的服务调用并无二致。首先通过指定相应的绑定(MetadataExchangeBindings.CreateMexHttpBinding())和地址(元数据的目标地址:http://127.0.0.1:9999/calculatorservice/mex)创建ChannelFactory<TChannel>对象(由于MEX终结点契约类型为IMetadataExchange,这里的TChannel类型为IMetadataExchange)。由于MEX终结点契约IMetadataExchange的Get方法的输入参数和输出参数均为Message对象,而是我们创建Message对象,并指定与WS-MEX匹配的Action。然后传入通过ChannelFactory<TChannel>创建的服务代理中进行服务调用。最后从回复消息中提取出包含元数据的MetadataSet对象,并将其写入一个XML文件中。

   1: using System;
   2: using System.Diagnostics;
   3: using System.ServiceModel;
   4: using System.ServiceModel.Channels;
   5: using System.ServiceModel.Description;
   6: using System.Text;
   7: using System.Xml;
   8: namespace Artech.MetataRetrieval
   9: {
  10:     class Program
  11:     {
  12:         static void Main(string[] args)
  13:         {
  14:             MetadataSet metadata = null;
  15:             using (ChannelFactory<IMetadataExchange> channelFactory = new ChannelFactory<IMetadataExchange>(MetadataExchangeBindings.CreateMexHttpBinding(), new EndpointAddress("http://127.0.0.1:9999/calculatorservice/mex")))
  16:             {
  17:                 IMetadataExchange proxy = channelFactory.CreateChannel();
  18:                 using (proxy as IDisposable)
  19:                 {
  20:                     Message request = Message.CreateMessage(MessageVersion.Default, "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get");
  21:                     metadata = proxy.Get(request).GetBody<MetadataSet>();
  22:                 }
  23:             }
  24:             using (XmlWriter writer = new XmlTextWriter("metadata.xml", Encoding.UTF8))
  25:             {
  26:                 metadata.WriteTo(writer);
  27:             }
  28:             Process.Start("metadata.xml");
  29:         } 
  30:     }
  31: }

当程序成功执行,包含元数据的XML文件将会通过IE输出(假设将IE作为默认的XML启动程序),图1为运行后的截图。

 1 通过IE显示获取的元数据(以WS-MEX方式发布)

二、 基于HTTP-GET的元数据获取

上面我们通过自定的方式成功获取了服务端以WS-MEX方式发布的元数据,现在我们来是实现基于HTTP-GET的元数据获取方式。既然服务端采用了基于HTTP-GET的元数据发布方式,那么就意味着我们可以通过简单的HTTP请求的方式获取相应的元数据资源。

同样是基于上面的例子,仔细的读者相信已经看到了,在计算服务的配置文件中,除了为服务添加MEX终结点之外,还通过ServiceMetadataBehavior开启了基于HTTP-GET的元数据发布方式,并将元数据发布地址指定为:http://127.0.0.1:3721/calculatorservice/metadata

下面的代码实现了相应的元数据获取,其中我通过指定目标地址创建了一个HttpWebRequest对象,并通过该对象向元数据的发布地址发送请求。获取的元数据将以HttpWebResponse的形式返回,由于获取的元数据实际上是一个WSDL文档,所以我们可以通过ServiceDescription的Read方法直接读取生成一个ServiceDescription对象,并最终通过MetadataSection的静态方法CreateFromServiceDescription将其转换成一个MetadataSection对象。该MetadataSection对象被最终添加到创建的MetadataSet中,并被写入一个XML文件。

   1: using System.Diagnostics;
   2: using System.Net;
   3: using System.ServiceModel.Description;
   4: using System.Xml; 
   5: using System.Text;
   6: namespace Artech.MetataRetrieval
   7: {
   8:     class Program
   9:     {
  10:         static void Main(string[] args)
  11:         {
  12:             MetadataSet metadata = new MetadataSet();
  13:             HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://127.0.0.1:3721/calculatorservice/metadata");
  14:             request.Method = "Get";
  15:             HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  16:             using (XmlReader reader = XmlDictionaryReader.CreateTextReader(response.GetResponseStream(), new XmlDictionaryReaderQuotas()))
  17:             {
  18:                 System.Web.Services.Description.ServiceDescription serviceDesc = System.Web.Services.Description.ServiceDescription.Read(reader);
  19:                 metadata.MetadataSections.Add(MetadataSection.CreateFromServiceDescription(serviceDesc));
  20:             }
  21:             using (XmlWriter writer = new XmlTextWriter("metadata.xml", Encoding.UTF8))
  22:             {
  23:                 metadata.WriteTo(writer);
  24:             }
  25:             Process.Start("metadata.xml");
  26:         }
  27:     }
  28: }

当上面的应用程序成功执行,包含获取的元数据的XML将会通过IE打开,图2为运行后的截图。通过两种方式获取的元数据本质上是相同的,不过可能细心的读者已经发现了:与上面的例子(WS-MEX)获取的MetadataSet不同,通过HTTP-GET获取的MetadataSet仅仅包含一个元数据方言(Dialect)为WSDL的MetadataSection。这是因为,前面的例子实际上将WSDL中引用(通过终结点地址或者资源地址)的内容都生成了相应的MetadataSection,在这里由于篇幅所限,并没有做这些工作。

 2 通过IE显示获取的元数据(以HTTP-GET方式发布)

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

原文链接

时间: 2024-12-31 09:22:38

WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]的相关文章

WCF技术剖析之二十八:自己动手获取元数据

元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-MEX和HTTP-GET的元数据发布,针对这两种不同的协议,元数据获取的实现方式也是不同的.我们首先来实现基于WS-MEX的元数据获取方式. 本文配套源码:http://www.bianceng.net/dotnet/201212/655.htm 一. 基于WS-MEX的元数据获取 ServiceMetadataBehavior通过创建MEX终结点实现了基于WS-ME

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

WCF客户端和服务端的框架体系相互协作,使得开发人员可以按照我们熟悉的方式进行异常的处理:在服务操作执行过程中抛出异常(FaultException),在调用服务时捕获异常,完全感觉不到"分布式"的存在,如同典型的"本地"操作一般.为了实现这样的效果,WCF在内部为我们作了很多. 消息交换是WCF进行通信的唯一手段,消息不仅仅是正常服务调用请求和回复的载体,服务端抛出的异常,甚至是服务的元数据都是通过消息的形式传向客户端的.所以,实现异常与消息之间的转换是整个异常处

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

通过<实现篇>对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding元素来源于终结点的绑定对象,那么这些基于Binding的元数据以及相应的策略断言是如何被写入WSDL的呢?WSDL导出扩展(WSDL Export Extension)和策略导出扩展(Policy Export Extension)就是为此设计的. 一.WSDL导出扩展(WSDL Export Extension) 终结点的绑定本质上就是相关的绑定元素(BindingElement)的有序组合(

WCF技术剖析之二十五:元数据(Metadata)架构体系全景展现[WS标准篇]

元数据实际上是服务终结点的描述,终结点由地址(Address).绑定(Binding)和契约(Contract)经典的ABC三要素组成.认真阅读过<WCF技术剖析(卷1)>的读者相对会对这三要素的本质有一个深刻的认识:地址决定了服务的位置并实现相应的寻址机制:契约描述了消息交换模式(Message Exchange Pattern: MEP)以及消息的结构(Schema):绑定则通过创建信道栈实现对消息的编码.传输和基于某些特殊的功能(比如实现事务.可靠传输以及基于消息的安全)对消息作出的处理

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

服务端只有抛出FaultException异常才能被正常地序列化成Fault消息,并实现向客户端传播.对于一般的异常(比如执行Divide操作抛出的DivideByZeroException),在默认的情况下,异常信息无法实现向客户端传递.但是,倘若为某个服务应用了ServiceDebugBehavior这么一个服务行为,并开启了IncludeExceptionDetailInFaults开关,异常信息将会原封不动地传播到客户端.WCF内部是如何处理抛出的非FaultException异常的呢?

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

我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置:通过ChannelFactory<TChannel>创建服务代理对象.在这篇文章中,我们采用一种独特的方式进行服务的调用.从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用.在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服务的元数据,而利用MetadataImporter将获取的元数据导入成Serv

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

元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框架体系中,元数据的导出工作由MetadataExporter实现.MetadataExporter是一个抽象类型,定义了导出元数据的基本行为.WCF定义一个具体的MetadataExporter:WsdlExporter,将基于某个终结点的元数据导出生成基于WSDL的MetadataSet.我们先来认识MetadataExporter和MetadataSet. 一.MetadataEx

WCF技术剖析之二十九:换种不同的方式调用WCF服务

我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置:通过ChannelFactory<TChannel>创建服务代理对象.在这篇文章中,我们采用一种独特的方式进行服务的调用.从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用.在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服务的元数据,而利用MetadataImporter将获取的元数据导入成Serv

WCF技术剖析之二十五:元数据(Metadata)架构体系全景展现[元数据描述篇]

在[WS标准篇]中我花了很大的篇幅介绍了WS-MEX以及与它相关的WS规范:WS-Policy.WS-Transfer和WSDL,因为WCF元数据结构体系完全是基于WS-MEX等相关的规范之上.熟悉这些基本的WS规范,对于我们全面.深刻的理解WCF整个元数据架构体系具有十分重要的意义.不仅仅是针对元数据,对于后续章节陆续要介绍的内容,比如事务.可靠会话.安全等,我强烈建议读者在正式进行相关部分的学习之前,先对相关的WS规范作一个大致的了解. 通过对WS-MEX的介绍,我们知道:不论是采用WS-T