WCF 4.0 进阶系列 – 第十五章 构建REST服务(第二部分)

通过REST Web服务更新数据

REST Web服务提供了查询数据的操作以响应HTTP GET请求。但是,HTTP协议支持其他形式的请求,你可以利用这些消息类型提供操作以修改REST Web服务中的数据。最常见的情形是你使用HTTP POST请求创建新项目的操作,HTTP PUT请求更新现存数据的操作,使用HTTP DELETE请求定义删除项目的操作。
注意,上述常规并不是强制的,你也可以使用HTTP POST请求更新和删除数据,但这并不是推荐的做法。上述常规之所以这么定义的原因在于HTTP协议:POST请求是非对等的,而PUT请求与DELETE请求是对等的。这意味着PUT请求与DELETE请求可以多次重复地调用操作,这些操作都具有同样的效果:那就是它们看来仿佛只被执行了一次;而这对于POST却不一样。因此,如果你使用PUT请求实现一个更新操作,那么你可以对同一个数据重复地执行该更新操作,而且这些操作的结果始终都是一样。这个逻辑同样适用于DELETE请求;如果一个项目已经被删除,那么它还是继续被删除。但是,使用POST请求重复地添加相同的信息可能会造成重复的数据。
在一个WCF Web服务中,你通过WebGet特性类标记操作以响应HTTP GET请求;你还提供了一个模板以指定Web客户端可以访问的URI以调用服务的操作。为了支持HTTP的POST请求,PUT请求和DELETE请求,WCF提供WebInvoke特性类。同样地,你使用该特性类指明一个URI,此外你还可以指明操作响应请求消息的类型。当REST Web服务接收到一条对满足URI所定义类型的消息,那么该请求将调用该操作。这个体系使得多个操作可以响应同一个URI,只是这些操作期望不同的HTTP消息类型。这一点相当有用,而且让你避免考虑如何使用多个URI体系使相同的数据支持不同的操作。比如,IProductsSales服务合约中的GetCustomer操作可能定义为:
那么你可以使用相同的URI定义DeleteCustomer操作以删除一个客户,但是你必须指定该操作响应HTTP DELETE消息;
在下面的一组练习中,你将扩展ProductsSales REST Web服务以使该服务具有能插入,更新,和删除客户数据的操作。
 
练习:扩展ProductsSales服务以支持数据更新
1. 在Visual Studio中,在文本编辑模式下打开ProductsSalesService项目下的IProductsSales.cs文件。
2. 添加下面的操作到IProductsSales接口
你将要实现的CreateCutomer方法会添加一个新的客户到AdventureWorks数据库中。该操作标注了WebInvoke特性,因为是插入操作所以Method属性设置为POST。UriTemplate属性指定了创建新客户所需声明的详细信息(AdventureWorks数据库中的字段远不止这些,但是其他的列使用其默认值)。与上一节练习中GetAllOrders和GetAllCustomer操作中的skip和top参数一样,UriTemplate包含参数的顺序并不重要,只要你定义在CreateCustomer方法中参数与UriTempalte包含的参数名字相同即可。
一个Web程序能通过UriTemplate属性指定的URI提交POST请求以创建新的客户。比如,为John Sharp添加一个记录,那么应用程序将使用下面的URI:
Customers?FirstName=John&LastName=Sharp&EmailAddress=john@adventure-works.com&Phone=(123)456789
3. 添加下面的UpdateCustomer操作到IProductsSales接口中:
UpdateCustomer方法将修改指定客户编号对应客户的电子邮件地址和电话号码为参数所声明的值。该操作将响应HTTP PUT请求
4. 添加DeleteCustomer操作到IProductsSales接口中:
该方法将响应HTTP DELETE请求,然后从数据库中移除指定的客户。
5. 在文本编辑模式下打开IProductsSalesService项目中的ProductsSales.cs文件,然后在ProductsSales类中实现CreateCustomer方法:
上述方法使用传入的参数创建一个新的Contact对象,然后使用实体框架(EF)保持新对象到数据库中。请注意某些列自动生成其默认值。AdventureWorks数据库自动为新客户生成客户编号,并且CreateCustomer方法返回自动生成的ID。如果错误发生,该方法将抛出一个HTTP状态编码为400的WebFaultException异常。
6. 添加下面的UpdateCustomer方法到ProductsSales类中:
UpdateCustomer方法首先尝试找到需要更新的客户。当找到匹配的客户,该方法将把email参数和phone参数对应的值更新到客户对象并保存到数据库。请注意如果任何一个参数为null,那么该方法将不会更新该对象对应的字段;这就允许Web客户端程序在不要更新数据库中对应的字段事可以省略这些参数中的一个参数。如果没有从AdventureWorks数据库中发现匹配的客户,该方法将抛出一个HTTP状态编码为404的WebFaultException异常。如果在执行更新的过程中发生错误,那么该方法将抛出一个HTTP状态编码为400的WebFaultException异常。
7. 添加下面的DeleteCustomer方法到ProductsSales类中:
该方法与UpdateCustoomer方法类似,但该方法的目标是发现匹配的客户并从数据库中删除该客户。如果没有从AdventureWorks数据库中发现匹配的客户,该方法将抛出一个HTTP状态编码为404的WebFaultException异常。如果在执行更新的过程中发生错误,那么该方法将抛出一个HTTP状态编码为400的WebFaultException异常。
8.重新生成ProductsSalesService项目。请注意你仅仅是重新生成了ProductsSalesService项目而不是整个解决方案;因为此时,ProductsSales客户端程序不能成功地生成,这是因为CreateCustomer,UpdateCustomer和DeleteCustomer方法还没有包含在客户端带来中。你将在下面的练习中添加这些方法。
 
