http://msdn.microsoft.com/en-us/library/ms734712.aspx

本节中包含的主题旨在帮助您快速了解 Windows Communication Foundation (WCF) 编程体验。这些主题要根据本主题底部的列表中的顺序完成。通过学习本教程,您可以初步了解创建 WCF 服务和客户端应用程序所需的步骤。服务是一种构造,它公开一个或多个终结点,其中每个终结点都公开一项或多项服务操作。服务的终结点指定下列信息:服务所在的位置;一个绑定,其中包含客户端必须与服务进行通信的信息;一个协定,用于定义服务向其客户端提供的功能。

在完成本教程中的系列主题之后,您将会得到一个正在运行的服务,以及一个可以调用该服务的操作的客户端。前三个主题描述如何使用协定定义服务,如何实现服务,以及如何在代码中配置服务、承载服务和运行服务。所创建的服务是自承载服务,客户端和服务都在同一计算机上运行。服务使用代码而非配置进行配置。另外还可以将服务承载于 Internet 信息服务 (IIS) 下。有关如何执行此操作的更多信息,请参见如何:如何:在 IIS 中承载 WCF 服务。也可以在配置文件中配置服务。有关使用配置文件的更多信息,请参见使用配置文件配置服务

后三个主题描述如何创建客户端代理,如何配置客户端应用程序,以及如何创建和使用可以访问服务功能的客户端。服务会发布可以访问的元数据,这些数据定义了客户端应用程序与服务操作进行通信所需的构造。WCF 提供了一个 ServiceModel 元数据实用工具 (Svcutil.exe) 来自动完成以下过程:访问发布的这些元数据,然后使用这些元数据来构造和配置服务的客户端应用程序。

本节中的所有主题均假定您使用 Visual Studio 2010 作为开发环境。如果您使用的是其他开发环境,请忽略特定于 Visual Studio 的说明。

Description: ms734712.note(zh-cn,VS.100).gif注意:

如果运行的是 Windows Vista,则必须通过转到开始菜单,然后右击 Visual Studio 2010 并选择以管理员身份运行来启动 Visual Studio。若要始终以管理员身份启动 Visual Studio 2010,可以创建一个快捷方式,右击该快捷方式,选择属性,选择兼容性选项卡,然后选中请以管理员身份运行该程序复选框。当您使用此快捷方式启动 Visual Studio 2010 时,它将始终以管理员身份运行。

有关可以下载到硬盘中并运行的示例应用程序,请参见 Windows Communication Foundation Samples中的主题。有关专门针对本主题的示例,请参见入门示例

有关创建服务和客户端的更深入信息,请参见基本 WCF 编程

本节内

如何:定义 Windows Communication Foundation 服务协定

描述如何使用用户定义的接口创建 WCF 协定。协定用于定义服务向外界提供的功能,并向外界的潜在用户描述如何与服务进行通信

如何:实现 Windows Communication Foundation 服务协定

描述如何实现服务协定。创建了协定后,必须在一个从定义协定的接口继承的类中实现服务所提供的功能

如何:承载和运行基本的 Windows Communication Foundation 服务

描述如何在代码中配置服务的终结点,以及如何在控制台应用程序内承载服务和启动服务。若要激活服务,必须在运行时环境中配置和承载服务。此环境将创建服务并控制其上下文和生存期

如何:创建 Windows Communication Foundation 客户端

描述如何从 WCF 服务检索用于创建 WCF 客户端的元数据。此过程使用由 WCF 提供的 ServiceModel 元数据实用工具 (Svcutil.exe)

如何:配置基本 Windows Communication Foundation 客户端

描述如何配置使用 ServiceModel 元数据实用工具 (Svcutil.exe) 创建的基本客户端。配置客户端需要指定客户端用于访问服务的终结点

如何:使用 Windows Communication Foundation 客户端

描述如何使用 ServiceModel 元数据实用工具 (Svcutil.exe) 生成的 WCF 客户端代理来调用服务所提供的功能

如何:定义 Windows Communication Foundation 服务协定

.NET Framework 4

这是创建基本 Windows Communication Foundation (WCF) 服务和可以调用该服务的客户端所需的六项任务中的第一项任务。有关全部六项任务的概述,请参见入门教程1主题。

