简单演示 WCF RESTful Web 服务





5.00/5 (13投票s)
快速了解简单的 WCF RESTful Web 服务!
目录
- 引言
- WCF RESTful 服务 - 简介
- 看看我们的 TweetBL 项目,它定义了简单的业务功能
- 创建 WCF RESTful 服务项目(用于 TweetBL 项目的业务功能)
- 运行默认的 WCF RESTful 服务项目(Web.config 文件仍有 AJAX 配置)
- 修改并运行默认的 Tweet.WCFService.RESTful 项目设置(从 AJAX 切换到 RESTful)
- 运行 Tweet.WCFService.RESTful 项目 - 简单的方式!
- 构建 WCF RESTful 服务项目(用于 TweetBL 项目的业务功能)
- 运行 WCF RESTful 服务项目(现在包含了我们的业务代码)
- 创建和测试 WCF RESTFul Web Service 客户端
- 最终想法
简介
在本篇文章中,我们将探讨如何创建 WCF RESTful Web Service!
我建议快速阅读这篇 文章,以便快速回顾 WCF 的基本细节。
我将专注于涵盖与 WCF RESTful 服务相关的主题,而不会深入探讨基本的 WCF 相关细节,例如解释操作契约。上面链接的文章解释了这些主题。
另外,这是我写的关于 WCF AJAX Web Service 的文章链接。如你将在本文中看到的,AJAX Web Service 和 RESTful Web Service 有很多相似之处。我提供了链接供您参考,因为两者都利用了 Web API。我建议在继续阅读本文之前快速浏览一下,因为我坚信这将使您更容易理解。
话虽如此,如果您按照本文的指导进行,应该不难理解这个概念。所以,不用担心,您可以稍后再阅读它们。
在本文中,我们将使用一个名为 TweetBL
的简单业务层项目作为起点。在本文的整个过程中,我们将把 TweetBL
的业务功能公开为 WCF RESTful Web Service。
在本文中,我们将专注于开发一个 WCF RESTful Web Service,并已尽我所能使其尽可能简单。
遵循 KISS 原则:“保持简单,愚蠢。”
那么,让我们开始吧……
WCF RESTful 服务 - 简介
我仍然认为…… Windows Communication Framework (WCF) 和漫威宇宙一样有趣! 没开玩笑。
WCF 是一个支持客户端和服务器之间基于消息通信的框架。
WCF 是高度可配置的……!!
我们将利用 WCF 的这一特性,采用 WebHttp
行为配置选项! WebHttp
行为提供了 XML 和/或 JSON 序列化,而不是使用传统的 SOAP 报文! WebHttp
还为我们服务公开的每个独立操作绑定了自定义路由。
不用说,它还支持下面提到的多种 HTTP 动词:
GET
动词:用于获取数据PUT
动词:用于更新数据POST
动词:用于插入数据DELETE
动词:用于(您猜对了!)删除数据
简而言之,WebHttp
行为提供了 WCF 开发基于 REST 的 Web 服务所需的功能。
注意,我们还将使用 WebHTTPBinding
服务绑定,因为它允许我们使用预定义的行为从 Web 服务连接到服务方法。
此外,WCF RESTful Web Service 仍然是一种 Web API 风格的 Web Service。这意味着 RESTful Web Service 不会生成 WSDL(Web Service Definition Language)文件。
那么,我们一直在谈论 RESTful……它到底是什么?好吧,REpresentational State Transfer (REST) 是一种 Web API Web Service 风格,在访问、更新和检索数据时遵循一些结构化准则(例如统一接口)!
REpresentational State Transfer (REST) 的一些亮点是:
- 统一接口 RESTful 对特定操作使用特定的 HTTP 动词
GET
:翻译为Read
(读取)操作PUT
:翻译为Update
(更新)操作POST
:翻译为Insert
/Create
(插入/创建)操作DELETE
:翻译为……嗯,Delete
(删除)操作
- RESTful Web Services 还偏好一种特定的 URI 风格(在第 3 点的 yourService.com 示例中演示),它们使用这种风格来访问和管理信息(数据/资源)。RESTful 偏好将它们管理的数据表示为资源。
- 促进更简洁的 URI 示例:yourService.com/SocialNetworker/1251/Tweets,而不是使用查询字符串 URI…… yourService.com/GetAllTweetsForSocialNetworker?SocialNetworkerId=1251
所以,说够了……
是时候卷起袖子开始干了!
看看我们定义简单业务功能的 TweetBL 项目
我们将把 TweetBL 项目的业务功能公开为 Web Service!
我们将作为 Web Service 公开的项目是一个名为 TweetBL
的简单类库项目。
TweetBL
项目代表了已确定要在 Web 上作为 WCF RESTful Web Service 提供的业务代码。
TweetBL
项目具有以下业务功能(方法),这些功能将被公开为服务。
业务功能方法是:
- 更新推文
- 保存/插入推文
- 删除推文
- 按 ID 检索推文,以及
- 检索所有推文
TweetBL
项目
Tweet.cs 只是一个数据类,它标识了我们要获取/更新/插入和删除的所有数据成员,以管理推文。可以将其视为 Model(数据模型)。
ManageTweet.cs 是包含业务方法的类,这些方法对 Tweet 数据执行所有必要的处理以进行管理和维护。
注意:由于我们没有使用实际数据库,因此还有一些维护代码,以使事情保持相对简单。
TweetBL
项目之旅结束…… TweetBL
功能就是这样……它确实相当简单!
让我们开始为我们的 TweetBL
项目编写 RESTful Web Service。
一旦完成,我们将把这个 RESTful 服务献给所有敬业的“Twitterati”……:P
创建 WCF RESTful 服务项目(用于 TweetBL
项目的业务功能)
既然我们已经快速浏览了我们的 TweetBL
项目,是时候进入实际代码了……
让我们开始添加一个名为 Tweet.WCFService.RESTful
的新项目。这将是我们的 WCF RESTful 服务项目。
选择“Empty”(空)选项,不要选择其他任何选项。
上述步骤为我们创建了一个空的 ASP.NET Web 应用程序!
现在,我们将向 Tweet.WCFService.RESTful
项目添加一个 WCF RESTful 服务。
转到“add new item”(添加新项)(在 Tweet.WCFService.RESTful
项目上),然后按照下面的屏幕截图操作。
添加 AJAX 服务后,我们的项目发生了一些更改。
一些 .NET 的引用和库已添加到我们的项目中。我们将介绍一些有趣的部分!
我们的 Web.config 文件也已修改!
我们的 Web.config 文件(默认情况下)已为开发 AJAX 服务进行了修改,但我们很快就会修改它来开发 RESTful 服务。让我们看一下……
注意*:<enableWebScript />
行为用于开发 WCF AJAX Web Service。但由于我们正在开发 RESTful Web Service,我们将对 Web.config 进行必要的修改。
此外,我们的 Tweet.WCFService.RESTful
项目还添加了一个 <endpointBehavior>
,它将启用对 Web 服务的请求调用监听。
注意使用的绑定“webHttpBinding
”。这允许我们的 Web 服务客户端使用 http GET
和 POST
动词与我们的服务进行通信。请注意,只有用 Operation Contract
属性修饰的方法才会被公开为服务。
除了上述更改外,我们还提供了一个 TweetService.svc 类的模板文件。
这里与 SOAP over HTTP Web Services 不同,我们没有接口类。
Service Contract
和 Operation Contract
属性直接定义在类上。另外,请注意 AspNetCompatibilityRequirements
属性:此属性表示该服务与 ASP.NET 管道集成。既然我们已经创建了一个项目并快速浏览了默认提供给我们的内容……让我们进一步构建实际的东西!
运行默认 WCF RESTful 服务项目(Web.config 文件仍有 AJAX 配置)
因此,在我们的 WCF 项目 Tweet.WCFService.RESTful
中,让我们通过右键单击 TweetService.svc 并选择“View in browser”(在浏览器中查看)来启动创建项目后获得的默认代码。
太棒了!自动生成的 HTML 页面。这是一个 Web API 服务,所以没有生成 WSDL!
当然,我们已经走了这么远,测试一下我们在 TweetService.svc 类中看到的默认 DoWork
方法也没有什么坏处。
为此,我们只需要向 DoWork
方法添加一个新属性。新属性是 WebGet
,如下面的屏幕截图所示。
自然,您会想知道 WebGet
属性做什么?基本上,WebGet
属性使用 GET
动词公开(用它修饰的)操作!现在,通过在服务 URI(在本例中为 TweetService.svc)后附加方法/操作名称(在本例中为 DoWork
)到地址栏,我们可以直接通过 Web 浏览器访问我们的 DoWork
服务。
接下来我们将这样做。
添加此新属性后,再次右键单击 TweetService.svc 并选择“View in browser”(在浏览器中查看)。
在路径末尾输入方法 DoWork
……然后按 Enter。
我们的劳动成果……
{"d":null}
是我们调用 DoWork
服务操作后收到的响应。这是 JSON 格式。
调用 AJAX 服务就是这么简单!
我们上面所做的一切都是在运行 WCF AJAX Web Service,因为请记住,我们还没有修改 Web.config 文件来指示这是一个 RESTful Web Service。
我们接下来这样做!
修改并运行默认的 Tweet.WCFService.RESTful 项目设置(从 AJAX 切换到 RESTful)
首先……我们现在需要做的第一件事是为我们的 WebGet
属性定义一个 URI,因为 REST 非常重视简洁的资源 URI。
这意味着 REST 希望我们指定一个特定的 URI 来访问一个特定的方法或一个特定的资源。
为了实现这一点,我们必须向 WebGet
属性传递参数。
准确地说,我们将采用 UriTemplate
参数。
将 TweetService.svc 中的 DoWork
方法修改如下:
// class code...
[OperationContract]
[WebGet(UriTemplate="/DoWork")]
public void DoWork()
{
// Add your operation implementation here
return;
}
// class code...
TweetService.svc 类现在……
UriTemplate
参数基本上允许我们传递一个 string
,它允许我们为托管提供商(在本例中为 Web Dev 服务器)将传入的请求与之匹配的 URI 定义一个模板!
现在我们准备调用 DoWork
服务方法…… RESTful Web Service 风格!
哦……发生了意想不到的事情!
这是一个服务器错误:表明我们使用了“UriTemplate
”将 URI 绑定到特定方法,但我们当前配置不允许这样做!(我们仍然处于 AJAX Web Service 配置)。
对 Tweet.WCFService.RESTful
项目中的 Web.conf 文件进行必要的更改,是时候迁移到 RESTful 配置了。
Web.config 当前状态……
我们特别想从 <enableWebScript />
切换到 <webHttp />
。<webHttp>
是一个 WCF 行为,它为我们提供了比 <enableWebScript>
更宽松、更灵活的 HTTP 通信控制。
为什么? 我们要进行这次切换??仍然感到困惑……嗯……即使 <enableWebScript>
也使用 HTTP 动词进行通信以及序列化和反序列化数据(使用 XML 或 JSON),但它这样做是通过默认自动生成的 JavaScript 代理!它有自己的做事方式。
而在 RESTful 中,我们不想使用这个默认的 JavaScipt 代理,因为我们希望对 HTTP 动词有更多的控制!我们希望自己决定哪个 HTTP 动词应该绑定到哪个方法……以及我们想要定义和使用的 URI!<webHttp>
允许在我们的 WebGet
和 WebInvoke
属性中定义所有这些。
关于这个自动生成的 JavaScript 代理的更多信息可以在 WCF AJAX Web Service 文章 中找到(如果您好奇……您也可以稍后阅读)。
在 Web.config 文件中(Tweet.WCFService.RESTful
项目)进行更改……
是时候再次运行 TweetService.svc DoWork
方法了……
……然后 DoWork
正常执行。不用说,DoWork
方法的返回类型是 void
,因此执行 DoWork
方法不会返回任何内容供我们显示。
UriTemplate
参数帮助服务器(在本例中是 Web Dev)确定如何处理传入的请求!它有助于推断哪个服务方法应该响应哪个特定的传入请求。
让我们将 DoWork
方法的 UriTemplate
参数从 /DoWork 更改为 /GetSomethingDone……
这将演示 UriTemplate
参数的重要性!因为当我们尝试使用 /DoWork URI 调用 DoWork
方法时,它会报告“Endpoint not found”(端点未找到)!因为我们现在已经更改了访问 DoWork
方法的 URI 以 /GetSomethingDone
。
在 TweetService.svc 中更改 UriTemplate
参数。
使用旧的 UriTemplate
URI /DoWork 调用 DoWork
方法……
服务器无法确定如何处理此请求,因为我们将 UriTemplate
映射到了 /GetSomethingDone。
现在让我们使用正确的 URI 调用 DoWork
方法。
看!DoWork
方法的 void
又回来了!!
现在我们已经很好地理解了 UriTemplate
的作用和重要性……让我们向公开真实的 TweetBL 业务方法(而不是 DoWork
(默认方法))迈出一步,作为我们备受期待的 TweetService
的一部分!
但在继续前进之前,让我们稍作绕道,让运行 TweetService.svc 变得更容易——只需按 F5!
这肯定会让我们的生活轻松很多,并在下一节中讨论。
简单地运行 Tweet.WCFService.RESTful 项目!
与其右键单击:TweetService.svc - 并选择“open in browser”(在浏览器中打开),我们可以这样做……
将 Tweet.WCFService.RESTful
项目设置为启动项目。
选择 TweetService.svc 并按 F5。
您将收到以下错误:
好吧,尝试启动 WCF 测试客户端,但由于 RESTful 服务未生成 WSDL,因此 WCF 测试客户端无法自动生成 XML(WSDL)来帮助我们测试服务……我们现在来修复这个问题;这样,当我们尝试在选择 TweetService.svc 后运行 Tweet.WCFService.RESTful
时——WCF 测试客户端将不再被用于帮助我们测试服务!
让我们编辑 Tweet.WCFService.RESTful
项目的文件。
在开始编辑之前,我们需要卸载 Tweet.WCFService.RESTful
项目。
项目卸载后,右键单击项目并选择“Edit Tweet.WCFService.RESTful.csproj”。
按“Ctrl+F”搜索“<WebProjectProperties>
”。
为 Tweet.WCFService.RESTful
项目的 WebProjectProperties
添加以下元素!然后保存文件。
<WebProjectProperties>
// Other Project Properties...
<EnableWcfTestClientForSVCDefaultValue>
false
</EnableWcfTestClientForSVCDefaultValue>
// Other Project Properties...
</WebProjectProperties>
保存对 Tweet.WCFService.RESTful.csproj 的更改后,是时候重新加载项目了……
点击“YES”!
再次将 Tweet.WCFService.RESTful
项目设置为启动项目……
选择 TweetService.svc 文件。
在 TweetService.svc 的后台代码文件中——按 F5!
WCF 测试客户端没有弹出!我们的 TweetService.svc 已执行……
现在,让我们继续公开我们的有效 TweetBL
业务功能,作为我们备受期待的 TweetService
(TweetService.svc)的一部分。这将在下一节中完成。
构建 WCF RESTful 服务项目(用于 TweetBL 项目的业务功能)
是时候构建我们真正的 RESTful 服务并删除 DoWork
方法了!让我们利用TweetBL
项目 - ManageTweet.cs:这个类包含我们需要管理 Tweet 的所有业务代码。我们将把所有这些方法公开为 RESTful Web Service。
在 Tweet.WCFService.RESTful
项目的 TweetService.svc 中,我们已包含对 TweetBL
项目的 ManageTweet.cs 的引用,正如上面屏幕截图所示,我们所做的只是将收到的任何 TweetService.svc
方法的调用传递给 ManageTweet
类方法来执行实际工作。
简单来说,我们在服务类中所做的就是在调用业务类来完成实际工作。
运行 WCF RESTful 服务项目(现在包含我们的业务代码)
现在我们准备好了——来实际运行我们的 Tweet 服务!
它不会有太大区别……但是的,需要一些额外的步骤才能运行某些方法!这些方法没有实现 GET
动词(WebGet
属性)而是实现了 WebInvoke
属性。另外,不用担心需要 ID 参数的方法 GetTweetById
,测试起来会很简单!下面指出的那些(在 TweetService.svc 中)
相信我,这很有趣……
测试 GetTweets()
方法: 按照下面屏幕截图中的步骤操作
运行服务 - 选择 TweetService.svc 并按 F5……
我们收到以下错误!
完整的错误消息是:“合同‘TweetService’中的操作‘GetTweetByID’有一个名为‘tweetId’的路径变量,其类型不是‘string’。UriTemplate 路径段的变量必须是‘string’类型。”
这里没有戏剧性的事情!抱怨的是 GetTweetByID
方法,它需要一个 int tweetId
参数。WCF Rest 无法解析 UriTemplate
路径中的任何其他值,除了字符串!
有问题的方法……嗯,一旦我们解决了 GetTweetById
!DeleteTweet
方法也会有问题!
最好现在就解决它们!
方法们
我们所要做的就是将 GetTweetByID
方法的 int tweetId
参数和 DeleteTweet
方法的 int deleteTweetId
参数更改为string
,并在我们的 GetTweetByID
方法和 DeleteTweet
方法中进行必要的数据转换,将 tweetId
和 deleteTweetId
参数从string
转换为 int
,然后再将它们传递给相应的 TweetBL
方法。
进行建议的更改——
GetTweetByID
方法
DeleteTweet
方法
终于,我们回到正轨了……
现在让我们第二次测试 TweetService.svc 方法!
测试 GetTweets()
方法: (注意* GetTweetByID
和 DeleteTweet
方法已修复!)按照下面屏幕截图中的步骤操作
运行服务 - 选择 TweetService.svc 并按 F5……
输入方法名 GetTweets
GetTweets
方法结果(未格式化)
注意到 k__BackingField
附加到了我们的每个 Tweet
属性……这是因为我们没有将我们的 Tweet
类(TweetBL
项目)标记为 DataContract
属性,并且没有将它的字段标记为 DataMember
属性。
快速回顾:数据契约定义了 Web 服务操作将发送和接收的数据的类型和格式。DataMember
属性应用于 DataContract
类的要序列化的字段。
我在我之前的一篇文章中详细介绍过 WCF 契约,相关部分可以在 这里 找到。
将属性应用于 Tweet.cs
哎哟!那些红色的波浪线……啊……这只是表明您在 TweetBL
项目中没有对“Serialization
”程序集的引用!
namespace TweetBL
{
using System;
using System.Runtime.Serialization;
.... remaining code...
让我们快速添加对“Serialization
”程序集的引用
然后一切又恢复正常了……
再次运行 TweetService.svc……我们得到以下结果: k__BackingField
不再附加。
让我们运行 GetTweetByID()
方法。此方法用 WebGet
属性修饰,但它还需要一个类型为 string 的参数!要传递……太棒了……
运行 TweetService.svc 并调用 GetTweetByID
方法而不传递必需的 string
参数将产生以下“Endpoint not found”(端点未找到)结果
我们得到上述结果是因为 WCF 尽力匹配请求的 URI,但未能找到匹配的方法。对于 GetTweetByID
方法,URI 指示需要一个 string
![WebGet(UriTemplate = "/Tweet/{tweetId}")]
。
运行 TweetService.svc 并仅通过 /Tweet 调用 GetTweetByID
方法将产生以下“Method not allowed”(方法不允许)结果
不用说,TweetService.svc 中定义的其他方法都没有 /Tweet 的 URI 并且用 WebGet
属性修饰!
UpdateTweet 方法确实有一个匹配的 URI,但它用WebInvoke 属性修饰,正如我们稍后将学到的,调用 WebInvoke
方法的方式有点不同。
默认情况下,我们的浏览器只发送 WebGet
请求!……所以它无法执行 URI 为 /Tweet 的方法(在本例中为 UpdateTweet
方法),因为它会以 GET
动词的 HTTP 请求发送 /Tweet,而 UpdateTweet
方法正在等待 PUT
动词的 HTTP 请求!
让我们在 URI 中传递必需的 string Id
参数,看看服务是如何工作的
将 0
传递给 GetTweetByID
方法
显而易见,我们没有 ID 为 0
的记录,所以返回 null
。
我们只需要传递一个正确的推文 ID(请参阅下方)
所以,这是关于如何运行用 WebGet
属性修饰并且需要传递 string
参数的服务操作/方法的一个简单演示!
是时候看一下 TweetService.svc 类中用 WebInvoke 属性修饰的其他操作了……
WebGet
和 WebInvoke
属性之间的关键区别在于,它使用 POST
动词而不是 WebGet
使用的 GET
动词。
为什么使用 WebInvoke
?嗯,WebInvoke
属性使用其他 HTTP 动词(如 POST
、PUT
和 DELETE
)公开服务操作/方法。这些操作旨在修改资源;因此,使用 WebInvoke
属性来修改资源。注意:默认选项是 POST
,但您可以通过设置 WebInvoke
属性的Method 属性来更改它。如下面所示
[OperationContract]
[WebInvoke(Method = "PUT")]
public void PutQuestion(int id, Question question)
{
// Put question in database
}
另一个需要注意的有趣点是,所有 Web 浏览器都针对 GET
动词请求进行了优化。它们缓存 Get
请求的结果,并且每次刷新浏览器时,结果都会从浏览器缓存中检索,而不是访问 Web 服务器。
因此,出于明显的原因,现在执行create
、update
或delete
操作时,您不希望浏览器缓存这些操作的结果!所以,我们使用不同的动词,如 Put
、Post
等,来表示我们不希望缓存这些操作的结果,并且在Put
、Post
或Delete
操作成功完成后,我们总是希望刷新数据。这是一个双赢!
现在,继续……如果我们尝试像调用 WebGet
属性修饰的操作那样运行 WebInvoke
修饰的操作,我们会得到以下结果
方法 CreateTweet
- URI:/Tweets
调用结果
我们收到“Method not allowed”(方法不允许)消息,因为我们为 CreateTweet
操作指定了 WebInvoke
属性。
我们现在提出的问题是……如何测试我们的 WebInvoke 方法 CreateTweet? 简单的答案是使用“Fiddler”。
Fiddler:是一个实用工具,允许我们创建和监控机器上的 HTTP Get
/Put
/Post
/Delete
请求!……正是我们需要的!
有一些问题的答案……嗯,这个问题不属于其中之一 :) 感谢 Fiddler。
事不宜迟,下载并安装 Fiddler……(我在 Windows 8 上)因此我选择了 Fiddler 4!请根据网站上的建议选择 2 或 4。
运行 FIDDLER 很简单。找到 Fiddler 并运行它……
现在,让我们再次使用 Fiddler 运行方法 CreateTweet
- URI:/Tweets!
所以,我们要向 TweetService
发送一个 POST
请求!
按照下面的屏幕截图:粘贴 TweetService
的地址,并将类型更改为 POST
!
添加对 CreateTweet
所需 URI 的调用:该方法的 UriTemplate
是 /Tweets。
现在,我们需要指定一个有效的请求头
这是因为我们希望明确告知我们要发送给服务器进行处理的数据格式!
请记住 CreateTweet
方法需要一个 TWEET 类型的参数!
指定request Header: Content-Type: application/json
,我们的数据将以 json 格式发送到服务器!
现在,我们来到了最重要的部分!指定消息正文——即在此情况下要保存的数据!(不用说,格式是 json!正如我们在请求头中指定的!)
所以,我们将发送一个 json 对象到服务器以作为我们调用 CreateTweet
方法的一部分进行保存!
{
"Id": 0,
"PostedBy": "Rahul Pawar via Fiddler",
"Text": "Saved tweet via Fiddler 4"
}
是时候点击Execute(执行)了。
200 的响应表明一切顺利!
快速调用 GetTweets
方法会返回新插入的 Tweet!
是时候测试我们的 UpdateTweet
方法了:UpdateTweet
用 Web Invoke 属性修饰,该属性接受 HTTP PUT
动词请求。
启动 Fiddler……
转到 Composer(作曲家)……输入 TweetService.svc 的地址……为此请求选择 PUT
作为 HTTP 动词……
添加对 UpdateTweet
所需 URI 的调用:该方法的 UriTemplate
是 /Tweet。
指定request Header: Content-Type: application/json
。
现在,我们来到了最重要的部分!指定消息正文——即通过 UpdateTweet
方法要更新的数据!
让我们更新 ID 为 2 的 Tweet,更新为以下内容:
{
"Id": 2,
"PostedBy": "UPDATED via Fiddler",
"Text": "UPDATED tweet via Fiddler"
}
是时候执行我们的 Update请求!
在 Inspectors(检查器)选项卡下,我们的 200 响应头表明一切都已顺利完成!记录已更新!
快速调用 GetTweets
方法会返回新更新的 Tweet!
是时候测试我们的 DeleteTweet
方法了:DeleteTweet
用 Web Invoke 属性修饰,该属性接受 HTTP DELETE
动词请求。
启动 Fiddler……
转到 Composer(作曲家)……输入 TweetService.svc 的地址……为该请求选择 DELETE
作为 HTTP 动词……
添加对 DeleteTweet
所需 URI 的调用:该方法的 UriTemplate
是 /Tweet/{deleteTweetId}。
我们将删除 ID 为 2 的 Tweet(在上一步中更新的那个)请注意——在 URI 中,我们只是在最后指定了 Tweet ID!……URI……/2……
注意*:根据HTTP 规范——对于 DELETE
和 GET
动词,我们不需要发送请求正文!不用说,REST 遵循这个规范。
是时候点击Execute(执行)了!
结果:我们得到 200 的响应——ID 为 2 的 Tweet 已被删除!
快速调用 GetTweets
方法会返回剩余的 Tweet(s)!
注意上面显示的 GetTweets
结果中缺少 ID 为 2 的 Tweet,因为我们已成功删除它!
至此,我们已完成了对 TweetService.svc 的快速测试,并已确定它工作正常!
现在是时候创建我们 TweetService.svc 的客户端了。我们将在下一节中这样做。
创建和测试 WCF RESTFul Web Service 客户端
Fiddler 对于一些快速的单元测试很有用。现在是时候构建我们自己的 Web Service 客户端了。让我们开始添加一个名为 TweetClient
的新 Console Application 项目,它将成为消费我们 RESTFul Tweet Web Service 的客户端。
由于 RESTFul 服务未生成 WSDL,因此我们无法通过简单地引入服务引用来获得默认服务代理类等便利。
我们将不得不自己完成所有必需的序列化、反序列化、网络调用、创建数据传输对象等工作来消费我们的 RESTFul Tweet Web Service……听起来很糟糕,但请坚持住,因为在 .NET 中这样做非常简单!
让我们创建一个名为 Services 的文件夹,并引入一个名为 TweetService
的类,它将负责我们 Web 客户端的所有通信……
引入 GetTweets
方法!
好的……我们还没有 Tweet 的定义!让我们先解决这个问题……
让我们创建一个名为 Transports 的文件夹,并引入一个名为 Tweet
的类,该类基本上是客户端的 Tweet
对象定义……
我们客户端的 Tweet
对象的定义与我们在 TweetBL
项目中定义的不会有太大区别!
添加对 Transports 文件夹中 Tweet
对象的引用……一切都很好!
现在,回到 GetTweets
方法……
在 GetTweets
方法中,我们将使用 Web Client 并要求 Web 服务器以 JSON 格式向我们传递数据。
下面是 GetTweets
方法的定义——注意它有适当的文档说明
public IList<Tweet> GetTweets()
{
// Making a call to our GetTweets Endpoint by employing a WebClient!
var client = new WebClient();
// Requesting JSON from the Web Server - because we have deserializer for JSON in place
client.Headers.Add("Accept", "application/json");
// Using WebClient we can download a file, a string etc.. we will download String
// because we will be receiving the data from our TweetService.svc in XML format or JSON format
// ...all we have to do than is create a deserializer to create a object from that
// received XML/JSON data! .. sweet
// to download a string we need to give the web address of our service endpoint
// below I have specified the local address and the correct endpoint to access the
// required information
var result = client.DownloadString("https://:47354/TweetService.svc/GetTweets");
// Now we will employ the JSON desiralizer that comes with .NET to de-serialize and
// create a Tweet object for us from the response received from TweetService.svc
var serializer = new DataContractJsonSerializer(typeof(List<Tweet>));
List<Tweet> resultObject;
using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(result)))
{
resultObject = (List<Tweet>)serializer.ReadObject(stream);
}
return resultObject;
}
GetTweets
方法的屏幕截图
哎呀——那条该死的红色波浪线!它抱怨 DataContractJsonSerializer
……让我们添加引用并修复它!
添加对:System.Runtime.Serialization
的引用以访问 DataContractJsonSerializer
。
注意*:已在 TweetClient
项目中添加了引用。
问题已解决!
是时候运行我们的 GetTweets
方法了。
步骤 1:将 Tweet.WCFService.RESTful
设置为默认启动项目。
步骤 2:在 Tweet.WCFService.RESTful
中双击 TweetService.svc。
步骤 3:转到**Debug**(菜单选项中的“调试”),然后选择**Start without Debugging**(启动而不调试)。
步骤 4:您的默认浏览器将显示以下页面!
步骤 5:跳转到 TweetClient
项目。
步骤 6:选择 TweetClient
项目,右键单击并按照下面的屏幕截图操作。
注意*:我将把 Program
类留在 TweetClient
项目中供您自己探索!因为它不包含任何与文章相关的代码。它只有一个花哨的 GUI(您决定 :)) 来调用我们的 RESTFul Tweet 服务!
按照步骤 6 操作后,我们劳动成果的展示
选择L(按 Enter)列出所有 Tweets - 它调用我们的 GetTweets
方法
轰……我们遇到了一个异常!异常在 TweetClient
项目的 GetTweets
方法中抛出。
让我们仔细看看异常。
在 TweetClient
项目的 TweetService
类的第 39 行和第 45 行设置断点。
再次运行 TweetClient
项目……以探索断点处应用程序的条件……
注意*:当 GUI 弹出时,请记住输入L然后按 Enter!
当执行到达第 39 行时按 F10,当它在第 45 行时,将光标指向第 39 行的变量 result
……我们需要在 JSON 查看器中查看变量 result 中存储的内容……按照下面的步骤操作。
在那里,一旦我们选择了 JSON 查看器……问题就变得有点明显了!
高亮的警告消息清楚地说明了问题……我们请求了 JSON 格式,但 Web 服务器没有按照我们的请求进行!
由于返回的结果不是 JSON 格式,我们的客户端无法将其反序列化。
现在要解决这个问题,我们需要在 Tweet.WCFService.RESTful
项目中进行更改……
我们需要让我们的 RESTFul TweetService.svc 更加灵活,以便它可以从其客户端获取关于结果返回格式的信息……
我们可以通过修改 Tweet.WCFService.RESTful
项目的 Web.config 文件来实现应用程序级别的更改……
更改 Web.config 文件!
添加 automaticFormatSelectionEnabled
将使我们的服务客户端能够指定返回数据的格式……默认情况下,Web 服务器返回 XML format
,因此我们的 TweetClient
项目 GetTweets
方法抛出了异常,因为它请求了 JSON 格式并且基于服务器会遵守其请求的假设……嗯,现在它会了!!
现在,我们在这里,让我们再次按照上面提到的 6 个步骤来测试我们的 GetTweets
方法
是的,请记住删除我们添加的断点……相信我,这次一切都会顺利的 :)
遵循(6 个步骤)后,这次我们得到以下结果(选择L后)
Voilà:所有记录中的推文都已返回……!我们的 GetTweets
方法终于成功了!
现在,继续处理其余方法。
测试 GetTweetByID
方法……
对于这个 GetTweetByID
方法,我们将请求并反序列化 XML 而不是 JSON。
GetTweetByID
方法
测试方法——现在,请再次按照上面提到的6 个步骤来测试我们的 GetTweetById
方法。
程序运行后,请按照以下步骤操作
选择L获取当前存储的所有推文列表。
输入 1 来提取 ID 为 1 的推文……
哎……又出麻烦了……
如果我们查看异常的详细信息
为了修复这个问题……我们需要介绍我们在 TweetBL
项目 Tweet
类中定义的 XML Schema 定义。
所以,在 Tweet
客户端项目的Transports文件夹的 Tweet
类中,添加以下一行……
现在再次运行测试……最终结果……
是时候进入创建 Tweet
方法了。
不,不幸的是,使用 WebClient
,您无法指定要用于服务操作的 HTTP 动词。Web Client 对所有请求都使用 GET HTTP 动词。
由于我们在创建/更新 Tweet 时需要更多控制,因此现在我们需要使用 HTTP Web Request 而不是 Web Client,因为它将为我们提供使用其他 HTTP 动词进行请求的能力。
CreateTweet
方法
是时候测试 CreateTweet
方法了
按照6 个步骤(上面提到)然后按照下面提到的步骤操作
输入 N - 用于输入 New Tweet(新推文)……
输入 L,这是结果
是时候编写和测试 Update
方法了
与 CreateTweet
方法相比,Update
方法只有一个区别,那就是它使用的 HTTP 动词……
Update
方法需要使用 PUT
HTTP 动词。
Update
方法
测试 Update
方法——按照(上面提供的)6 个步骤以及下面指定的步骤……
检索我们使用 CreateTweet
方法保存的 Tweet……
选择 E 选项进行编辑
选择 L 列出所有 Tweets……
最终结果……更新的 Tweet!
现在,最后一个方法——DeleteTweet
方法!
对于 Delete
,我们要发送一个不是 Tweet
对象,但包含 Tweet Id
属性的对象……
在 TweetClient
项目中添加一个新的 Transport 对象……它将包含我们想要用于 DeleteTweet
操作的对象定义的必需定义!
DeleteTweet
方法
是时候测试 DeleteTweet
方法了
按照上面提到的6 个步骤,然后按照下面的步骤……
输入我们使用 CreateTweet
方法添加的 Tweet 的 ID……选择 D 选项删除它……
选择 Y(是)- 确认删除:还输入 L 列出所有 Tweets……
我们的劳动成果……ID 为 7 的 Tweet 已被删除……返回的 Tweets 不包含 ID 为 7 的 Tweet!
我们完成了!!!!
最终想法
这是一篇关于WCF Web Service的文章!另外,这是关于 WCF Ajax Web Service的文章链接!
这两篇文章都是我写的。两篇文章都演示了上述服务的简单示例,展示了 WCF 的强大功能和简单性。
现在该我告别了。欢迎随时提问、提供反馈和任何其他事宜,因为我和您在同一条船上。附注:这艘船叫做“燃烧与学习”。
历史
- 版本 1 提交于 2015 年 4 月 19 日