你可以从一个Web程序中通过提交POST,PUT和DELETE请求调用CreateCustomer,UpdateCustomer和DeleteCustomer操作。下面的代码片段是从一个ASP.NET Web程序中提取出来的,它演示了如何提交一个HTTP Delete请求以尝试从AdventureWorks数据库中删除客户编码为101的客户。
你不能简单地在Web浏览器比如IE的地址栏输入一个URI然后调用上面的操作。这是因为大多数浏览器都是通过发送HTTP GET请求工作;这是因为浏览器本身就是为了查询数据而不是为了修改数据。为了测试这些新的方法,你可以创建一个ASP.NET Web程序或者通过一个过程性的客户端程序调用这些操作。你下面的练习中,你将创建一个过程性客户端程序调用新添加的操作。
为了在客户端能调用新的操作,你首先必须更新ProductsSalesProxy类。
 
练习:更新客户端以测试ProductsSales REST Web服务
1. 在文本编辑模式下打开ProductsSalesClient项目的productsSalesProxy.cs文件。添加CreateCustomer,UpdateCustomer,和DeleteCustomer方法到ProductsSalesProxy类中:
这些方法与前一节的练习中定义的方法使用相同的模式;他们简单地实现了通过ClientBase<IProductsSales>类的Channel属性路由请求到服务。请注意,UpdateCustomer方法为参数email和phone设置了默认值,因为客户端在有需要时可以省略这两个参数中的任意一个。
2. 在文本编辑模式下打开ProductsSalesClient项目下的Program.cs文件,然后在Main方法中的proxy.Close()之前添加下面的代码:
上述代码通过依次调用新创建的方法从而实现了测试ProductsSales REST服务。第一个测试创建一个新的客户,然后调用GetCustomer方法时使用新创建客户的客户编号以验证CreateCustomer操作是否成功。第二个测试更改该客户的电子邮件地址,然后再次调用GetCustomer以获取更新后的客户的详细信息。最后一个测试方法删除新创建的客户,在删除操作结束后,如果DeleteCustomer方法成功那么GetCustomer方法将返回一个null对象。
3. 重新生成解决方案
4. 在非调适模式下运行解决方案。在ProductsSalesClient控制台窗口中,按下ENTER键。所有的新测试都将成功地执行:一个新客户端被添加,然后更新,随后被删除:
5. 在ProductsSalesClient控制台窗口中按ENTER键以关闭客户程序;然后在ProductsSalesHost控制台中按ENTER键以关闭寄宿程序。
 
 
posted @ 2011-10-26 13:17  On the road....  阅读(2135)  评论(3编辑  收藏  举报