下面的实例我们将创建一个承载于托管代码中的WCF示例程序.开发工具是VS2010, .NET FrameWork 4.0.
这个示例主要概念是,建一个WCF服务提供程序,提供加减乘除的运算,然后再建一个客户端调用程序来调用WCF服务上的方法.下面是完成后的程序框架的截图:
下面我们开始示例程序
1.打开VS2010-->File-->New-->Project. 在弹出的对话框中,按照下面填写.
2.点击OK按钮,创建一个普通的控制台应用程序.
3.引入System.ServiceModel.dll. 因为在下面创建服务协定的时候需要用到此类库.右键单击References-->Add References. 在弹出的对话框中,按照下面选择,点击OK按钮.
4.现在创建一个服务协定,也就是新建一个接口.为接口应用ServiceContractAttribute特性, 为接口中的4个方法应用OperationContractAttribute特性.
这也是WCF协定于普通接口不同之处.带有[ServiceContract]特性的接口说明是WCF公开的协议;带有[OperationContract]特性的方法说明是协议公开的方法. 完整代码如下:
ICalculator.cs
using System; // Step 5: Add the using statement for the System.ServiceModel namespace using System.ServiceModel; namespace Microsoft.ServiceModel.Samples { // Step 6: Define a service contract. [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")] public interface ICalculator { // Step7: Create the method declaration for the contract. [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); [OperationContract] double Multiply(double n1, double n2); [OperationContract] double Divide(double n1, double n2); } }
5.实现服务协定,也就是创建一个类,并实现接口的方法.
这个类需要继承于ICalculator接口,并实现ICalculator接口的方法.这个类的方法会由WCF服务提供给客户端调用.
CalculatorService.cs
using System; using System.ServiceModel; namespace Microsoft.ServiceModel.Samples { // Step 1: Create service class that implements the service contract. public class CalculatorService : ICalculator { // Step 2: Implement functionality for the service operations. public double Add(double n1, double n2) { double result = n1 + n2; Console.WriteLine("Received Add({0},{1})", n1, n2); // Code added to write output to the console window. Console.WriteLine("Return: {0}", result); return result; } public double Subtract(double n1, double n2) { double result = n1 - n2; Console.WriteLine("Received Subtract({0},{1})", n1, n2); Console.WriteLine("Return: {0}", result); return result; } public double Multiply(double n1, double n2) { double result = n1 * n2; Console.WriteLine("Received Multiply({0},{1})", n1, n2); Console.WriteLine("Return: {0}", result); return result; } public double Divide(double n1, double n2) { double result = n1 / n2; Console.WriteLine("Received Divide({0},{1})", n1, n2); Console.WriteLine("Return: {0}", result); return result; } } }
6.创建服务承载程序,也就是WCF服务的宿主.
这个类主要是对WCF做一些服务器端的配置和绑定.注意这行的代码 selfHost.AddServiceEndpoint( typeof(ICalculator), new WSHttpBinding(), "CalculatorService");实现了把协议绑定到主机.
Program.cs
using System; using System.ServiceModel; using System.ServiceModel.Description; namespace Microsoft.ServiceModel.Samples { class Program { static void Main(string[] args) { // Step 1 of the address configuration procedure: Create a URI to serve as the base address. Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service"); // Step 2 of the hosting procedure: Create ServiceHost ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress); try { // Step 3 of the hosting procedure: Add a service endpoint. selfHost.AddServiceEndpoint( typeof(ICalculator), new WSHttpBinding(), "CalculatorService"); // Step 4 of the hosting procedure: Enable metadata exchange. ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; selfHost.Description.Behaviors.Add(smb); // Step 5 of the hosting procedure: Start (and then stop) the service. selfHost.Open(); Console.WriteLine("The service is ready."); Console.WriteLine("Press <ENTER> to terminate service."); Console.WriteLine(); Console.ReadLine(); // Close the ServiceHostBase to shutdown the service. selfHost.Close(); } catch (CommunicationException ce) { Console.WriteLine("An exception occurred: {0}", ce.Message); selfHost.Abort(); } } } }
这是创建好的服务项目截图
到这一步我们的服务已经可以运行了.它提供了加减乘除4个方法供客户端调用.我们可以试运行一下服务,看看效果.导航到项目目录下,双击WcfServiceDemo.exe. 具体目录取决于自己的电脑上项目的位置.
显示服务已经运行.
打开 Internet Explorer,并浏览到服务的调试页(网址为 http://localhost:8000/ServiceModelSamples/Service)
写过WebService的同学,觉得这个页面看起来是不是很熟悉.
点击http://localhost:8000/ServiceModelSamples/Service?wsdl,可以浏览CalculatorService Service的详细描述. 有了这些描述信息,其他平台或公司的开发人员就可以根据这些描述来调用你的WCF程序了.
<?xml version="1.0" encoding="UTF-8"?> -<wsdl:definitions xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:i0="http://Microsoft.ServiceModel.Samples" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:tns="http://tempuri.org/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://tempuri.org/" name="CalculatorService">-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">-<wsp:Policy>-<sp:ProtectionToken>-<wsp:Policy>-<sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">-<wsp:Policy><sp:RequireDerivedKeys/>-<sp:BootstrapPolicy>-<wsp:Policy>-<sp:SignedParts><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts><sp:Body/></sp:EncryptedParts>-<sp:SymmetricBinding>-<wsp:Policy>-<sp:ProtectionToken>-<wsp:Policy>-<sp:SpnegoContextToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">-<wsp:Policy><sp:RequireDerivedKeys/></wsp:Policy></sp:SpnegoContextToken></wsp:Policy></sp:ProtectionToken>-<sp:AlgorithmSuite>-<wsp:Policy><sp:Basic256/></wsp:Policy></sp:AlgorithmSuite>-<sp:Layout>-<wsp:Policy><sp:Strict/></wsp:Policy></sp:Layout><sp:IncludeTimestamp/><sp:EncryptSignature/><sp:OnlySignEntireHeadersAndBody/></wsp:Policy></sp:SymmetricBinding>-<sp:Wss11><wsp:Policy/></sp:Wss11>-<sp:Trust10>-<wsp:Policy><sp:MustSupportIssuedTokens/><sp:RequireClientEntropy/><sp:RequireServerEntropy/></wsp:Policy></sp:Trust10></wsp:Policy></sp:BootstrapPolicy></wsp:Policy></sp:SecureConversationToken></wsp:Policy></sp:ProtectionToken>-<sp:AlgorithmSuite>-<wsp:Policy><sp:Basic256/></wsp:Policy></sp:AlgorithmSuite>-<sp:Layout>-<wsp:Policy><sp:Strict/></wsp:Policy></sp:Layout><sp:IncludeTimestamp/><sp:EncryptSignature/><sp:OnlySignEntireHeadersAndBody/></wsp:Policy></sp:SymmetricBinding>-<sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><wsp:Policy/></sp:Wss11>-<sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">-<wsp:Policy><sp:MustSupportIssuedTokens/><sp:RequireClientEntropy/><sp:RequireServerEntropy/></wsp:Policy></sp:Trust10><wsaw:UsingAddressing/></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Add_Input_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Add_output_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Subtract_Input_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Subtract_output_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Multiply_Input_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Multiply_output_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Divide_Input_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy>-<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Divide_output_policy">-<wsp:ExactlyOne>-<wsp:All>-<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/><sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/></sp:SignedParts>-<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><sp:Body/></sp:EncryptedParts></wsp:All></wsp:ExactlyOne></wsp:Policy><wsdl:import location="http://localhost:8000/ServiceModelSamples/Service?wsdl=wsdl0" namespace="http://Microsoft.ServiceModel.Samples"/><wsdl:types/>-<wsdl:binding name="WSHttpBinding_ICalculator" type="i0:ICalculator"><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_policy"/><soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>-<wsdl:operation name="Add"><soap12:operation style="document" soapAction="http://Microsoft.ServiceModel.Samples/ICalculator/Add"/>-<wsdl:input><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Add_Input_policy"/><soap12:body use="literal"/></wsdl:input>-<wsdl:output><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Add_output_policy"/><soap12:body use="literal"/></wsdl:output></wsdl:operation>-<wsdl:operation name="Subtract"><soap12:operation style="document" soapAction="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract"/>-<wsdl:input><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Subtract_Input_policy"/><soap12:body use="literal"/></wsdl:input>-<wsdl:output><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Subtract_output_policy"/><soap12:body use="literal"/></wsdl:output></wsdl:operation>-<wsdl:operation name="Multiply"><soap12:operation style="document" soapAction="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply"/>-<wsdl:input><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Multiply_Input_policy"/><soap12:body use="literal"/></wsdl:input>-<wsdl:output><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Multiply_output_policy"/><soap12:body use="literal"/></wsdl:output></wsdl:operation>-<wsdl:operation name="Divide"><soap12:operation style="document" soapAction="http://Microsoft.ServiceModel.Samples/ICalculator/Divide"/>-<wsdl:input><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Divide_Input_policy"/><soap12:body use="literal"/></wsdl:input>-<wsdl:output><wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Divide_output_policy"/><soap12:body use="literal"/></wsdl:output></wsdl:operation></wsdl:binding>-<wsdl:service name="CalculatorService">-<wsdl:port name="WSHttpBinding_ICalculator" binding="tns:WSHttpBinding_ICalculator"><soap12:address location="http://localhost:8000/ServiceModelSamples/Service/CalculatorService"/>-<wsa10:EndpointReference><wsa10:Address>http://localhost:8000/ServiceModelSamples/Service/CalculatorService</wsa10:Address>-<Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity"><Upn>SZX-STATION168\Administrator</Upn></Identity></wsa10:EndpointReference></wsdl:port></wsdl:service></wsdl:definitions>
7.下面我们创建一个可以调用此服务的客户端.我们还是创建一个控制台项目.
打开VS2010-->File-->New-->Project. 在弹出的对话框中,按照下面填写.
点击OK按钮完成添加. 跟服务器端程序一样,客户端程序也需要引用System.ServiceModel.dll.
8.VS2010提供的ServiceModel 元数据实用工具 (Svcutil.exe) 可以方便的创建客户端代码和配置文件. 我们这里就演示如何使用Svcutil.exe来配置客户端.
开始菜单-->所有程序-->Microsoft Visual Studio 2010-->Visual Studio Tools-->Visual Studio Command Prompt (2010). 打开VS2010命令提示行.接着导航到要放置客户端代码的目录。如果使用默认值创建客户端项目,则该目录为 C:\Users\<用户名>\My Documents\Visual Studio 10\Projects\Service\Client. 我对应的路径是D:\visual studio 2010\Projects\WCF\WcfServiceDemo\WcfClient.
在执行下面的命令前需要先启动WCF服务程序,也就是前面的WcfServiceDemo.exe,否则会报错.
接着执行如下命令 svcutil.exe /language:cs /out:generatedProxy.cs /config:app.config http://localhost:8000/ServiceModelSamples/service
运行完毕后,我们可以看到在WcfClient目录下生成了两个新文件,有了这两个文件我们就可以在客户端调用WCF服务程序上的方法了.
回到VS2010 IDE界面,将新生成的两个文件包含到WcfClient项目中.
这两个文件,一个是配置文件,一个是代理类;其实这两个文件完全可以自己手工写,但是既然可以自动生成,我们就偷点懒,使用Svcutil工具自动生成.下面是这两个文件的详细内容.
App.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_ICalculator" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="Message"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" /> </security> </binding> </wsHttpBinding> </bindings> <client> <endpoint address="http://localhost:8000/ServiceModelSamples/Service/CalculatorService" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator" contract="ICalculator" name="WSHttpBinding_ICalculator"> <identity> <userPrincipalName value="SZX-STATION168\Administrator" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>
generatedProxy.cs
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // Runtime Version:4.0.30319.296 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] [System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.ServiceModel.Samples", ConfigurationName="ICalculator")] public interface ICalculator { [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")] double Add(double n1, double n2); [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")] double Subtract(double n1, double n2); [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")] double Multiply(double n1, double n2); [System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")] double Divide(double n1, double n2); } [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] public interface ICalculatorChannel : ICalculator, System.ServiceModel.IClientChannel { } [System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] public partial class CalculatorClient : System.ServiceModel.ClientBase<ICalculator>, ICalculator { public CalculatorClient() { } public CalculatorClient(string endpointConfigurationName) : base(endpointConfigurationName) { } public CalculatorClient(string endpointConfigurationName, string remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : base(binding, remoteAddress) { } public double Add(double n1, double n2) { return base.Channel.Add(n1, n2); } public double Subtract(double n1, double n2) { return base.Channel.Subtract(n1, n2); } public double Multiply(double n1, double n2) { return base.Channel.Multiply(n1, n2); } public double Divide(double n1, double n2) { return base.Channel.Divide(n1, n2); } }
9.使用客户端调用WCF服务.
将program.cs重命名为Client, 并添加下面的代码.下面的代码是不是很熟悉,就像是一般的C#程序代码. 其实它就是实现了调用WCF服务的程序.
Client.cs
using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; namespace ServiceModelSamples { class Client { static void Main() { //Step 1: Create an endpoint address and an instance of the WCF Client. CalculatorClient client = new CalculatorClient(); // Step 2: Call the service operations. // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = client.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Call the Subtract service operation. value1 = 145.00D; value2 = 76.54D; result = client.Subtract(value1, value2); Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result); // Call the Multiply service operation. value1 = 9.00D; value2 = 81.25D; result = client.Multiply(value1, value2); Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result); // Call the Divide service operation. value1 = 22.00D; value2 = 7.00D; result = client.Divide(value1, value2); Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result); //Step 3: Closing the client gracefully closes the connection and cleans up resources. client.Close(); Console.WriteLine(); Console.WriteLine("Press <ENTER> to terminate client."); Console.ReadLine(); } } }
到这一步一个完整的WCF服务和客户端程序已经完成了.我们运行客户端程序看看效果.记住在运行客户端之前需要先启动WCF服务程序.我机器上WCF服务和客户端分别在以下位置:
D:\visual studio 2010\Projects\WCF\WcfServiceDemo\WcfServiceDemo\bin\Debug\WcfServiceDemo.exe
D:\visual studio 2010\Projects\WCF\WcfServiceDemo\WcfClient\bin\Debug\WcfClient.exe
客户端截图:
服务器端截图:
至此,一个WCF服务的创建和调用已经完成. 示例没有对程序细节做过多的解释,如定义服务协定,实现服务协定,绑定类型等. 本示例旨在演示如何创建一个可以运行的WCF服务程序, 通过完成示例,达到对WCF有个大概的了解.这个示例主要取材于MSDN上的例子,有兴趣的同学可以去看看http://msdn.microsoft.com/zh-cn/library/ms734712(v=vs.100).aspx,那里的介绍比我的详细很多.