创建基本 WCF 服务时,第一项任务是定义协定。协定指定服务支持的操作。可以将操作视为一个 Web 服务方法。通过定义 C++C# Visual Basic (VB) 接口可创建协定。接口中的每个方法都对应于特定的服务操作。每个接口都必须将 ServiceContractAttribute2 应用于自身,而每个操作都必须将 OperationContractAttribute3 应用于自身。如果接口中的一个方法具有 ServiceContractAttribute 而没有 OperationContractAttribute,则不公开该方法。

在操作过程后面的示例中提供了用于此任务的代码。

使用接口创建 Windows Communication Foundation

  1. 通过在“开始”菜单中右击“Visual Studio 2010”并选择“以管理员身份运行”,以管理员身份打开该程序。
  2. 创建新的控制台应用程序项目。单击“文件”菜单,选择“新建”,然后选择“项目”。在“新��项目”对话框中,选择“Visual Basic”或“Visual C#”,选择“控制台应用程序”模板,然后将其命名为 Service。使用默认的“位置”。
  3. 对于 C# 项目,Visual Studio 会创建名为 Program.cs 的文件。此类会包含名为 Main() 的空方法。对于 VB 项目,Visual Studio 会创建名为 Module1.vb 的文件,其中包含名为 Main() 的空子例程。控制台应用程序项目需要这些方法才能正确生成,因此您可以放心地将这些方法保留在项目中。
  4. 将默认的 Service 命名空间更改为 Microsoft.ServiceModel.Samples。为此,请在“解决方案资源管理器”中,右击项目,并选择“属性”。确保选择了“属性”对话框左侧的“应用程序”选项卡。对于 C# 项目,在标有“默认命名空间”的编辑框中键入 Microsoft.ServiceModel.Samples。对于 VB 项目,在标有“根命名空间”的编辑框中键入Microsoft.ServiceModel.Samples。单击“文件”菜单,然后选择“全部保存”以保存更改。
  5. 如果使用 C#,请在生成的 Program.cs 文件中将命名空间更改为 Microsoft.ServiceModel.Samples,如下面的示例所示。

C#

namespace Microsoft.ServiceModel.Samples 
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}
 

如果使用 VB,请将 Namespace 语句和 End Namespace 语句添加到生成的 Module1.vb 中,如下面的示例所示。

VB

Namespace Microsoft.ServiceModel.Samples
    Module Module1
        Sub Main()
        End Sub 
    End Module 
End Namespace 
 
  1. 将对 System.ServiceModel.dll 的引用添加到项目:
    1. 解决方案资源管理器中,右击项目文件夹下的引用文件夹,然后选择添加引用
    2. 添加引用对话框中选择“.NET”选项卡,向下滚动屏幕,看到“System.ServiceModel”(版本 4.0.0.0)后,将其选中,然后单击确定

Description: ms731835.note(zh-cn,VS.100).gif注意:

在使用命令行编译器(例如 Csc.exe Vbc.exe)时,还必须提供程序集的路径。例如,默认情况下,在运行 Windows Vista 的计算机上,路径为:Windows\Microsoft.NET\Framework\v4.0”

  1. 为 System.ServiceModel 命名空间添加一个 using 语句(在 Visual Basic 中为 Imports)。

C#

using System.ServiceModel;
 
  1. 定义一个名为 ICalculator 的新接口,并向该接口应用 Namespace4 值为“http://Microsoft.ServiceModel.Samples”的 ServiceContractAttribute 特性。显式指定命名空间是一种最佳做法,因为这样可防止将默认命名空间值添加到协定名称。

Description: ms731835.note(zh-cn,VS.100).gif注意:

使用特性给接口或类添加批注时,可以从特性名称中去掉Attribute部分。因此 ServiceContractAttribute  C# 中为 [ServiceContract],在 Visual Basic 中为 <ServiceContract>

  1. C#
10. [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
11. public interface ICalculator
12.  

13. 在接口中为 ICalculator 协定公开的每个操作(加、减、乘和除)声明一个方法,并对希望作为公共 WCF 协定的一部分公开的每个方法应用OperationContractAttribute 特性。

C#

[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);
 

下面的代码示例演示一个定义服务协定的基本接口。

C#

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);
  }
}
 

现在已创建接口,继续按照如何:实现 Windows Communication Foundation 服务协定5中的说明实现该接口。有关疑难解答信息,请参见入门教程疑难解答6


如何:实现 Windows Communication Foundation 服务协定

.NET Framework 4

