65.9K
CodeProject 正在变化。 阅读更多。
Home

编写您的第一个 WCF 服务

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.92/5 (21投票s)

2007年4月28日

5分钟阅读

viewsIcon

128865

downloadIcon

2624

本文有助于编写第一个 WCF 服务

在尝试示例之前,请确保您已安装 .NET Framework 3.0 可再发行组件包和 Microsoft® Windows® Software Development Kit for Windows Vista™ and .NET Framework 3.0 Runtime Components。

引言

WCF 是 .NET 3.0 中用于跨计算机对象通信的方式。它基于 WSDL。WCF 服务在开始为您工作之前需要正确完成一些事情。以下几点以最简短的术语描述了所有的技术术语。

在深入实际工作之前,让我们先了解一下基础知识。我将尽量使它们直观简单。

WCF 基础知识

流行的 ABC

这是理解 WCF 如何工作的流行方式。A 是地址 (Address),B 是绑定 (Binding),C 是契约 (Contract)。

  • 地址 (Address) 是你进行通信的地方。它不像部署服务的位置,而是用于内部映射你的请求和响应的 URL。
  • 绑定 (Binding) 是你如何通信。有几种默认的绑定,如 BasicHttp、TCP、NamedPipes、MSMQ 等。这是服务器和客户端在通信时理解的协议。
  • 契约 (Contract) 是你通信的内容。有关契约的详细信息,请参阅下一节。

合同

有两种类型的契约

  1. 服务契约 (Service Contracts): 这是服务消费者在你的服务上调用的 API。它是将进入 WSDL 的方法签名。
  2. 数据契约 (Data Contracts): 这是将从服务消费者和到服务传输的数据。它是数据结构。这可以在你的服务的 schema 中找到。

还有一种叫做消息契约 (Message Contract) 的东西,它基本上是一种使用消息而不是严格类型化结构进行通信的方式。有很多你想使用它的情况,但这超出了本文的范围。

托管

有三种方式可以托管你的服务。

  1. 自托管 (Self hosting): 服务将自行托管并监听客户端请求并进行响应。
  2. IIS 托管 (IIS hosting): 到目前为止,这是最流行的一种。IIS 将托管你的服务(就像你的 ASMX 服务一样)。
  3. WAS 托管 (WAS hosting): 这仅适用于 Windows Vista,并且比其他方法提供了许多优点,但这超出了本文的范围。

既然你已经有了 WCF 的基本信息,我们来构建一个。

开发第一个应用程序

你想做的第一件事就是准备好你的服务,以便客户端可以开始使用它。

开发服务

通过定义你的数据结构来创建你的数据契约。

[DataContract]
public class Request
{
  string name;
  [DataMember]
  public string Name
  {
    get { return name; }
    set { name = value; }
  }
}

[DataContract]
public class Response
{
  string message;
  [DataMember]
  public string Message
  {
    get { return message; }
    set { message = value; }
  }
} 

我们基本上编写了两个类,但指定了 DataContractDataMember 属性,这使得它们对 WCF 来说是特殊的。

现在,让我们通过定义 API 签名来创建一个服务契约。

[ServiceContract]
public interface ISampleService
{
  [OperationContract]
  Response GetMessage ( Request request );

  [OperationContract]
  String SayHello();
} 

在上面的代码中,我定义了两个服务契约,一个使用数据契约,另一个使用本机数据结构 (string)。就这样,很简单。

现在我们已经准备好了结构,我们将去构建我们的服务。

[ServiceBehavior]
public class Service: ISampleService
{
  [OperationBehavior]
  public Response GetMessage ( Request request )
  {
    Response response = new Response();
    if ( null == request )
      response.Message = "Error!";
    else
      response.Message = "Hello, " + request.Name;
    return response;
  }

  [OperationBehavior]
  public string SayHello()
  {
    return "Hello, World!";
  }
}

同样,我们这里没有做什么不同的事情。只是向 service 类添加了 ServiceBehavior 属性,并继承了 ServiceContract interface。事实上,添加 ServiceBehavior 属性是可选的。你所要做的就是让你的 service 类派生自服务契约。

