WCF获取服务元数据经验总结

开发 开发工具
WCF获取服务元数据中包含有许多个终结点,客户端与服务端可以通过这个终结点来交换信息。在这篇文章中就介绍了一些相关的实现方法,希望对大家有所帮助。

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

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

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

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

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

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

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

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

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

public abstract class 
MetadataImporter  
{   public abstract Collection
<ContractDescription> 
ImportAllContracts();  
public abstract Service
EndpointCollection
 ImportAllEndpoints();  
//其它方法略;  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

 

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

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

 

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

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

public class WsdlImporter :
 MetadataImporter  
{   public WsdlImporter(MetadataSet
 metadata);  
public Collection<Binding>
 ImportAllBindings();   public override Collection
<ContractDescription> ImportAllContracts();   public override ServiceEndpoint
Collection ImportAllEndpoints();  
public ServiceEndpointCollection 
ImportEndpoints(Binding wsdlBinding);  
//其它成员略;  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

 

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

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

 

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

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

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

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

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

 

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

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

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

责任编辑:曹凯 来源: 博客园
相关推荐

2009-12-22 18:36:17

WCF知识结构

2009-10-15 09:27:00

2010-03-19 14:03:34

云计算

2009-09-16 17:13:54

学习Linq

2009-08-19 09:24:43

AJAX引擎经验总结

2009-09-29 16:32:11

OJB Hiberna

2009-12-22 16:14:01

WCF服务元数据

2010-04-20 10:41:49

Oracle数据库

2009-12-25 15:58:37

WPF数据处理

2010-06-12 17:37:18

UML实践指南

2009-09-16 17:44:54

LINQ to SQL

2009-09-08 10:57:55

LINQ查询操作

2009-08-20 17:35:47

Servlet和JSP

2011-07-08 13:15:52

JSP

2009-11-17 11:24:00

PHP应用技巧

2009-10-22 15:07:12

综合布线工程

2009-09-11 13:29:31

LINQ查询操作

2009-09-08 16:02:47

Linq使用Group

2009-03-11 15:40:20

2010-02-26 14:12:27

WCF元数据
点赞
收藏

51CTO技术栈公众号