一个WCF服务是一系列终结点集合,每个终结点有一个独一无二的地址。终结点地址和绑定确定了终结点在哪里以及如何监听进入请求。除了终结点地址,服务本身也有地址,称为基地址。
一个服务的基地址用来作为可能在终结点中定义的相对地址的基地址。使用相对地址,而不是绝对地址,终结点地址让在一个服务中管理终结点变得更加容易。通过相对地址,你可以在一个服务中仅通过改变服务基地址就改变所有终结点地址。
当在一个终结点中使用一个相对地址时,相对地址附加到基地址来形成服务基地址。例如,如果一个服务基地址是http://localhost/foo 而终结点地址是bar,终结点将会在http://localhost/foo/bar 监听进入请求消息。
当在一个终结点中使用相对地址时,终结点地址与服务基地址无关。例如,一个服务基地址可以是http://localhost/foo, 而在它内部的一个终结点地址是net.tcp://bar/MyOtherService/.
一个服务可以有多个基地址, 但是每个URI 只有一个。当在一个终结点中使用一个相对地址时, WCF使用满足终结点绑定定义的传输协议来找到服务基地址。例如,如果一个服务定义两个基地址, http://localhost/ 和net.tcp://bigserver/, 一个终结点使用一个basicHttpBinding绑定的相对地址foo, 终结点地址是http://localhost/foo. 如果服务中的另外一个终结点也使用同样的相对地址, 终结点地址是net.tcp/bigserver/foo.
当在IIS中寄宿一个服务时, 服务的基地址是SVC文件所在的IIS虚拟目录的地址。如果MyService.SVC文件位于http://localhost/foo/, 服务的基地址是http://localhost/foo. 当在IIS中寄宿时由web.config确定的终结点地址必须是相对地址。
列表7.2显示了一个服务的配置文件。注意以下几点:
基地址. 服务定义了两个基地址, 每个使用一个不同的协议。如果两个基地址使用同样协议定义, 如何从终结点相对地址创建完全地址是不可能的, 所以WCF将会在服务激活时抛出一个异常。
空的相对地址. 第一个终结点的地址是空的。使用同样的协议与服务基地址组合, 终结点地址与服务地址一样。
非空的相对地址. 第二个终结点的地址是ws.使用同样的协议与基地址组合, 终结点的地址是http://localhost:8000/EssentialWCF/ws.
列表7.12 配置文件中的服务和终结点地址
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <behaviors /> <services> <service name="EssentialWCF.GoodStockService"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="" contract="EssentialWCF.GoodStockService" /> <endpoint address="secure" binding="wsHttpBinding" bindingConfiguration="" contract="EssentialWCF.GoodStockService" /> <endpoint address="fast" binding="netTcpBinding" bindingConfiguration="" contract="EssentialWCF.GoodStockService" /> <host> <baseAddresses> <add baseAddress="http://localhost:8000/EssentialWCF" /> <add baseAddress="net.tcp://localhost:8001/EssentialWCF" /> </baseAddresses> </host> </service> </services> </system.serviceModel> </configuration>
使用System.ServiceModel.Description命名空间,你可以从ServiceHost访问所有的地址和绑定信息。列表7.13显示了一段指出这个信息的代码片段。
列表7.13 打印地址和终结点信息的代码片段
foreach (Uri uri in serviceHost.BaseAddresses) { Console.WriteLine("Base Addr Uri : {0}", uri.AbsoluteUri); } foreach (ServiceEndpoint endpoint in serviceHost.Description.Endpoints) { Console.WriteLine("\nEndpoint - address: {0}", endpoint.Address); Console.WriteLine(" binding: {0}", endpoint.Binding.Name); Console.WriteLine(" contract: {0}", endpoint.Contract.Name); }
图片7.6 显示了当运行使用列表7.12中的配置文件的代码输出