很多学习WCF的例子,感觉受益匪浅,但是由于每个人学习的侧重点不同,一些很详细的细节例如每一个属性都是用来干什么的,建立不同的项目类型对创建的服务有什么区别等等,都不得而知。终于,在MSDN上发现了一篇入门教程。讲解的十分基本,十分详细,想进到每一个细节,然我彻底了解入门的每一个细节,整个教程结构清晰,代码简洁,讲解细致,值得推荐。
地址: http://msdn.microsoft.com/en-us/library/ms734712.aspx
做这分5部来讲解创建一个最基本的基于B/S构架的WCF应用。服务是根据输入的两个数字,返回这两个数字的加减乘除运算结果。
第一步:定义WCF服务契约(创建项目,加入引用,定义Interface)
第二部:引入WCF服务契约(添加具体服务函数)
第三部:构架WCF服务,运行WCF服务(添加Uri,定义服务对象地址,运行服务)
第四部:利用工具访问服务,自动生成WCF服务代理的代码文件
第五部:配置一个简单的WCF客户端(用客户端引入服务代理,通过服务代理来访问服务)
第六部:运行程序
How to: Define a Windows Communication Foundation Service Contract
How to: Implement a Windows Communication Foundation Service Contract
How to: Host and Run a Basic Windows Communication Foundation Service
How to: Create a Windows Communication Foundation Client
How to: Configure a Basic Windows Communication Foundation Client
How to: Use a Windows Communication Foundation Client
先建立一个解决方案。
在这个解决方案下面建立一个叫做Server的控制台应用项目,再建立一个叫做Client的控制台应用项目。
分别给每一个项目添加引用到System.ServiceModel
view plaincopy to clipboardprint? using System; using System.ServiceModel; using System.ServiceModel.Description; namespace Microsoft.ServiceModel.Samples { // Define a service contract. [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")] public interface ICalculator { [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); } // Service class that implements the service contract. // Added code to write output to the console window. public class CalculatorService : ICalculator { public double Add(double n1, double n2) { double result = n1 + n2; Console.WriteLine("Received Add({0},{1})", n1, n2); 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; } } 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 1 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(); } } } } using System; using System.ServiceModel; using System.ServiceModel.Description; namespace Microsoft.ServiceModel.Samples { // Define a service contract. [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")] public interface ICalculator { [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); } // Service class that implements the service contract. // Added code to write output to the console window. public class CalculatorService : ICalculator { public double Add(double n1, double n2) { double result = n1 + n2; Console.WriteLine("Received Add({0},{1})", n1, n2); 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; } } 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 1 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(); } } } }
服务端创建好了以后,就可以试运行了。
这时候可以用微软提供的命令行工具访问这个服务,生成服务代理 app.config 和 generatedProxy.cs两个文件。
PATH=C:\WINDOWS\Microsoft.NET\Framework\v3.5
DataSvcUtil.exe /language:csharp /out:generatedProxy.cs /config:app.config http://localhost:8000/ServiceModelSamples/service
注意:实在server运行的时候,生成包装类。
当然,如果是已经运行的服务,可以使用VS引用就行了。
把这两个文件添加到客户端项目里去。
现在就可以编辑客户端代码了。
1 view plaincopy to clipboardprint?
2 using System;
3 using System.Collections.Generic;
4 using System.Text;
5 using System.ServiceModel;
6
7 namespace ServiceModelSamples
8 {
9
10 class Client
11 {
12 static void Main()
13 {
14 //Step 1: Create an endpoint address and an instance of the WCF Client.
15 EndpointAddress epAddress = new EndpointAddress("http://localhost:8000/ServiceModelSamples/Service/CalculatorService");
16 CalculatorClient client = new CalculatorClient(new WSHttpBinding(), epAddress);
17
18
19 // Step 2: Call the service operations.
20 // Call the Add service operation.
21 double value1 = 100.00D;
22 double value2 = 15.99D;
23 double result = client.Add(value1, value2);
24 Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
25
26 // Call the Subtract service operation.
27 value1 = 145.00D;
28 value2 = 76.54D;
29 result = client.Subtract(value1, value2);
30 Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
31
32 // Call the Multiply service operation.
33 value1 = 9.00D;
34 value2 = 81.25D;
35 result = client.Multiply(value1, value2);
36 Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
37
38 // Call the Divide service operation.
39 value1 = 22.00D;
40 value2 = 7.00D;
41 result = client.Divide(value1, value2);
42 Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
43
44 //Step 3: Closing the client gracefully closes the connection and cleans up resources.
45 client.Close();
46
47 Console.WriteLine();
48 Console.WriteLine("Press <ENTER> to terminate client.");
49 Console.ReadLine();
50
51
52 }
53 }
54 }
55 using System;
56 using System.Collections.Generic;
57 using System.Text;
58 using System.ServiceModel;
59
60 namespace ServiceModelSamples
61 {
62
63 class Client
64 {
65 static void Main()
66 {
67 //Step 1: Create an endpoint address and an instance of the WCF Client.
68 EndpointAddress epAddress = new EndpointAddress("http://localhost:8000/ServiceModelSamples/Service/CalculatorService");
69 CalculatorClient client = new CalculatorClient(new WSHttpBinding(), epAddress);
70
71
72 // Step 2: Call the service operations.
73 // Call the Add service operation.
74 double value1 = 100.00D;
75 double value2 = 15.99D;
76 double result = client.Add(value1, value2);
77 Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
78
79 // Call the Subtract service operation.
80 value1 = 145.00D;
81 value2 = 76.54D;
82 result = client.Subtract(value1, value2);
83 Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
84
85 // Call the Multiply service operation.
86 value1 = 9.00D;
87 value2 = 81.25D;
88 result = client.Multiply(value1, value2);
89 Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
90
91 // Call the Divide service operation.
92 value1 = 22.00D;
93 value2 = 7.00D;
94 result = client.Divide(value1, value2);
95 Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
96
97 //Step 3: Closing the client gracefully closes the connection and cleans up resources.
98 client.Close();
99
100 Console.WriteLine();
101 Console.WriteLine("Press <ENTER> to terminate client.");
102 Console.ReadLine();
103
104
105 }
106 }
107 }
每一个细节都包含在上面的这两个Program.cs文件中了,你大概看一下就会懂。比院子里大多数教材说得都清晰,特别适合像我一样爱刨根问底的初学者。:)
最后编译程序,试运行。(两个都是命令行程序,直接到那个编译好的目录里去找那个exe文件运行,先运行服务,再运行客户端)。