程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 在WCF中獲取服務元數據信息

在WCF中獲取服務元數據信息

編輯:關於.NET

所謂獲取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();
}

通過以上介紹的類,采用相似的途徑,還可以獲取更多元數據信 息,例如服務契約、回調契約、基地址、地址、綁定等信息。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved