快速入门系列--WCF--03RESTFUL服务与示例

之前介绍了基于SOAP的Web服务,接下来将介绍基于REST的轻量级的Web服务。

REST(Representational State Transfer)与技术无关,代表一种软件架构风格,可以成为ROA面向资源的架构,之前Web服务的架构风格主要是SOAP和XML-RPC。REST从资源的角度来观察整个网络,分布在各处的资源有URI来标识,而客户端通过URI来获取资源的表征,获得这些表征使得应用程序转变了状态。作者是这样解释的,"设计良好的网络应用表现为一系列的网页,这些网页可以看做是虚拟的状态机,用户选择这些链接导致下一网页传输给客户端展现给使用的人,而这正代表了状态的改变"。一般来说,REST是建立在HTTP、URI、XML、JSON等概念的基础之上的,其特点是:一切数据都是资源,所有的资源均可被你唯一标识,采用统一而简单的接口,基于表征的通信,无状态服务调用。

在Web Http编程模型中,包含的主要的类型有:WebHttpBinding, WebHttpBehavior, WebGetAttribute/WebInvokeAttribute和WebServiceHost等。其中值得一提的是WebHttpSecurityMode:None表示请求未使用任何安全性;Transport表示请求使用传输级安全;TransportCredentialOnly表示仅提供基于HTTP客户端身份验证。这儿可以看到由于WebHttpBinding不是基于SOAP协议,因此WS-*协议簇均无法使用。在消息内容上,可以通过设置相关属性进行,例如RequestFormat=WebMessageFormat.Xml,ResponseFormat=WebMessageFormat.Json,BodyStyle=WebMessgaeBodyStyle.Bare。

对于SOAP协议来说,操作的选择是通过<Action>来决定的,而在这儿时通过UriTemplate属性表示的一个URI模板来决定的,常见的路由例子如接下来的,/filename.{ext}/, /{filename}.jpg/, /{filename}.{ext}/, /{a}.{b}someLiteral{c}{d}/等多种通配符方式,和ASP.NET一样由一个通过注册一个静态的路由表,之后通过路由表来路由请求。

接下来,介绍几个比较有趣的概念,分别是输出缓存、条件获取和更新。前者由于涉及到ASP.NET的CacheProfile的使用,需要使用ASP.NET的兼容模式,不太推荐,可以考虑使用其他的缓存方式进行缓存,比如Redis。后者涉及一个http协议中的请求头ETag,通过对其的判断来决定内容是否已经被更新,比较有实际意思,例子的代码如下。

Interface

 1 namespace Sory.CoreFramework.Interface
 2 {
 3 [ServiceContract(Namespace = "http://www.sory.com")]
 4 public interface IEmployees
 5 {
 6 [WebGet(UriTemplate="all")]
 7 IEnumerable<Employee> GetAll();
 8  
 9 [WebGet(UriTemplate = "{id}")]
10 Employee Get (String id);
11 
12 [WebInvoke(UriTemplate = "/", Method = "POST")]
13 void Create(Employee employee);
14 
15 [WebInvoke(UriTemplate = "/", Method = "PUT")]
16 void Update(Employee employee);
17 
18 [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
19 void Delete(string id);
20 }
21 }

Service的实现

 1 public class EmployeesService : IEmployees
 2 {
 3 private static IList<Employee> _employees = new List<Employee>
 4 {
 5 new Employee {Id="001", Name="xiongda", Department="xiaowei", Grade="T13"},
 6 new Employee {Id="002", Name="xionger", Department="xiaowei", Grade="T15"}
 7 };
 8 
 9 public IEnumerable<Interface.Entities.Employee> GetAll()
10 {
11 var hashCode = _employees.GetHashCode();
12 WebOperationContext.Current.IncomingRequest.CheckConditionalRetrieve(hashCode);
13 WebOperationContext.Current.OutgoingResponse.SetETag(hashCode);
14 return _employees;
15 }
16 
17 public Interface.Entities.Employee Get(string id)
18 {
19 var employee = _employees.FirstOrDefault(e => e.Id == id);
20 if (null == employee)
21 {
22 //WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
23 throw new WebFaultException(HttpStatusCode.NotFound);
24 }
25 
26 WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
27 return employee;
28 }
29 
30 public void Create(Interface.Entities.Employee employee)
31 {
32 _employees.Add(employee);
33 }
34 
35 public void Update(Interface.Entities.Employee employee)
36 {
37 var existing = _employees.FirstOrDefault(e => e.Id == employee.Id);
38 if (null == existing)
39 {
40 throw new WebFaultException(HttpStatusCode.NotFound);
41 }
42 
43 existing.Name += Guid.NewGuid().ToString();
44 WebOperationContext.Current.IncomingRequest.CheckConditionalUpdate(existing.GetHashCode());
45 
46 Delete(employee.Id);
47 _employees.Add(employee);
48 
49 WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
50 }
51  
52 public void Delete(string id)
53 {
54 var employee = this.Get(id);
55 if (null != employee)
56 {
57 _employees.Remove(employee);
58 }
59 }
60 }

Server

 1 public static class ServiceHost
 2 {
 3 public static void Start()
 4 {
 5 using (WebServiceHost host = new WebServiceHost(typeof(EmployeesService)))
 6 {
 7 host.Open();
 8 Console.Read();
 9 }
10 }
11 }
12 配置文件
13 <system.serviceModel>
14 <services>
15 <service name ="Sory.CoreFramework.Service.EmployeesService">
16 <endpoint address="http://127.0.0.1:3721/employees" binding="webHttpBinding"
17 contract="Sory.CoreFramework.Interface.IEmployees"/>
18 </service>
19 </services>
20 </system.serviceModel>

Client

 1 public class CheckDemo
 2 {
 3 public static void Test()
 4 {
 5 using (ChannelFactory<IEmployees> channelFactory = new ChannelFactory<IEmployees>("employeeService"))
 6 {
 7 var proxy = channelFactory.CreateChannel();
 8 Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp));
 9 }
10 }
11 }
12 配置文件
13 <system.serviceModel>
14 <behaviors>
15 <endpointBehaviors>
16 <behavior name="webBehavior">
17 <webHttp/>
18 </behavior>
19 </endpointBehaviors>
20 </behaviors>
21 <client>
22 <endpoint name="employeeService" address="http://127.0.0.1:3721/employees" behaviorConfiguration="webBehavior"
23 binding="webHttpBinding" contract="Sory.CoreFramework.Interface.IEmployees">
24 </endpoint>
25 </client>
26 </system.serviceModel>

