首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 服務元數據獲取全攻略:端點資訊與 MetadataExchangeClient 實戰

     編輯:關於.NET

所謂獲取 WCF 服務元數據,本質上是獲取服務端點的詳細資訊 —— 即位址、繫結、契約 (ABC)。Juval Löwy 在《Programming WCF Services》一書中以棒棒糖圖示生動呈現端點構成。

端點構成棒棒糖圖
端點構成:位址、繫結、契約
多端點通訊示意圖
客戶端與服務端透過多個端點交換資訊

WCF 服務可包含多個端點,每個端點都是通訊入口。掌握端點詳細資訊有助於深入剖析服務定義、內容與執行方式。

兩種元數據發布方式

  1. HTTP-GET 協定:直接透過 HTTP GET 請求獲取元數據
  2. 元數據交換端點:專用端點,契約為 IMetadataExchange,使用 WS-MetadataExchange (MEX) 協定

對應 MetadataExchangeClientMode 列舉:

public enum MetadataExchangeClientMode
{
    MetadataExchange,  // MEX 端點
    HttpGet            // HTTP-GET
}

核心類別架構

ServiceEndpoint:端點資訊容器

定義於 System.ServiceModel.Description,包含三大核心屬性:

ServiceEndpoint 類別結構
ServiceEndpoint 對應 Address、Binding、Contract

MetadataImporter:抽象匯入器

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

關鍵方法 ImportAllEndpoints() 回傳 ServiceEndpointCollection,可透過 Find() 或 FindAll() 依契約類型或位址查詢。

WsdlImporter:WSDL 專用匯入器

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

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-GET 模式)

string mexAddress = "https://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();

注意:HTTP-GET 模式下元數據位址尾碼必須為 ?wsdl。

彈性策略:優先嘗試 MEX 端點,失敗再嘗試 HTTP-GET

string mexAddress = "https://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 || endpoints.Count == 0)
{
    string httpGetAddress = mexAddress.EndsWith("?wsdl") ? mexAddress : mexAddress + "?wsdl";
    metadata = mexClient.GetMetadata(new Uri(httpGetAddress), MetadataExchangeClientMode.HttpGet);
    importer = new WsdlImporter(metadata);
    endpoints = importer.ImportAllEndpoints();
}

列印端點詳細資訊

foreach (ServiceEndpoint endpoint in endpoints)
{
    Console.WriteLine("Endpoint Name: {0}", endpoint.Name);
    Console.WriteLine("Address: {0}", endpoint.Address.Uri.AbsoluteUri);
    Console.WriteLine("Binding: {0}", endpoint.Binding.GetType().ToString());
    Console.WriteLine("Contract: {0}", endpoint.Contract.Name);
    Console.WriteLine();
}

延伸應用

透過類似途徑,還可獲取服務契約、回呼契約、基底位址、繫結參數等更多元數據資訊,為服務治理、動態代理生成、自動化測試提供強力支援。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved