WCF中的元数据是精确描述如何与服务通信的消息。客户端可以向一个运行的服务请求元数据来了解它们要求的终结点和消息格式。在设计时,客户端发送由WS-MetadataExchange 标准定义的消息并接收返回的WSDL。WSDL可以被客户端用来定义一个将要用来在运行时与服务通信的代理类和配置文件。图片1.4显示了这个交流过程。
默认情况下,WCF服务不暴露MEX终结点。这意味着没有人能查询到这个服务并知晓如何与它通信。不知道地址,绑定和契约,与服务通信是非常困难的,除非服务被记录到注册表中。幸运的是,WCF让暴露MEX终结点变得非常容易以至于客户端可以与服务端顺畅的通信。MEX终结点可以通过代码或者配置文件暴露。
列表1.4显示了在一个服务中暴露一个MEX终结点所必需的代码。这个例子在很多方面都对列表1.1中的例子进行了扩展。首先,一个行为(IMetadataExchange)被添加到服务中来指导WCF包含MEX契约。其次,一个地址是"mex",绑定是HTTP 协议,契约是 IMetadataExchange 的终结点被添加到服务中。因为这个地址是作为一个相对地址,服务的基地址要放在头部,所以完整的地址是 http://localhost:8000/EssentialWCF/mex .注意服务中的行为也被改动去使能HTTP Get 功能。这不是必须的但是可以允许用户通过浏览器访问MEX终结点。
列表1.4 在代码中暴露服务中的MEX终结点
using System; using System.ServiceModel; using System.ServiceModel.Description; namespace EssentialWCF { [ServiceContract] public interface IStockService { [OperationContract] double GetPrice(string ticker); } public class StockService : IStockService { public double GetPrice(string ticker) { return 94.85; } } public class Service { public static void Main() { ServiceHost serviceHost = new ServiceHost(typeof(StockService), new Uri("http://localhost:8000/EssentialWCF")); serviceHost.AddServiceEndpoint(typeof(IStockService), new BasicHttpBinding(), ""); ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); behavior.HttpGetEnabled = true; serviceHost.Description.Behaviors.Add(behavior); serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); serviceHost.Open(); Console.WriteLine("Press <Enter> to terminate.\r\n"); Console.ReadLine(); serviceHost.Close(); } } }
如果你选择在配置文件中设置终结点而不是在代码中,你需要在配置文件中暴露MEX终结点。列表1.5 如果修改列表1.3中的配置文件来暴露MEX终结点。一个MEX终结点被添加到服务中而且一个服务行为被添加以便于MEX终结点可以通过HTTP来访问。
列表1.5 使用配置文件暴露服务的MEX终结点
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.servicemodel> <services> <service name="EssentialWCF.StockService" behaviorConfiguration="myServiceBehavior"> <host> <baseaddresses> <add baseaddress="http://localhost:8000/EssentialWCF" /> </baseaddresses> </host> <endpoint address="" binding="basicHttpBinding" contract="EssentialWCF.IStockService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="myServiceBehavior"> <serviceMetadata httpGetEnabled="True" /> </behavior> </serviceBehaviors> </behaviors> </system.servicemodel> </configuration>