这是创建基本 Windows Communication Foundation (WCF) 服务和可以调用该服务的客户端所需的六项任务中的第二项任务。有关全部六项任务的概述,请参见入门教程1主题。

创建 WCF 服务要求首先创建使用接口定义的协定。有关创建该接口的更多信息,请参见如何:定义 Windows Communication Foundation 服务协定2。本示例中显示的下一步骤是实现接口。这涉及到创建一个名为 CalculatorService 的类,该类实现用户定义的 ICalculator 接口。在操作过程后面的示例中提供了用于此任务的代码。

实现 WCF 服务协

  1. 在定义了 ICalculator 接口的同一文件中创建一个名为 CalculatorService 的新类。CalculatorService 实现 ICalculator 接口。

C#

public class CalculatorService : ICalculator
 
  1. 在 CalculatorService 类中实现在 ICalculator 接口中定义的每个方法。

C#

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;
}
 

Description: ms734686.note(zh-cn,VS.100).gif注意:

已经添加写入输出代码以方便测试。

下面的代码示例演示定义协定的接口和接口的实现。

C#

using System;
using System.ServiceModel;
 
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);
    }
 
    // 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;
        }
    }
}
 

现在已创建并实现了服务协定。生成该解决方案以确保不存在编译错误,然后按照如何:承载和运行基本的 Windows Communication Foundation 服务3中的说明运行服务。有关疑难解答信息,请参见入门教程疑难解答4

编译代

如果使用的是命令行编译器,则必须引用 System.ServiceModel 程序集。

如果使用的是 Visual Studio,请在生成菜单上单击生成解决方案(或按 Ctrl+Shift+B)。


如何:承载和运行基本的 Windows Communication Foundation 服务

.NET Framework 4

这是创建基本 Windows Communication Foundation (WCF) 服务和可以调用该服务的客户端所需的六项任务中的第三项任务。有关全部六项任务的概述,请参见入门教程1主题。

本主题描述如何运行基本的 Windows Communication Foundation (WCF) 服务。此过程包含以下步骤:

  • 为服务创建基址。
  • 为服务创建服务主机。
  • 启用元数据交换。
  • 打开服务主机。

在过程后面的以下示例中提供了在此任务中编写的代码的完整清单。将下面的代码添加到 Program 类中定义的 Main() 方法。此类是在您创建 Service 解决方案时生成的。

为服务配置基

  1. 为服务的基址创建 Uri2 实例。此 URI 指定 HTTP 方案、本地计算机、端口号 8000,以及服务协定中为服务命名空间指定的服务路径 ServiceModelSample/Service。

C#

Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");
 

承载服

  1. 导入 System.ServiceModel.Description 命名空间。这行代码应该与 using 或 imports 语句的其余部分一起放置在 Program.cs/Program.vb 文件的顶部。

C#

using System.ServiceModel.Description;
 
  1. 创建一个新的 ServiceHost3 实例以承载服务。必须指定实现服务协定和基址的类型。对于此示例,基址为http://localhost:8000/ServiceModelSamples/Service,CalculatorService 为实现服务协定的类型。

C#

ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);
 
  1. 添加一个捕获 CommunicationException4 的 try-catch 语句,并在接下来的三个步骤中将该代码添加到 try 块中。catch 子句应该显示错误信息,然后调用selfHost.Abort()。

C#

try 
{
    // ... 
}
catch (CommunicationException ce)
{
    Console.WriteLine("An exception occurred: {0}", ce.Message);
    selfHost.Abort();
}
 
  1. 添加公开服务的终结点。为此,必须指定终结点公开的协议、绑定和终结点的地址。对于此示例,将 ICalculator 指定为协定,将 WSHttpBinding 指定为绑定,并将CalculatorService 指定为地址。在这里请注意,终结点地址是相对地址。终结点的完整地址是基址和终结点地址的组合。在此例中,完整地址是http://localhost:8000/ServiceModelSamples/Service/CalculatorService。

C#

selfHost.AddServiceEndpoint(
    typeof(ICalculator),
    new WSHttpBinding(),
    "CalculatorService");
 

Description: ms730935.note(zh-cn,VS.100).gif注意:

.NET Framework 4 开始,如果未显式配置服务的任何终结点,则当打开 ServiceHost 时,运行时将添加默认终结点。此示例显式添加了一个终结点,以提供如何执行此操作的示例。有关默认终结点、绑定和行为的更多信息,请参见简化配置5 WCF 服务的简化配置6

  1. 启用元数据交换。为此,添加服务元数据行为。首先创建一个 ServiceMetadataBehavior7 实例,将 HttpGetEnabled8 属性设置为 true,然后为服务添加新行为。有关发布元数据时出现的安全问题的更多信息,请参见Security Considerations with Metadata9。

C#

ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
 
  1. 打开 ServiceHost 并等待传入消息。用户按 Enter 键时,关闭 ServiceHost。

C#

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();
 

验证服务是否正常运

  1. 从 Visual Studio 内部运行 service.exe。在 Windows Vista 上运行时,必须使用管理员特权运行服务。由于 Visual Studio 是使用管理员特权运行的,因此 service.exe 也是使用管理员特权运行的。也可以启动新的命令提示,使用管理员特权运行它,并在其中运行 service.exe。
  2. 打开 Internet Explorer,并浏览到服务的调试页(网址为 http://localhost:8000/ServiceModelSamples/Service)。

下面的示例包括本教程中前面步骤的服务协定和实现,并将服务承载于控制台应用程序中。将以下内容编译为可执行文件 Service.exe

在编译代码时,务必引用 System.ServiceModel.dll

C#

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 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();
            }
 
        }
    }
}
 

Description: ms730935.note(zh-cn,VS.100).gif注意:

此类服务需要在计算机上注册 HTTP 地址以进行侦听的权限。管理员帐户具有此权限,但必须授予非管理员帐户对 HTTP 命名空间的权限。有关如何配置命名空间保留的更多信息,请参见配置 HTTP HTTPS10。在 Visual Studio 下运行时,必须使用管理员特权运行 service.exe

此时服务正在运行。继续执行如何:创建 Windows Communication Foundation 客户端11中的步骤。有关疑难解答信息,请参见入门教程疑难解答12


如何:创建 Windows Communication Foundation 客户端

.NET Framework 4

这是创建基本 Windows Communication Foundation (WCF) 服务和可以调用该服务的客户端所需的六项任务中的第四项任务。有关全部六项任务的概述,请参见入门教程1主题。

本主题描述如何检索 WCF 服务中的元数据,以及如何使用这些元数据创建可以访问该服务的 WCF 代理。此任务是通过使用 WCF 所提供的 ServiceModel 元数据实用工具 (Svcutil.exe)2 完成的。此工具可以获取服务的元数据,并使用所选语言生成代理的托管源代码文件。除了创建客户端代理外,该工具还会为客户端创建配置文件,以使客户端应用程序能够连接至其某个终结点上的服务。

Description: ms733133.note(zh-cn,VS.100).gif注意:

可以在 Visual Studio 2010 中向客户端项目添加服务引用,以便在不使用 ServiceModel 元数据实用工具 (Svcutil.exe)2 的情况下创建客户端代理。

Description: ms733133.Warning(zh-cn,VS.100).gif 警告:

当在 Visual Studio 2010 中从某个类库项目调用 WCF 服务时,可以使用添加服务引用功能自动生成代理和关联配置文件。该类库项目不会使用配置文件。需要将配置文件复制到包含调用该类库的可执行文件的目录中。

客户端应用程序使用生成的代理创建 WCF 客户端对象。如何:使用 Windows Communication Foundation 客户端3中对此过程进行了描述。

在操作过程后面的示例中提供了用于此任务产生的客户端的代码。

创建 Windows Communication Foundation 客户

  1. 通过执行以下步骤,在 Visual Studio 2010 中在当前解决方案中为客户端创建一个新项目:
  2. 为项目添加对 System.ServiceModel.dll 的引用:
    1. 在包含该服务的同一解决方案中的解决方案资源管理器(位于右上角)中,右击当前解决方案(而不是项目),选择添加,然后选择新项目
    2. 添加新项目对话框中,选择“Visual Basic”“Visual C#”,选择控制台应用程序模板,然后将其命名为 Client。使用默认的位置。
    3. 单击确定
    1. 解决方案资源管理器中的“Client”项目下右击引用文件夹,然后选择添加引用
    2. 选择“.NET”选项卡,从列表框中选择“System.ServiceModel.dll”(版本 4.0.0.0),然后单击确定

Description: ms733133.note(zh-cn,VS.100).gif注意:

在使用命令行编译器(例如 Csc.exe Vbc.exe)时,还必须提供程序集的路径。例如,默认情况下,在运行 Windows Vista 的计算机上,路径为:Windows\Microsoft.NET\Framework\v4.0

  1. 在生成的 Program.cs 或 Program.vb 文件中为 System.ServiceModel 命名空间添加一个 using 语句(在 Visual Basic 中为 Imports)。

C#

using System.ServiceModel;
  1. 在 Visual Studio 中,按 F5 启动在前面的主题中创建的服务。有关更多信息,请参见 如何:承载和运行基本的 Windows Communication Foundation 服务4.
  2. 通过执行以下步骤,使用适当的开关运行ServiceModel 元数据实用工具 (Svcutil.exe)2 以创建客户端代码和配置文件:
    1. 开始菜单上,单击所有程序,然后单击“Visual Studio 2010”。单击“Visual Studio 工具,然后单击“Visual Studio 2010 命令提示
    2. 导航到要放置客户端代码的目录。如果使用默认&#20540;创建客户端项目,则该目录为 C:\Users\<用户名>\My Documents\Visual Studio 10\Projects\Service\Client
    3. 将命令行工具ServiceModel 元数据实用工具 (Svcutil.exe)2 与适当的开关一起使用以创建客户端代码。下面的示例生成服务的代码文件和配置文件。

C#

svcutil.exe /language:cs /out:generatedProxy.cs /config:app.config http://localhost:8000/ServiceModelSamples/service 

默认情况下,将在一个以服务命名的文件(例如,在本示例中将为 CalculatorService.cs CalculatorService.vb,其扩展名与编程语言相对应:.vb 对应于 Visual Basic.cs 对应于 C#)中生成客户端代理代码。/out 开关会将客户端代理文件的名称更改为 GeneratedProxy.cs/config 开关会将客户端配置文件的名称从默认的 Output.config 更改为 App.config。请注意,这些文件都是在 C:\Users\<用户名>\My Documents\Visual Studio 10\Projects\Service\Client 目录中生成的。

  1. 在 Visual Studio 中将生成的代理添加到该客户端项目中,方法是在“解决方案资源管理器”中右击该客户端项目,选择“添加”,然后选择“现有项”。选择上面的步骤中生成的“generatedProxy”文件。

此示例演示由ServiceModel 元数据实用工具 (Svcutil.exe)2 生成的客户端代码。

C#

 
//------------------------------------------------------------------------------ 
// <auto-generated> 
//     This code was generated by a tool. 
//     Runtime Version:2.0.50727.1366 
// 
//     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", "3.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", "3.0.0.0")]
public interface ICalculatorChannel : ICalculator, System.ServiceModel.IClientChannel
{
}
 
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.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);
    }
}
 
 

现在您已经创建了一个 Windows Communication Foundation (WCF) 客户端。请继续执行如何:配置基本 Windows Communication Foundation 客户端5中的步骤配置该客户端。有关疑难解答信息,请参见入门教程疑难解答6

如何:配置基本 Windows Communication Foundation 客户端

.NET Framework 4

这是创建基本 Windows Communication Foundation (WCF) 服务和可以调用该服务的客户端所需的六项任务中的第五项任务。有关全部六项任务的概述,请参见入门教程1主题。

本主题要将使用ServiceModel 元数据实用工具 (Svcutil.exe)2 生成的客户端配置文件添加到客户端项目中,并解释客户端配置元素的内容。配置客户端包括指定客户端用于访问服务的终结点。每个终结点都有一个地址、一个绑定和一个协定,所有这些元素都必须在配置客户端的过程中指定。

在过程后面的示例中提供了为客户端生成的配置文件的内容。

配置 Windows Communication Foundation 客户

  1. 在 Visual Studio 中,将在前一过程如何:创建 Windows Communication Foundation 客户端3中生成的 App.config 配置文件添加到客户端项目中。在“解决方案资源管理器”中右击客户端项目,选择“添加”,然后选择“现有项”。接下来,从上一步在其中运行 SvcUtil.exe 的目录中选择 App.config 配置文件。(之所以命名为 App.config 文件,是因为在使用 Svcutil.exe 工具生成此文件时使用了 /config:app.config 开关)。单击“确定”。默认情况下,“添加现有项”对话框会筛选出具有 .config 扩展名的所有文件。若要查看这些文件,请从位于“添加现有项”对话框右下角的下拉列表框中选择“所有文件(*.*)”。
  2. 打开生成的配置文件。Svcutil.exe 会为绑定上的每一项设置都生成&#20540;。下面的示例显示了生成的配置文件。请在 <system.serviceModel>4<endpoint> 节下查找 5 元素。下面的配置文件是所生成的文件的简化版本。
3.  <?xml version="1.0" encoding="utf-8"?>
4.  <configuration>
5.    <system.serviceModel>
6.      <bindings>
7.        <wsHttpBinding>
8.          <binding name="WSHttpBinding_ICalculator">
9.          </binding>
10.       </wsHttpBinding>
11.     </bindings>
12.     <client>
13.       <endpoint
14.            address="http://localhost:8000/ServiceModelSamples/Service/CalculatorService"
15.            binding="wsHttpBinding"
16.            bindingConfiguration="WSHttpBinding_ICalculator"
17.            contract="Microsoft.ServiceModel.Samples.ICalculator"
18.            name="WSHttpBinding_ICalculator">
19.       </endpoint>
20.     </client>
21.   </system.serviceModel>
22. </configuration> 

此示例配置的终结点可供客户端在访问位于以下地址的服务时使用:http://localhost:8000/ServiceModelSamples/service

终结点元素指定 Microsoft.ServiceModel.Samples.ICalculator 协定将用于通过系统提供的 WsHttpBinding6 配置的通信。此绑定指定 HTTP 作为传输协议、可互操作安全性以及其他配置详细信息。

23. 有关如何在此配置下使用生成的客户端的更多信息,请参见如何:使用 Windows Communication Foundation 客户端7

下面的示例演示为客户端生成的配置文件的内容。

<?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" 
              establishSecurityContext="true" />
           </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="user@contoso.com" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

现在已配置完客户端。请继续执行如何:使用 Windows Communication Foundation 客户端7中的步骤。有关疑难解答信息,请参见入门教程疑难解答8

如何:使用 Windows Communication Foundation 客户端

.NET Framework 4

这是创建基本 Windows Communication Foundation (WCF) 服务和可以调用该服务的客户端所需的六项任务中的最后一项任务。有关全部六项任务的概述,请参见入门教程1主题。

在创建并配置了 Windows Communication Foundation (WCF) 代理后,就可以创建客户端实例,进而编译客户端应用程序并使用它与 WCF 服务进行通信。本主题描述创建和使用 WCF 客户端的过程。此过程执行三项操作:

  1. 创建 WCF 客户端。
  2. 从生成的代理调用服务操作。
  3. 在完成操作调用后关闭客户端。

在过程后面的示例中还提供了过程中所讨论的代码。此任务中的代码应放置在客户端项目中所生成的 Program 类的 Main() 方法中。

使用 Windows Communication Foundation 客户

  1. 为要调用的服务的基址创建 EndpointAddress2 实例,然后创建 WCF Client 对象。

C#

//Step 1: Create an endpoint address and an instance of the WCF Client. 
CalculatorClient client = new CalculatorClient();
 
  1. 从 Client 内调用客户端操作。

C#

// 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);
 
  1. 在 WCF 客户端上调用 Close 并等待,直到用户按 Enter 终止应用程序。

C#

//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 客户端和下面的代码示例编译为可执行文件 Client.exe。在编译代码时,务必引用 System.ServiceModel

C#

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();
 
        }
    }
}
 

确保在尝试使用客户端之前服务正在运行。有关更多信息,请参见 如何:承载和运行基本的 Windows Communication Foundation 服务3.

若要启动客户端,请在解决方案资源管理器中右击客户端,然后依次选择调试启动新实例

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.

如果看到此输出,则说明成功完成了教程。此示例演示如何在代码中配置 WCF 客户端。有关疑难解答信息,请参见入门教程疑难解答4

入门教程疑难解答

.NET Framework 4

本主题列出使用入门教程时最常遇见的问题及其解决方法。

  1. 无法在硬盘上找到项目文件。 
  2. 尝试运行服务应用程序时出现以下错误:HTTP 无法注册 URL http://+:8000/ServiceModelSamples/Service/。进程不具有此命名空间的访问权限。 
  3. 尝试使用 Svcutil.exe 工具时出现以下错误:“svcutil”不是内部或外部命令,也不是可操作的程序或批处理文件。 
  4. 无法找到由 Svcutil.exe 生成的 App.config 文件。 
  5. 编译客户端应用程序期间出现以下错误:“CalculatorClient”不包含“<方法名称>”的定义,并且找不到可接受类型为“CalculatorClient”的第一个参数的扩展方法“<方法名称>”(是否缺少 using 指令或程序集引用?) 
  6. 编译客户端应用程序期间出现以下错误:找不到类型或命名空间名称“CalculatorClient”(是否缺少 using 指令或程序集引用?) 
  7. 运行客户端期间出现以下错误:未处理的异常: System.ServiceModel.EndpointNotFoundException: 无法连接到 http://localhost:8000/ServiceModelSamples/Service/CalculatorServiceTCP 错误代码 10061: 由于目标计算机主动拒绝,未能建立连接。 

无法在硬盘上找到项目文件。


Windows Vista Windows°7 中,Visual Studio 将项目文件保存在 c:\users\<用户名\Documents\Visual Studio 2010\Projects 下,对于 Windows 的早期版本,保存在 c:\Documents and Settings\<用户名>\My Documents\Visual Studio 2010\Projects 下。

尝试运行服务应用程序时出现以下错误:HTTP 无法注册 URL http://+:8000/ServiceModelSamples/Service/。进程不具有此命名空间的访问权限。


必须使用管理特权来运行承载 WCF 服务的进程。如果从 Visual Studio 2010 内运行服务,则必须以管理员身份运行 Visual Studio 2010。为此,请单击开始,右击“Visual Studio 2010”,然后选择以管理员身份运行。如果从命令行提示符运行服务,则必须按类&#20284;方式以管理员身份启动命令行提示符。单击开始,右击命令提示符,然后选择以管理员身份运行

尝试使用 Svcutil.exe 工具时出现以下错误:“svcutil”不是内部或外部命令,也不是可操作的程序或批处理文件。


Svcutil.exe 必须位于系统路径中。最简单的解决方案是使用命令提示符。单击开始,依次选择所有程序“Visual Studio 2010”“Visual Studio Tools”“Visual Studio 2010 命令提示。对于 Visual Studio 2010 中附带的所有工具,此命令提示均能将系统路径设置为正确的位置。

无法找到由 Svcutil.exe 生成的 App.config 文件。


默认情况下,添加现有项对话框仅显示具有以下扩展名的文件:.cs.resx.settings.xsd .wsdl。通过在添加现有项对话框右下角的下拉列表框中选择所有文件(*.*),可以指定您希望查看所有文件类型。

编译客户端应用程序期间出现以下错误:“CalculatorClient”不包含“<方法名称>”的定义,并且找不到可接受类型为“CalculatorClient”的第一个参数的扩展方法“<方法名称>”(是否缺少 using 指令或程序集引用?)


仅向外界公开标记有 ServiceOperationAttribute 的那些方法。如果在 ICalculator 接口的某个方法中省略了 ServiceOperationAttribute 特性,则当所编译的客户端应用程序调用缺少该特性的操作时,便会收到此错误消息。

编译客户端应用程序期间出现以下错误:找不到类型或命名空间名称“CalculatorClient”(是否缺少 using 指令或程序集引用?)


如果未将 Proxy.cs Proxy.vb 文件添加到客户端项目,则会收到此错误。

运行客户端期间出现以下错误:未处理的异常: System.ServiceModel.EndpointNotFoundException: 无法连接到 http://localhost:8000/ServiceModelSamples/Service/CalculatorServiceTCP 错误代码 10061: 由于目标计算机主动拒绝,未能建立连接。


如果在未运行服务的情况下运行客户端应用程序,则会出现此错误。

未处理的异常: System.ServiceModel.Security.SecurityNegotiationException: 目标“http://localhost:8000/ServiceModelSamples/Service/CalculatorService”“http://localhost:8000/ServiceModelSamples/Service/CalculatorService” SOAP 安全协商失败


此错误发生在已加入域但没有网络连接的计算机上。将计算机连接到网络,或者同时关闭客户端和服务的安全性。对于服务,将创建 WSHttpBinding 的代码修改为以下代码。

// Step 3 of the hosting procedure: Add a service endpoint
selfhost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(SecurityMode.None), "CalculatorService");
 

对于客户端,将 <binding> 元素下的 <security> 元素更改为以下内容:

<security mode="Node" />