元資料發布方式決定獲取行為。WCF 透過 ServiceMetadataBehavior 支援 WS-MEX 與 HTTP-GET 兩種發布協定,對應的獲取實作也各異。本文分別示範如何手動實作這兩種獲取方式。
MEX 端點本質上就是一般服務端點,契約為 IMetadataExchange。我們可建立對應的 ChannelFactory<IMetadataExchange>,發送 WS-Transfer Get 請求訊息,從回覆訊息中取出 MetadataSet。
using System;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Xml;
namespace Artech.MetataRetrieval
{
class Program
{
static void Main(string[] args)
{
MetadataSet metadata = null;
using (ChannelFactory<IMetadataExchange> channelFactory = new ChannelFactory<IMetadataExchange>(
MetadataExchangeBindings.CreateMexHttpBinding(),
new EndpointAddress("https://127.0.0.1:9999/calculatorservice/mex")))
{
IMetadataExchange proxy = channelFactory.CreateChannel();
using (proxy as IDisposable)
{
Message request = Message.CreateMessage(MessageVersion.Default, "https://schemas.xmlsoap.org/ws/2004/09/transfer/Get");
metadata = proxy.Get(request).GetBody<MetadataSet>();
}
}
using (XmlWriter writer = new XmlTextWriter("metadata.xml", Encoding.UTF8))
{
metadata.WriteTo(writer);
}
Process.Start("metadata.xml");
}
}
}
執行後,包含元資料的 XML 檔案會以 IE 開啟(圖 1)。

圖 1 通過 IE 顯示獲取的元資料(WS-MEX 方式)
若服務啟用 HTTP-GET 發布(組態中 httpGetEnabled="true"、httpGetUrl 指定位址),則可直接發送 HTTP GET 請求取得 WSDL,再轉為 MetadataSet。
using System.Diagnostics;
using System.Net;
using System.ServiceModel.Description;
using System.Xml;
using System.Text;
namespace Artech.MetataRetrieval
{
class Program
{
static void Main(string[] args)
{
MetadataSet metadata = new MetadataSet();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://127.0.0.1:3721/calculatorservice/metadata");
request.Method = "Get";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (XmlReader reader = XmlDictionaryReader.CreateTextReader(response.GetResponseStream(), new XmlDictionaryReaderQuotas()))
{
System.Web.Services.Description.ServiceDescription serviceDesc = System.Web.Services.Description.ServiceDescription.Read(reader);
metadata.MetadataSections.Add(MetadataSection.CreateFromServiceDescription(serviceDesc));
}
using (XmlWriter writer = new XmlTextWriter("metadata.xml", Encoding.UTF8))
{
metadata.WriteTo(writer);
}
Process.Start("metadata.xml");
}
}
}
執行結果如圖 2。透過 HTTP-GET 取得的 MetadataSet 僅包含 WSDL 方言的 MetadataSection,因為未進一步解析 WSDL 中引用的外部結構描述。

圖 2 通過 IE 顯示獲取的元資料(HTTP-GET 方式)