现在我们已经开发了服务,我们应该托管它,以便消费者可以开始使用它。我将向你展示如何在 IIS 中托管它,因为我认为这是最常见的。

要在 IIS 中托管服务,我们需要两样东西。一个配置文件和一个服务宿主文件 (.svc)。

配置文件是我们定义 ABC 的地方,svc 文件是我们定义服务的地方,也将是我们的消费者的联系点。

//web.config file excerpts
<system.serviceModel>
  <services>
    <service name="SampleService.Service" 
        behaviorConfiguration="SampleServiceBehavior">
      <endpoint address="" binding="basicHttpBinding" 
        contract="SampleService.ISampleService"/>
      <endpoint contract="IMetadataExchange" 
        binding="mexHttpBinding" address="mex"/>
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="SampleServiceBehavior">
        <serviceDebug includeExceptionDetailInFaults ="true"/>
        <serviceMetadata httpGetEnabled="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>
//svc file excerpts
<% @ServiceHost Language=C# Service="SampleService.Service" %>

你必须添加引用,服务程序集。

配置文件中的服务行为基本上指示运行时在通过 HttpGet 协议查询时包含元数据。

现在,我们的服务已经完成。只需在浏览器中打开 svc 文件,看看一切是否看起来正常。你应该会看到通过 IIS 或 VS Web Server 浏览的文件。

开发客户端

我们现在将重点关注如何为此服务开发客户端。

我们现在需要创建一个代理来与服务通信。这里有 Visual Studio 会有帮助,如果没有,我们可以使用 svcutil.exe 来生成代理。

我自己编写了代理,因为这让我有自由来减少 svcutil 放入的不必要的东西。我将跳过代理,因为它与 servicecontractdatacontract 和服务存根非常相似。

VS 会自动生成一个配置文件,看起来像

<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ISampleService"
        closeTimeout="00:01:00" openTimeout="00:01:00"
        receiveTimeout="00:10:00" sendTimeout="00:01:00"
        allowCookies="false" bypassProxyOnLocal="false"
        hostNameComparisonMode="StrongWildcard"
        maxBufferSize="65536" maxBufferPoolSize="524288"
        maxReceivedMessageSize="65536" messageEncoding="Text"
        textEncoding="utf-8" transferMode="Buffered"
        useDefaultWebProxy="true">
          <readerQuotas maxDepth="32"
        maxStringContentLength="8192" maxArrayLength="16384"
        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None" 
                                realm="" />
            <message clientCredentialType="UserName" 
                        algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address=https://:4161/ServiceHost/Service.svc 
                        binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ISampleService"
contract="SampleService.ISampleService"
name="BasicHttpBinding_ISampleService" />
    </client>
  </system.serviceModel>
</configuration>

这基本上指定了超时、内容长度和其他基本信息,并且这些元素的解释超出了本文的范围。

这里有趣的点是 endpoint 元素及其属性。这里的地址指的是我们创建和托管的svc 文件,绑定应该与服务器绑定相同。如果你想指定多个绑定,你可以这样做。但服务器首先应该为此做好准备。最后,契约指定了要在服务器上执行的代码。

客户端应用程序就像使用代理公开的 API 一样简单,看起来像

static void Main( string[] args )
{
    Request request = new Request();
    request.Name = "Sidhu";

    SampleServiceClient service = new SampleServiceClien
                ( "BasicHttpBinding_ISampleService" );
    Console.WriteLine( service.SayHello() );
    Response response = service.GetMessage( request );
    Console.Write( response.Message );
    Console.ReadKey();
}

这里唯一要考虑的是 endpoint 名称应该与配置文件中的名称相同。

摘要

执行程序,然后在屏幕上看到 Hello, World!

对于一个简单的程序来说,这已经不少了,但值得开始,因为它的潜力是巨大的。

请对本文留下反馈/建议/评论。如果你想要包含此代码的工作解决方案,请发送一封主题行为“源文件:第一个 WCF 示例”的邮件。这将帮助我进行筛选并及时回复。

© . All rights reserved.