WCF客户端可以调用任何基于标准的服务而不用考虑目标宿主环境。在.NET Framework 1.1 上创建的ASMX网络服务是完全兼容的。由WS-I 1.1基本概况定义的标准确保它们可以被WCF调用。
支持工具
就像调用一个WCF服务,你可以使用添加服务引用(ASR)或者Svcutil.exe来创建代理类和配置文件来调用ASMX服务操作。在这些被创建以后,客户端通过实例化代理调用方法来与ASMX网络服务通信。同样的,你可以使用添加网络服务引用(AWR)或者wsdl.exe 来生成代理类和配置文件。然后在实例被创建以后,客户端在代理上调用方法来和服务通信。
对于新生成的调用已存在的ASMX网络服务的客户端应用,最好是使用ASR或者svcutil.exe.对于那些已经通过ASR/svcutil.exe产生代理类和配置文件的已有应用,最好是继续使用AWR/wsdl.exe.这种方式,客户端不用使用两种类型的代理类和配置文件来和ASMX服务通信。如果客户端被修改去使用basicHttpBinding来调用新的WCF服务,你可以仍然使用AWR/wsdl.exe来为WCF服务产生新的代理。
不论你是否使用svcutil.exe或者wsdl.exe来生成代理类,客户端使用这个代理来访问远程服务。额外的,为了支持代理类在客户端应用程序的app.config中增加了入口。
生成客户端代理类和配置文件
如果你在修改一个已存在的已经有ASMX代理的客户端,你应该使用添加服务引用(ASR).列表1.13显示了使用通过添加服务引用生成的客户端代码调用服务操作的过程。
列表1.13 使用添加服务引用添加生成的客户端代码访问一个ASMX服务
using System; using System.ServiceModel; using System.ServiceModel.Description; namespace Client { class Program { static void Main(string[] args) { ASMXReference.StockService proxy = new ASMXReference.StockService(); double p = proxy.GetPrice("msft"); Console.WriteLine("Price:{0}", p); proxy.Close(); } } }
列表1.14显示了一个由Visual Studio通过添加服务引用生成的配置文件。注意唯一的存储在app.config中的属性是服务的地址。 这将与列表1.16中的通过添加服务引用生成的app.config所描述的细节形成鲜明对比。通过添加服务引用添加的额外配置可以让开发人员或者管理员改变参数,比如超时,而不用改任何代码。
列表1.14 通过为一个ASMX服务添加服务引用而生成的app.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <section name="Clinet.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 requirePermission=false"/> </sectionGroup> </configSections> <applicationSettings> <Client.Properties.Settings> <setting name="Client_ASMXReference_StockService" serializeAs="string"> <value>http://localhost/asmx/service.asmx</value> </setting> </Client.Properties.Settings> </applicationSettings> </configuration>
如果你在创建一个没有ASMX代理的客户端,你应该使用添加服务引用以便于你使用新的代理来开始一个新的工程。列表1.15显示了和一个ASMX服务一起使用的由添加服务引用生成代理的客户端代码。注意终结点的名字,StockServiceSoap,必须在代理生成之前被创建。这是因为添加服务引用会添加两个终结点到app.config文件中:一个使用basicHttpBinding,另一个使用与SOAP 1.1适应的自定义绑定。
列表1.15 使用添加服务引用代理访问ASMX的客户端代码
using System; using System.ServiceModel; using System.ServiceModel.Description; namespace Client { class Program { static void Main(string[] args) { using(WCFReference.StockServiceSoapClient proxy = new client.WCFReference.StockServiceSoapClient("StockServiceSoap")) { double p = proxy.GetPrice("msft"); Console.WriteLine("Price:{0}", p); } } } }
列表1.16显示了由Visual Studio添加服务引用添加的为一个ASMX服务使用的配置文件。注意绑定的全部细节和终结点信息是从ASMX服务获取的,它们存储于app.config中。也要注意有两个终结点被定义。第一个终结点,StockServiceSoap,使用basicHttpBinding,与WS-I基本架构1.1标准一起编译。第二个终结点,StockServiceSoap12,使用自定义绑定和后来的SOAP协议通信。因为ASMX是WS-I基本框架1.1标准兼容的,所以1.1终结点也被使用。
列表1.16 由添加服务引用生成的为一个ASMX服务使用的app.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="StockServiceSoap" closeTimeout="00:01:00" openTimeout="0:01:00" receiveTimeout="00:01:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/> <security mode="None"> <transport clientCredentialType="None" proxyCredentialType="None" realm=""/> <message clientCredentialType="UserName" algorithmSuite="Default"/> </security> </binding> </basicHttpBinding> <customBinding> <binding name="StockService12"> <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" messageVersion="Soap12" writeEncoding="utf-8"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/> </textMessageEncoding> <httpTransport manualAddressing="false" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true"/> </binding> </customBinding> </bindings> <client> <endpoint address="http://localhost/asmx/service.asmx" binding="basicHttpBinding" bindingConfiguration="StockServiceSoap" contract="Client.WCFReference.StockServiceSoap" name="StockServiceSoap"/> <endpoint address="http://localhost/asmx/service.asmx" binding="customBinding" bindingConfiguration="StockServiceSoap12" contract="Client.WCFReference.StockServiceSoap" name="StockServiceSoap12"/> </client> </system.serviceModel> </configuration>