在WCF中获取服务元数据信息

简介:

所谓获取WCF的服务元数据(Metadata),归根结点,实际上就是获取服务的终结点 (Endpoint)的信息,这是服务公开在外的数据信息,包括Address、Binding与Contract,也就是所谓的ABCs。Juval Löwy在《Programming WCF Services》一书中,用生动形象的棒棒糖表示了终结点的构成:

 

WCF服务可能包含多个终结点,每个终结点相当于是通信的入口,客户端和服务端通过终结点交换信息,如下图所示:

 

 

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

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

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

public  enum MetadataExchangeClientMode
{
   MetadataExchange,
   HttpGet
}

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

 

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

public  abstract  class  MetadataImporter
{
     public  abstract Collection<ContractDescription> ImportAllContracts();
     public  abstract ServiceEndpointCollection ImportAllEndpoints();
     //其它方法略;
}

 

在类中,最重要的一个方法是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);
     //其它成员略
}

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

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

public  class  WsdlImporter : MetadataImporter
{
     public WsdlImporter(MetadataSet metadata);

     public Collection<Binding> ImportAllBindings();
     public  override Collection<ContractDescription> ImportAllContracts();
     public  override ServiceEndpointCollection ImportAllEndpoints();
     public ServiceEndpointCollection ImportEndpoints(Binding wsdlBinding);
     //其它成员略;
}

如果要使用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);

     //其它方法略;
}

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

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();

注意,如果是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();
}

在获得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();
}

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










本文转自wayfarer51CTO博客,原文链接:http://blog.51cto.com/wayfarer/280098,如需转载请自行联系原作者

相关文章
|
前端开发
WCF更新服务引用报错的原因之一
WCF更新服务引用报错的原因之一
|
12月前
|
C# 数据安全/隐私保护
c#如何创建WCF服务到发布(SqlServer版已经验证)
c#如何创建WCF服务到发布(SqlServer版已经验证)
53 0
|
12月前
|
安全 数据库连接 数据库
WCF服务创建到发布(SqlServer版)
在本示例开始之前,让我们先来了解一下什么是wcf? wcf有哪些特点? wcf是一个面向服务编程的综合分层架构。该架构的项层为服务模型层。 使用户用最少的时间和精力建立自己的软件产品和外界通信的模型。它使得开发者能够建立一个跨平台的安全、可信赖、事务性的解决方案。且能与已有系统兼容写作。 简单概括就是:一组数据通信的应用程序开发接口。
87 0
|
C++
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
119 0
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
WCF使用纯代码的方式进行服务寄宿
服务寄宿的目的是为了开启一个进程,为WCF服务提供一个运行的环境。通过为服务添加一个或者多个终结点,使之暴露给潜在的服务消费,服务消费者通过匹配的终结点对该服务进行调用,除去上面的两种寄宿方式,还可以以纯代码的方式实现服务的寄宿工作。
874 0
|
Windows
WCF服务寄宿到IIS
一.WCF简介: Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台。整合了原有的windows通讯的 .net Remoting,WebService,Socket的机制,并融合有HTTP和FTP的相关技术。
1075 0
WCF服务自我寄宿
WCF服务的寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以寄宿在各种进程之中,常见的寄宿有: IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。
1017 0
|
网络架构
(纯代码)快速创建wcf rest 服务
因为有一个小工具需要和其它的业务对接数据,所以就试一下看能不能弄一个无需配置快速对接的方法出来,百(以)度(讹)过(传)后(讹),最后还是对照wcf配置对象调试出来了: 1.创建WebHttpBinding 2.
994 0