WCF获取服务元数据经验总结
创始人
2024-06-16 19:21:37
0

WCF框架是目前比较受欢迎的一款由微软研发的开发框架。它的出现实现了跨平台的网络解决方案。在这篇文章中就为大家介绍有关WCF获取服务元数据的相关方法。#t#

所谓WCF获取服务元数据(Metadata),归根结点,实际上就是获取服务的终结点(Endpoint)的信息,这是服务公开在外的数据信息,包括Address、Binding与Contract,也就是所谓的ABCs。

WCF获取服务元数据可能包含多个终结点,每个终结点相当于是通信的入口,客户端和服务端通过终结点交换信息。

因而,如果能够获取终结点的详细信息,有助于我们更好地剖析服务的定义、内容与执行方式。

服务有两种方案可以发布自己的元数据。一种是基于HTTP-GET协议提供元数据;另一种则为元数据交换方式,它往往使用一个专门的终结点,称之为元数据交换终结点。元数据交换终结点与其它终结点相似,仍然包含了地址、绑定与契约,但是使用的服务契约为WCF提供的接口IMetadataExchange。

实际上,这两种发布元数据的方式代表了它使用了两种不同的WCF获取服务元数据标准协议,前者为HTTP/GET请求,后者为WS-MetadataExchange(MEX)。在WCF,以MetadataExchangeClientMode枚举类型表示这两种元数据交换模式:

  1. public enum Metadata
    ExchangeClientMode  
  2. {  
  3. MetadataExchange,  
  4. HttpGet  
  5. }  

WCF为终结点定义了一个专门的ServiceEndpoint类,被定义在System.ServiceModel.Description命名空间中。ServiceEndpoint类包含了EndpointAddress,Binding,ContractDescription三个类型的属性,分别对应Endpoint的Address,Binding,Contract。

