WCF入门教程
这一系列文章的内容是从msdn中copy过来的,讲述的是最简单的wcf程序示例:如何在控制台应用程序实现和承载wcf服务,以及如何创建、配置和使用wcf客户端。
文章主体可分为两部分,分别介绍服务器端和客户端的编程实现。细分的话,可以分为六项任务。
- 服务器端
定义wcf服务协定(任务一)
这是创建基本 windows communication foundation (wcf) 服务和可以使用该服务的客户端所需的六项任务中的第一项任务。
创建基本 wcf 服务时,第一项任务是为与外界共享的服务创建协定,并在其中描述如何与该服务进行通信。
具体步骤为:
1、 创建新的控制台应用程序项目。 在“新建项目”对话框中,选中“visual basic”或“visual c#”,并选择“控制台应用程序”模板,并命名为service。 使用默认的位置。
2、将默认的service 命名空间更改为 microsoft.servicemodel.samples。
3、为项目提供对 system.servicemodel 命名空间的引用:右击“解决方案资源管理器”中的“service”项目,选择“添加引用”项,在弹出的对话框中的“.net”选项卡里的“组件名称”中选择“system.servicemodel”,然后单击“确定”。
下面是编程步骤:
1、为 system.servicemodel 命名空间添加一个 using 语句。
using system.servicemodel;
2、创建一个新的icalculator 接口,并将 servicecontractattribute 属性应用于该接口,并将 namespace 值设置为“http://microsoft.servicemodel.samples”。 此命名空间指定该服务在计算机上的路径,并构成该服务的基址部分。 请注意,在通过采用方括号表示法的属性来批注接口或类时,该属性类可以从其名称中去掉“attribute”部分。
[servicecontract(namespace = "http://microsoft.servicemodel.samples")]
public interface icalculator
3、在接口中创建方法声明,并将 operationcontractattribute 属性应用于每个要作为公共 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;
// add the using statement for the sytem.servicemodel namespace
using system.servicemodel;
namespace microsoft.servicemodel.samples
{
// define a service contract.
[servicecontract(namespace = "http://microsoft.servicemodel.samples")]
public interface icalculator
{
// 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);
}
}
........(整个服务器端的代码未完,等讲完任务三时,再给出完整代码)
实现wcf服务协定(任务二)
1、创建一个新 calculatorservice 类,该类从用户定义的 icalculator 接口继承而来并实现该接口定义的协定功能。
public class calculatorservice : icalculator
2、实现每个算术运算符的功能。
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;
}
在创建和实现了服务协定后,下一步是运行该服务。 运行服务由三个步骤组成:配置、承载和打开服务。
配置、承载和运行服务(任务三)
- 为服务配置基址
为服务的基址创建 uri 实例。 此 uri 指定 http 方案、本地计算机、端口号 8000,以及服务协定中为服务命名空间指定的服务路径servicemodelsample/services。
uri baseaddress = new uri("http://localhost:8000/servicemodelsamples/service");
- 承载服务
- 创建一个新的 servicehost 实例以承载服务。 必须指定实现服务协定和基址的类型。 对于此示例,我们将基址指定为http://localhost:8000/servicemodelsamples/services,并将 calculatorservice 指定为实现服务协定的类型。
servicehost selfhost = new servicehost(typeof(calculatorservice), baseaddress); |
- 添加一个捕获 communicationexception 的 try-catch 语句,并在接下来的三个步骤中将该代码添加到 try 块中。
- 添加公开服务的终结点。 为此,必须指定终结点公开的协议、绑定和终结点的地址。 此例中,将 icalculator 指定为协定,将 wshttpbinding 指定为绑定,并将 calculatorservice 指定为地址。 在这里请注意,我们指定的是相对地址。 终结点的完整地址是基址和终结点地址的组合。 在此例中,完整地址是 http://localhost:8000/servicemodelsamples/services/calculatorservice。
selfhost.addserviceendpoint( typeof(icalculator), new wshttpbinding(), "calculatorservice"); |
- 启用元数据交换。 为此,必须添加服务元数据行为。 首先创建一个 servicemetadatabehavior 实例,将 httpgetenabled 属性设置为 true,然后为服务添加新行为。
servicemetadatabehavior smb = new servicemetadatabehavior(); smb.httpgetenabled = true; selfhost.description.behaviors.add(smb); |
- 打开 servicehost 并等待传入消息。 用户按 enter 键时,关闭 servicehost。
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();
下面是服务器端(即“service”项目中program.cs文件中)的完整程序代码:
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)
{
// create a uri to serve as the base address.
uri baseaddress = new uri("http://localhost:8000/servicemodelsamples/service");
// create servicehost
servicehost selfhost = new servicehost(typeof(calculatorservice), baseaddress);
try
{
// add a service endpoint.
selfhost.addserviceendpoint(
typeof(icalculator),
new wshttpbinding(),
"calculatorservice");
// enable metadata exchange.
servicemetadatabehavior smb = new servicemetadatabehavior();
smb.httpgetenabled = true;
selfhost.description.behaviors.add(smb);
// 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();
}
}
}
}
若要运行服务,启动项目文件夹下bin目录中的 service.exe即可。
前面三篇文章是讲服务器端的部署和运行,下面讲讲客户端如何配置和使用。
创建wcf客户端(任务四)
-
通过执行以下步骤,在 visual studio 2005 中为客户端创建新项目:
- 在包含该服务(之前文章所述的服务)的同一解决方案中的“解决方案资源管理器”(位于右上角)中,右击当前解决方案,然后选择“添加新项目”。
- 在“添加新项目”对话框中,选择“visual basic”或“visual c#”,选择“控制台应用程序”模板,然后将其命名为 client。 使用默认的位置。
- 单击“确定”。
- 为项目提供对 system.servicemodel 命名空间的引用:在“解决方案资源管理器”中右击“service”项目,从“.net”选项卡上的“组件名称”列中选择“system.servicemodel”,然后单击“确定”。
- 为 system.servicemodel 命名空间添加 using 语句:using system.servicemodel;
- 启动在前面的步骤中创建的服务。(即打开在服务器项目中生成的service.exe可执行文件)
-
通过执行以下步骤,使用适当的开关运行service model metadata utility tool (svcutil.exe) 以创建客户端代码和配置文件:
- 通过选择“开始”菜单中的“microsoft windows sdk”项下的“cmd shell”,启动 windows sdk 控制台会话。
- 导航到要放置客户端代码的目录。 如果使用默认设置创建 client 项目,则目录为 c:\documents and settings\<用户名>\documents\visual studio 2008\projects\service\client。
- 将命令行工具service model metadata utility tool (svcutil.exe) 与适当的开关一起使用以创建客户端代码。 下面的示例生成服务的代码文件和配置文件。
svcutil.exe /language:cs /out:generatedproxy.cs /config:app.config http://localhost:8000/servicemodelsamples/service
- 在 visual studio 中将生成的代理添加到 client 项目中,方法是在“解决方案资源管理器”中右击“client”并选择“添加现有项”。 然后选择在上一步中生成的 generatedproxy.cs 文件。
配置wcf客户端(任务五)
在 visual studio 中,将在前一过程中生成的 app.config 配置文件添加到客户端项目中。 在“解决方案资源管理器”中右击该客户端,选择“添加现有项”,然后从 c:\documents and settings\<用户名>\documents\visual studio 2008\projects\service\client\bin 目录中选择 app.config 配置文件。
将app.config添加到项目中后,就算是完成了wcf客户端的配置。因为具体的配置信息,我们在使用svcutil.exe工具时,它就帮我们配置好并写入了app.config文件。
使用wcf客户端(任务六)
1、为要调用的服务的基址创建 endpointaddress 实例,然后创建 wcf client 对象。
//create an endpoint address and an instance of the wcf client.
endpointaddress epaddress = new endpointaddress("http://localhost:8000/servicemodelsamples/service/calculatorservice");
calculatorclient client = new calculatorclient(new wshttpbinding(), epaddress);
2、从 client 内调用客户端操作。
// 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);
3、在 wcf 客户端上调用 close。
// closing the client gracefully closes the connection and cleans up resources.
client.close();
下面是客户端的完整代码:
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.
endpointaddress epaddress = new endpointaddress("http://localhost:8000/servicemodelsamples/service/calculatorservice");
calculatorclient client = new calculatorclient(new wshttpbinding(), epaddress);
// 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();
}
}
}
若要启动客户端,请在“开始”菜单中的“microsoft windows sdk”项下选择“cmd shell”,从而启动 windows sdk 控制台会话。 定位至 c:\documents and settings\<用户名>\documents\visual studio 2008\projects\service\client\obj\debug 目录,键入 client,然后按enter。 操作请求和响应将出现在客户端控制台窗口中,如下所示。
add(100,15.99) = 115.99
subtract(145,76.54) = 68.46
multiply(9,81.25) = 731.25
divide(22,7) = 3.14285714285714
press <enter> to terminate client.
最后,附上我的asp.net学习群,欢迎各位同行入群指导交流。技术群:【asp.net技术社区】872894940