这篇文章转自http://www.docin.com/p-59081680.html,但因为在原文有些地方我没读懂,后来又借鉴其他一些文章才写完整个代码,故在原文做了一些修改并重新整理,希望对您有所帮助!如果您在看的时候有疑惑,可留言或发邮件至:takako_yang@sina.com。
本文讲述的是最简单的WCF程序示例:如何在控制台应用程序实现和承载WCF服务,以及如何创建、配置和使用WCF客户端。
文章主体可分为两部分,分别介绍服务器端和客户端的变成实现。细分的话,可以分为五项任务。
·服务器端
定义WCF服务协定(任务一)
这是创建基本WCF服务和可以使用该服务的客户端所需的六项任务中的第一项任务。
创建基本WCF服务时,第一项任务是为与外界共享的服务创建协定,并在其中描述如何与该服务进行通信。
具体步骤为:
1、创建新的控制台应用程序项目。开启VS2010(或其他版本),在左上角"File"中选择"New"->"Project",选择"Visual C#"中的"Console Application",将项目的Name改成"TakakoService"。注意此时的命名空间也应该是"TakakoService",(命名空间很重要,后续要用到)。
2、右击"Solution"中的"TakakoService"项目,选择"Add Reference",在弹出的对话框中的".Net"选项卡中选择"System.ServiceModel",然后单击"OK"。
下面是编程步骤:
1、在program.cs中添加两个using语句,它们是:
using System.ServiceModel;
using System.ServiceModel.Description;
2、创建一个新的ICalculator接口,并将ServiceContractAttribute属性应用于该接口,并将Namespace值设置为http://TakakoService。此命名空间指定该服务在计算机上的路径,并构成该服务的基址部分。请注意,在通过采用方括号表示法的属性来批注接口或类时,该属性类可以从其名称中去掉"Attribute"部分。
[ServiceContract(Namespace = "http://TakakoService")]
public interface ICalculator
3、在接口中创建方法声明,并将OperationContract属性应用于每个要作为公共WCF协定的一部分公开的方法。
[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);
下面是创建服务协定的完整代码段:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace TakakoService
{
#region My Test
[ServiceContract(Namespace ="http://TakakoService")]
publicinterface 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);
}
}
定义WCF服务协定(任务二)
1、创建一个新的CalculatorService类,该类从用户定义的ICalculator接口继承而来并实现该接口定义的协定功能。
public class CalculatorService : ICalculator
2、实现每个算术运算符的功能。
在创建和实现了服务协定后,下一步是运行该服务。运行服务由三个步骤组成:配置、承载和打开服务。
{
publicdouble Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
publicdouble Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
publicdouble Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
publicdouble Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
}
在创建和实现了服务协定后,下一步是运行该服务。运行服务由三个步骤组成:配置、承载和打开服务。
配置、承载和运行服务(任务三)
· 为服务配置基址
为服务的基址创建URI实例。此URI指定HTTP方案、本地计算机、端口号8000,以及服务协定中为服务命名空间指定的服务路径 ServiceModelSample/Services。
· 承载服务
2、添加一个捕获CommunicationException的try catch语句,并在接下来的三个步骤中将该代码添加到try块中。
3、添加公开服务的终结点。为此,必须指定终结点公开的协议、绑定和终结点的地址。此例中,将ICalculator指定为协定,将WSHttpBinding指定为绑定,并将CalculatorService指定为地址。在这里注意,我们指定的是相对地址。终结点的完整地址是基址和终结点地址的组合。在此例中,完整地址是http://localhost:8000/ServiceModelSamples/Service/CalculatorService
{
selfHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService"
);
4、启用元数据交换。为此,必须添加服务元数据行为。首先创建一个ServiceMetadataBehavior实例,将HttpGetEnabled属性设置为true,然后为服务添加新行为。
{
selfHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService"
);
ServiceMetadataBehavior smb =new ServiceMetadataBehavior();
smb.HttpGetEnabled =true;
selfHost.Description.Behaviors.Add(smb);
5、打开ServiceHost并等待传入消息。用户按Enter键时,关闭ServiceHost。
{
selfHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService"
);
ServiceMetadataBehavior smb =new ServiceMetadataBehavior();
smb.HttpGetEnabled =true;
selfHost.Description.Behaviors.Add(smb);
selfHost.Open();
Console.WriteLine("The service is ready");
Console.WriteLine("Press<ENTER> to terminate service");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
下面是服务端(即“Service”项目中的Program.cs文件中)的完整程序代码:
using System.ServiceModel;
using System.ServiceModel.Description;
namespace TakakoService
{
#region My Test
[ServiceContract(Namespace ="http://TakakoService")]
publicinterface 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);
}
publicclass CalculatorService : ICalculator
{
publicdouble Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
publicdouble Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
publicdouble Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
publicdouble Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return:{0}", result);
return result;
}
}
#endregion
class Program
{
staticvoid Main(string[] args)
{
Test();
}
staticvoid Test()
{
Uri baseAddress =new Uri("http://localhost:8000/ServiceModelSamples/Service");
ServiceHost selfHost =new ServiceHost(typeof(CalculatorService), baseAddress);
try
{
selfHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService"
);
ServiceMetadataBehavior smb =new ServiceMetadataBehavior();
smb.HttpGetEnabled =true;
selfHost.Description.Behaviors.Add(smb);
selfHost.Open();
Console.WriteLine("The service is ready");
Console.WriteLine("Press<ENTER> to terminate service");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred:{0}", ce.Message);
selfHost.Abort();
}
}
}
}
若要运行服务,启动项目文件夹下bin目录中的Service.exe即可。
前面三篇文章是讲服务器端的部署和运行,下面讲讲客户端如何配置和使用。
创建和配置WCF客户端(任务四)
1、通过执行以下步骤,在Visual Studio中为客户端创建新项目:
1、在包含该服务(之前文章所述的服务)的同一解决方案中的“解决方案资源管理器”(位于右上角)中,右击当前解决方案,然后选择“添加新项目”。
2、在“添加新项目”的对话框中,选择“控制台应用程序”模板,然后将其命名为Client。使用默认的位置。
3、单击“确定”。
2、为项目提供对System.ServiceModel命名空间的引用:在“解决方案资源管理器”中右击"Service”项目,从".Net"选项卡上的“组件名称”列中选择"System.ServiceModel",然后单击“确定”。
3、为System.ServiceModel命名空间添加using语句:using System.ServiceModel;
4、启动在前面的步骤中创建的服务。(即打开在服务器项目中生成的Service.exe可执行文件,一定要开启,否则后续无法生成客户端所需文件)
5、这里和原文有点出入。我建议大家可以看这篇“通过SvcUtil.exe生成客户端代码和配置”http://www.cnblogs.com/cjfwu/archive/2010/05/21/1740895.html
这时会在你源代码的文件夹下多出两个代理文件来:output.config和CalculatorService.cs。在“解决方案资源管理器”中右击"Client”并选择“添加现有项”,然后选择前面生成的两个代理文件。到此,你的Client程序应该有3个文件:Program.cs, CalculationService.cs, output.config。
使用WCF客户端(任务五)
1、为要调用的服务的基址创建EndpointAddress实例,然后创建WCF Client对象。
CalculatorClient client =new CalculatorClient(new WSHttpBinding(), epAddress);
2、从Client内调用客户端操作。
double value2 =15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1})={2}", value1, value2, result);
value1 =145.00D;
value2 =76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1})={2}", value1, value2, result);
value1 =22.00D;
value2 =7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1})={2}", value1, value2, result);
3、在WCF客户端上调用Close。
下面是客户端的完整代码:
{
class Program
{
staticvoid Main(string[] args)
{
EndpointAddress epAddress =new EndpointAddress("http://localhost:8000/ServiceModelSamples/Service/CalculatorService");
CalculatorClient client =new CalculatorClient(new WSHttpBinding(), epAddress);
double value1 =100.00D;
double value2 =15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1})={2}", value1, value2, result);
value1 =145.00D;
value2 =76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1})={2}", value1, value2, result);
value1 =22.00D;
value2 =7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1})={2}", value1, value2, result);
client.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client");
Console.ReadLine();
}
}
}
先启动Server端,就是先debug第一个程式(或者直接双击其bin文件夹下的.exe),再启动Client端,就是debug第二个程式(或者直接双击其bin文件夹下的.exe)。
如果您看到第一个dos界面如下所述,证明这段程式调试成功。
The service is ready
Press<ENTER> to terminate service
Received Add(100,15.99)
Return:115.99
Received Subtract(145,76.54)
Return:68.46
Received Divide(22,7)
Return:3.14285714285714