简单演示 WCF Web 服务






4.85/5 (20投票s)
快速了解简单的 WCF Web 服务!
Content
- WCF - 简介
- 什么是服务协定、操作协定和数据协定
- 关于 WCF 配置的说明
- 了解我们定义了简单业务功能的项目
- 通过 WCF Web Service 公开上述业务功能
- 使用 WCF 测试客户端测试我们新创建的 Web Service
- 为我们新的 Web Service 创建代理客户端
- 测试我们上面创建的代理客户端
- 最终想法
引言
在本文中,我们将介绍一个简单的 WCF Web Service。
通过示例来理解概念会更容易。
在本文中,我们将总共使用 3 个项目。
类库项目 TweetBL 将代表一个需要启用服务功能的项目。然后,我们将介绍一个 WCF 服务项目,该项目将把我们的 TweetBL 项目的业务功能公开为 Web Service。在我们的第三个也是最后一个项目中,我们将创建一个代理客户端来消耗我们的 WCF Web Service。
最后,值得一提的是,我们将逐步测试每一个细节。请坚持下去,不要慌张,我已尽量使用简单的代码,并且在这里只关注 WCF!
那么,开始吧……
WCF - 简介
WCF 代表 Windows Communication Foundation。
WCF 是一个框架,旨在支持客户端和服务器上的基于消息的通信。
WCF 支持多种传输方式,如 SOAP over HTTP(我们的示例 Web Service 基于此)、TCP、命名管道、MSMQ 等。
WCF 支持多种编码方式,如 XML、文本、二进制以及其他一些选项。
目前,为了举例说明,一些采用 WCF 的技术包括 Windows Workflow、Silverlight 等。
什么是服务协定、操作协定和数据协定
在 WCF 中,协定用于定义功能。
协定基本上是客户端和服务之间的正式协议,用于定义一种平台中立的
以及标准化方式来描述服务将要做什么以及能够做什么。
WCF 定义了 4 种类型的协定
- 服务契约
- 操作协定
- 数据协定
- 故障契约
在本文中,我们将重点介绍前三种协定。
服务协定 定义了 Web Service 的能力。
它本质上是一个接口协定,将应用程序(业务功能 - 要公开的业务操作
)绑定到提供一组固定的操作(如接口协定中所述),以供
消耗 Web Service 的源使用。
它简单地描述了在服务终结点上可用,并向外界公开的
客户端可调用的操作或方法。
就代码而言
我们所需要做的就是编写代码并使用 ServiceContract
特性装饰一个接口。
该接口将包含作为 Tweet Service 的一部分向外界提供的成员(方法)。
//
// Service Contract
// Wee need to decorate the Interface with the ServiceContract Attribute
//
[ServiceContract]
interface ITweetService
{
// Interface members
// Tweet Service Methods that need to be exposed to the outside world!
}
另一方面,操作协定 定义了外部系统可以访问的服务方法。
它是上面创建的服务协定接口不可或缺的一部分。
在服务协定接口中用 Operation Contract 特性标记的成员是那些
向外部系统公开的成员。
在服务协定接口中没有用 Operation Contract 特性装饰的成员不会
作为 Web Service 的一部分公开。
就代码而言
它只能应用于方法。
它用于装饰属于服务协定接口的方法。
//
// Service Contract - Operation Contact example
//
[ServiceContract]
interface ITweetService
{
[OperationContract]
int AddNewTweet(string tweetBy, string tweet);
// Other members...
}
数据协定 定义了 Web Service 操作要发送和接收的数据的类型和格式。
它是服务和客户端之间的一个正式协议,抽象地描述了要交换的数据。
数据协定可以是显式的或隐式的。像 int
、string
等简单类型具有隐式数据协定。
用户定义的对象的显式或复杂类型,您必须使用 [DataContract]
和 [DataMember]
特性来定义数据协定。
下面提到了关于数据协定的一些重要因素
- 描述了传递到 Web Service 操作和从 Web Service 操作传递出的数据的格式、结构和类型
- 进行 CLR 类型和 XML Schema 之间的映射
- 定义相关数据如何序列化和反序列化
序列化 = 将数据(对象)转换为可以在网络上传输的字节序列
反序列化 = 将字节序列重新组装回其原始形式 -> 数据(对象) - 是一个松耦合模型,定义在服务实现之外,并且可以被其他平台的服务访问
就代码而言
要定义数据协定,请将 DataContract
特性应用于类,以便序列化器可以序列化该类,并将 DataMember
特性应用于类中必须序列化的字段。
我们需要将 System.Runtime.Serialization
引用添加到项目中。
该程序集包含 DataContract
和 DataMember
特性。
//
// Data Contract - Data Member example
//
// Creating a user defined data type called SampleData. This data type should be identified
// for serialization and de-serialization by mentioning with [DataContract] and [DataMember] attribute.
//
// There should be: using System.Runtime.Serialization; reference in the using section.
//
[DataContract]
public class SampleData
{
private string _somePropertyPrivateVariable;
[DataMember]
public string SomeProperty
{
get { return _somePropertyPrivateVariable;}
set { _somePropertyPrivateVariable = value;}
}
// Other properties...
}
关于 WCF 配置的说明
由于 WCF 支持如此多的技术、传输协议和编码方式,因此它在很大程度上依赖于配置。
所有这些都归结为以下几点
- 终结点 (Endpoint):这是服务器发送和接收数据的地址。
- 绑定 (Binding):它定义了终结点使用的传输和编码。
- 行为 (Behaviour):这是最后一部分,负责 Web Service、终结点、操作和/或客户端的运行时行为。
行为很重要,因为它们会影响错误处理、凭据以及许多其他重要功能。
在本文中,我们将使用默认的 WCF 配置。这里解释了为每个项目提供的默认 WCF 配置。
了解我们定义了简单业务功能的项目
我们将把这个业务功能公开为 Web Service!
我们将要公开为 Web Service 的项目是一个简单的类库项目,名为 TweetBL(BL 代表 Business Layer,业务层)。
TweetBL 项目代表已经确定要通过 Web Service 在 Web 上提供的业务代码。
TweetBL 项目具有以下业务功能(方法),将作为服务公开。
业务功能方法包括
- 更新推文
- 保存/插入推文
- 删除推文
- 按 ID 检索推文,以及
- 检索所有推文
TweetBL 项目
Tweet.cs 只是一个数据类,其中包含我们要获取/更新/插入和删除以管理推文的所有数据成员。可以将其视为模型(数据模型)。
TweetService.cs 是包含业务方法的类,这些方法对 Tweet 数据进行所有必要的处理以进行管理和维护。
注意:由于我们没有使用实际数据库,因此还有一些辅助代码(与要公开的业务功能无关),以保持事物相对简单。
通过 WCF Web Service 公开上述业务功能
在我们快速浏览了 TweetBL 项目后,是时候开始编写真正的代码了……
让我们通过添加一个名为 Tweet.WebService
的新项目开始 - 这将是我们的 WCF 项目。
现在,我们将向 Tweet.WebService
项目添加一个 WCF 服务。
转到添加新项(在 Tweet.WebService
项目上),然后按照下面的屏幕截图操作
添加服务后,它会使项目发生一些更改。
已添加 Serialization
和 ServiceModal
引用以及其他一些文件!
Web.config 文件也已修改!
需要注意的一点是,一旦我们添加了一个 WCF Web Service,Web.config 文件就会更新为基于 SOAP over HTTP 的 WCF 服务的默认配置……
我们可以看到为我们的 WCF 服务定义了一系列行为,特别是为我们的 Web Service 定义了一个。
行为定义了我们服务的运行时方面。
您可以随意添加、删除或修改这些设置,但对于本文,我们将坚持使用默认设置。
这里遵循KISS 原则 - 保持简单,笨蛋!
此设置允许使用 get
动词通过 HTTP 和 HTTPS 发送元数据。
//
// Web.Config snippet
//
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
我们将 includeExceptionDetailInFaults
设置为 false
,以便如果服务器上发生任何错误,我们不会将异常的详细信息发送回客户端。
//
// Web.Config snippet
//
<serviceDebug includeExceptionDetailInFaults="false"/>
下面的配置设置定义了 Web Service 的托管方式。将 aspNetCompatibilityEnabled
设置为 true
使我们能够与 IIS 中的 ASP.NET 管道集成。
最后,将 multipleSiteBindingsEnabled
设置为 true
允许我们将 Web Service 与
IIS 上配置的多个站点绑定关联起来。
//
// Web.Config snippet
//
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true"/>
以上所有设置都已默认设置好……所以我们不必担心任何事情!
现在,一个接口和一个 svc 文件也被添加到了项目中。让我们现在关注它们。
WCF 使用接口来定义每个单独服务的各项能力,而ITweetService.cs 代表
该设计和目的。
//
// ITweetService.cs snippet
//
[ServiceContract]
public interface ITweetService
{
[OperationContract]
void DoWork();
}
ServiceContract
特性告诉 WCF 该接口ITweetService.cs 可以作为 Web Service 的一部分用于提供数据。
OperationContract
特性简单地标识了服务可以执行的操作。
最后,我们有 TweetService.svc。
//
// ITweetService.svc (right-click: View Markup) snippet
//
<%@ ServiceHost Language="C#" Debug="true"
Service="Tweet.WebService.TweetService" CodeBehind="TweetService.svc.cs"%>
ServiceHost
指令(上图)是 WCF 特有的 - 它启用了我们在前几节中探索过的所有绑定和配置。
其代码隐藏文件非常简洁,因为所有 WCF 特定的配置都已被抽象出来并指定
在 ITweetService
接口中。
//
// ITweetService.svc.cs Code behind file snippet
//
public class TweetService : ITweetService
{
public void DoWork()
{
// Lets do some work
}
}
现在让我们将业务代码整合到这个新创建的 WCF Web Service 中
我们将从 TweetBL
项目公开所有相关的 TweetService
类方法来管理推文,作为 Web Service。
让我们开始通过 Tweet.WebService
项目的 ITweetService
接口公开这些方法。
向 Tweet.WebService
项目的 ITweetService
接口添加方法
现在,我们必须在 TweetService.svc.cs 类中实现 ITweetService.cs 接口。我将通过利用我们在项目中定义的业务功能代码来实现这些方法:TweetBL
项目 - TweetService.cs 类。
在 TweetService.svc.cs 类中实现 ITweetService.cs 接口。
现在,在实现并生成项目后 - 转到 TweetService.svc,右键单击并选择在浏览器中查看。
这将显示我们 Web Service 的生成的 HTML 页面,我们可以使用该页面来构建我们的代理客户端(消耗我们服务的客户端)。
最后,我们离测试服务只有一步之遥了。让我们在数据对象 Tweet.cs (我们的 Transport
类)项目 TweetBL
上用以下特性标记
[DataContract]
:用此特性标记我们的数据传输类 Tweet.cs (TweetBL
项目)[DataMember]
:用此特性标记 Tweet.cs 类(TweetBL
项目)中的所有字段
现在我们准备测试我们的 WCF Service 了!
注意* 数据协定已在此处解释。
使用 WCF 测试客户端测试我们新创建的 Web Service
在上节中,我们完成了 ITweetService.cs 接口在 TweetService.svc.cs 类中的实现。
现在是快速测试的时候了……将 Tweet.WebService
项目设置为启动项目。
选择 TweetService.svc 类,然后按 F5 启动 WCF 测试客户端。
选择 GetTweets()
方法并双击 - 这将为我们启动一个窗体……GetTweets()
服务方法不接受任何参数,因此我们可以直接单击“调用”按钮
上面的屏幕截图显示了 GetTweets()
服务调用的结果 - 结果显示在一个格式良好的数据表中!
它返回了 4 个元素的列表。
我们的业务层项目 TweetBL
- 类 TweetService.cs 已被设置为创建 4 条初始推文。
所有这 4 条记录都已返回。
如果您单击XML 选项卡 - 您可以看到请求和响应的 SOAP 信封。Request
信封由客户端生成,Response
信封是我们从 WCF 服务收到的。
注意 - 您也可以使用 WCF 测试客户端测试所有其他服务方法。
其余的服务方法我留给您自己玩。
为我们新的 Web Service 创建代理客户端
添加一个名为 TweetClient
的新控制台应用程序项目,它将是消耗我们 Tweet Web Service 的代理客户端。
现在,让我们为 TweetClient
项目添加 TweetService
的服务引用
右键单击 TweetClient
项目,然后转到添加 -> 服务引用……
单击“发现”按钮 - 由于我们的服务在同一个解决方案中,它将被发现并显示。
通过展开 TweetService
,它将从服务下载 Web Service 定义文档,并获取 WCF 服务的服务协定。
正如您所见,我们在服务协定中公开的 5 个操作已显示出来。
单击“确定”,选定的服务引用将被添加到名为“Service References”的文件夹中。
如果您双击新添加的服务引用,它会打开对象浏览器。
如果您选择 ITweetService
接口,这里有一些有趣的信息可以查看
正如您在上图中所见 - 对于 ITweetService
接口,对象浏览器不仅显示了
我们通过服务协定公开的 5 个操作,它还显示了这些方法的异步版本。这些异步方法是默认添加的,它允许客户端创建异步 Web 请求!以便与服务器通信而不阻塞其主线程。
另外,快速看一下我们的 Tweet
传输类……
这是我们将用于与服务器进行所有调用(例如:创建
、获取
和更新
)之间的数据传输的类。
它具有执行上述操作所需的所有字段。
最后,让我们看看 TweetServiceClient
……
这是 ITweetService
的具体实现。它也有 5 个不同的构造函数定义。
注意* 默认构造函数将使用我们添加服务引用时使用的 Web 地址!
其他构造函数可用于为我们提供不同的选项来配置服务,以使用不同的服务器,例如测试服务器或生产服务器,或两者都使用。
使用这些构造函数,您可以定义服务将要通信的终结点。
在本文中,我们将仅使用默认构造函数的服务。
既然我们有了服务引用,让我们定义我们的 TweetClientDataService
。
在 TweetClientDataService
实现(上图)中,我使用了对 TweetServiceClient
的引用。
TweetServiceClient
在后台为我们提供了大量功能!
例如:TweetServiceClient
- 在后台处理所有请求和响应 SOAP 信封的序列化和反序列化
它还为我们打开连接,并在网络上代表我们发送和接收信息。
因此,它确实抽象了在通过
RPC SAOP 风格的 Web Services 进行通信时
需要面对的许多复杂性!
测试我们上面创建的代理客户端
哇!我们在这里……我们几乎完成了!
我在 TweetClient
项目中创建了一个 Program
类,并引入了一些命令提示符
界面来与我们的 Tweet Web Service 操作进行交互。我将 TweetClient
中的 Program
类
项目留给您探索,因为它相当简单。
要运行 TweetClient
项目中的 Program
类,请按照下面的屏幕截图操作
一个(您决定!)看起来不错的命令提示符界面将弹出,您可以使用它来调用我们的 Tweet Web Service 操作!
玩得开心,使用 TweetClient 来操作我们的 TweetService!
最终想法
现在该我退场了。随时提出问题、提供反馈以及介于两者之间的任何内容,因为我和您在同一条船上。
附言:那艘船叫做“燃烧与学习”。
历史
- 版本 1 提交于 2015 年 3 月 9 日