参考资料:

[1]蒋金楠. WCF全面解析[M]. 上海:电子工业出版社, 2012.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏码农阿宇

EF Core下利用Mysql进行数据存储在并发访问下的数据同步问题

小故事 在开始讲这篇文章之前,我们来说一个小故事,纯素虚构(真实的存钱逻辑并非如此) 小刘发工资后,赶忙拿着现金去银行,准备把钱存起来,而与此同时,小刘的老婆刘...

3425
来自专栏魏琼东

分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载

一、分布式消息总线      在很多MIS项目之中都有这样的需求,需要一个及时、高效的的通知机制,即比如当使用者A完成了任务X,就需要立即告知使用者B任务X已经...

4087
来自专栏GuZhenYin

ASP.NET Core文件上传与下载(多种上传方式)

官方机器翻译的地址:https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads

2570
来自专栏恰童鞋骚年

.NET Core微服务之基于MassTransit实现数据最终一致性(Part 2)

  在上一篇中,我们了解了MassTransit这个开源组件的基本用法,这一篇我们结合一个小案例来了解在ASP.NET Core中如何借助MassTransit...

1514
来自专栏小特工作室

基于微软企业库的AOP组件(含源码)

软件开发,离不开对日志的操作。日志可以帮助我们查找和检测问题,比较传统的日志是在方法执行前或后,手动调用日志代码保存。但自从AOP出现后,我们就可以避免这种繁琐...

2357
来自专栏木宛城主

开源依旧:再次分享一个进销存系统

开篇 我之前发过一篇博文《两天完成一个小型工程报价系统(三层架构)》,不少朋友向我要源码学习,后来久而久之忘记回复了。今天我再分享一个进销存系统,只为学习,没...

1K10
来自专栏菩提树下的杨过

用VS2010调试微软开放的部分源码

msdn上有一篇讲解如何用vs2008调试源码的文章:http://blogs.msdn.com/b/sburke/archive/2008/01/16/con...

2325
来自专栏GuZhenYin

ASP.NET Core文件上传与下载(多种上传方式)

前言 前段时间项目上线,实在太忙,最近终于开始可以研究研究ASP.NET Core了. 打算写个系列,但是还没想好目录,今天先来一篇,后面在整理吧. ASP.N...

6036
来自专栏程序员的SOD蜜

使用Topshelf创建自宿主的Windows服务程序

在传统的Windows服务开发过程中,需要添加一个服务安装程序,里面写安装,启动和停止服务等逻辑。现在,使用TopSelf可以简化这个过程。具体请看官网说明: ...

2435
来自专栏挖坑填坑

使用.net core ABP和Angular模板构建博客管理系统(创建后端服务)

1052

扫码关注云+社区

领取腾讯云代金券