要WCF获取服务元数据的终结点,可以通过抽象类MetadataImporter获取,类的定义如下:

  1. public abstract class 
    MetadataImporter  
  2. {  
  3. public abstract Collection
     
    ImportAllContracts();  
  4. public abstract Service
    EndpointCollection
     ImportAllEndpoints();  
  5. //其它方法略;  

 

在类中,最重要的一个方法是ImportAllEndpoints(),它能够获取服务的所有终结点,并返回一个ServiceEndpointCollection类型的对象。该类型为一个终结点集合,可以通过调用ServiceEndpointCollection的Find()方法或FindAll()方法,找到符合条件的一个或多个终结点。它的定义如下:

  1. public class ServiceEndpointCollection
     : Collection 
  2. {  
  3. public ServiceEndpoint Find
    (Type contractType);  
  4. public ServiceEndpoint Find(Uri address);  
  5. public Collection 
    FindAll(Type contractType);  
  6. //其它成员略  

 

我们可以通过契约类型,或者服务契约的地址,查找符合条件的终结点。

MetadataImporter类只是一个抽象类,如果要获取WSDL元数据,还会需要使用继承它的子类型WsdlImporter:

  1. public class WsdlImporter :
     MetadataImporter  
  2. {  
  3. public WsdlImporter(MetadataSet
     metadata);  
  4. public Collection
     ImportAllBindings();  
  5. public override Collection
     ImportAllContracts();  
  6. public override ServiceEndpoint
    Collection ImportAllEndpoints();  
  7. public ServiceEndpointCollection 
    ImportEndpoints(Binding wsdlBinding);  
  8. //其它成员略;  

 

如果要使用WsdlImporter,需要为其构造函数传递一个MetadataSet类型的对象。而MetadataSet类型的对象则可以通过MetadataExchangeClient类的GetMetadata()方法获得。MetadataExchangeClient类的定义如下所示:

  1. public class MetadataExchangeClient  
  2. {  
  3. public MetadataExchangeClient();  
  4. public MetadataExchangeClient
    (Binding mexBinding);  
  5. public MetadataExchangeClient
    (EndpointAddress address);  
  6. public MetadataExchangeClient
    (string endpointConfigurationName);  
  7. public MetadataExchangeClient
    (Uri address, MetadataExchangeClientMode mode);  
  8. public MetadataSet GetMetadata();  
  9. public MetadataSet GetMetadata
    (EndpointAddress address);  
  10. public MetadataSet GetMetadata
    (Uri address, MetadataExchangeClientMode mode);  
  11. //其它方法略;  

 

假定服务公开的元数据地址为http://localhost:8001/IMyService?wsdl,则WCF获取服务元数据的方法如下:

  1. string mexAddress = “http
    ://localhost:8001/IMyService?wsdl”;  
  2. BasicHttpBinding binding = new BasicHttpBinding();  
  3. MetadataExchangeClient mexClient = 
    new MetadataExchangeClient(binding);  
  4. MetadataSet metadata = mexClient.
    GetMetadata(new Uri(mexAddress), 
    MetadataExchangeClientMode.HttpGet);  
  5. MetadataImporter importer = new
     WsdlImporter(metadata);  
  6. ServiceEndpointCollection endpoints = 
    importer.ImportAllEndpoints(); 

注意,如果是HttpGet模式,则元数据地址的后缀必须为?wsdl。由于我们在调用MetadataExchangeClient的GetMetadata()方法时,传递的MetadataExchangeClientMode枚举参数值为HttpGet,因此获取的为基于HTTP-GET的元数据。

如果服务使用的协议为HTTP或者HTTPS,则可能使用元数据交换终结点,也可能为Http-Get模式。此时,我们可以先获取元数据交换终结点,如果没有找到,再获取基于HTTP-GET的终结点:

  1. string mexAddress = 
    “http://localhost:8001/IMyService?wsdl”;  
  2. BasicHttpBinding binding = 
    new BasicHttpBinding();  
  3. MetadataExchangeClient mexClient = 
    new MetadataExchangeClient(binding);  
  4. MetadataSet metadata = mexClient
    .GetMetadata(new EndpointAddress(mexAddress));  
  5. MetadataImporter importer = 
    new WsdlImporter(metadata);  
  6. ServiceEndpointCollection endpoints = 
    importer.ImportAllEndpoints();  
  7. if (endpoints == null)  
  8. {  
  9. string httpGetAddress = mexAddress;  
  10. if (!mexAddress.EndsWith(“?wsdl”) )  
  11. {  
  12. httpGetAddress += “?wsdl”;  
  13. }  
  14. BasicHttpBinding binding =
     new BasicHttpBinding();  
  15. MetadataExchangeClient mexClient =
     new MetadataExchangeClient(binding);  
  16. MetadataSet metadata = mexClient.
    GetMetadata(new Uri(mexAddress), 
    MetadataExchangeClientMode.HttpGet);  
  17. MetadataImporter importer =
     new WsdlImporter(metadata);  
  18. endpoints = importer.ImportAllEndpoints();  

 

在获得ServiceEndpointCollection集合对象后,就可以针对每个ServiceEndpoint获取终结点的Address、Binding、Contract的信息,如下所示:

  1. foreach (ServiceEndpoint endpoint
     in endpoints)  
  2. {  
  3. Console.WriteLine(“Endpoint Name 
    is {0}”, endpoint.Name);  
  4. Console.WriteLine(“Address is {0}”, 
    endpoint.Address.Uri.AbsoluteUri);  
  5. Console.WriteLine(“Binding is {0}”, 
    endpoint.Binding.GetType().ToString());  
  6. Console.WriteLine(“Address is {0}”, 
    endpoint.Contract.Name);  
  7. Console.WriteLine();  

通过以上介绍的类,采用相似的途径,还可以实现更多的WCF获取服务元数据,例如服务契约、回调契约、基地址、地址、绑定等信息。
 

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...