之前介绍了基于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

 namespace Sory.CoreFramework.Interface
{
[ServiceContract(Namespace = "http://www.sory.com")]
public interface IEmployees
{
[WebGet(UriTemplate="all")]
IEnumerable<Employee> GetAll(); [WebGet(UriTemplate = "{id}")]
Employee Get (String id); [WebInvoke(UriTemplate = "/", Method = "POST")]
void Create(Employee employee); [WebInvoke(UriTemplate = "/", Method = "PUT")]
void Update(Employee employee); [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
void Delete(string id);
}
}

Service的实现

 public class EmployeesService : IEmployees
{
private static IList<Employee> _employees = new List<Employee>
{
new Employee {Id="", Name="xiongda", Department="xiaowei", Grade="T13"},
new Employee {Id="", Name="xionger", Department="xiaowei", Grade="T15"}
}; public IEnumerable<Interface.Entities.Employee> GetAll()
{
var hashCode = _employees.GetHashCode();
WebOperationContext.Current.IncomingRequest.CheckConditionalRetrieve(hashCode);
WebOperationContext.Current.OutgoingResponse.SetETag(hashCode);
return _employees;
} public Interface.Entities.Employee Get(string id)
{
var employee = _employees.FirstOrDefault(e => e.Id == id);
if (null == employee)
{
//WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound;
throw new WebFaultException(HttpStatusCode.NotFound);
} WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
return employee;
} public void Create(Interface.Entities.Employee employee)
{
_employees.Add(employee);
} public void Update(Interface.Entities.Employee employee)
{
var existing = _employees.FirstOrDefault(e => e.Id == employee.Id);
if (null == existing)
{
throw new WebFaultException(HttpStatusCode.NotFound);
} existing.Name += Guid.NewGuid().ToString();
WebOperationContext.Current.IncomingRequest.CheckConditionalUpdate(existing.GetHashCode()); Delete(employee.Id);
_employees.Add(employee); WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
} public void Delete(string id)
{
var employee = this.Get(id);
if (null != employee)
{
_employees.Remove(employee);
}
}
}

Server

 public static class ServiceHost
{
public static void Start()
{
using (WebServiceHost host = new WebServiceHost(typeof(EmployeesService)))
{
host.Open();
Console.Read();
}
}
}
配置文件
<system.serviceModel>
<services>
<service name ="Sory.CoreFramework.Service.EmployeesService">
<endpoint address="http://127.0.0.1:3721/employees" binding="webHttpBinding"
contract="Sory.CoreFramework.Interface.IEmployees"/>
</service>
</services>
</system.serviceModel>

Client

 public class CheckDemo
{
public static void Test()
{
using (ChannelFactory<IEmployees> channelFactory = new ChannelFactory<IEmployees>("employeeService"))
{
var proxy = channelFactory.CreateChannel();
Array.ForEach<Employee>(proxy.GetAll().ToArray(), emp => Console.WriteLine(emp));
}
}
}
配置文件
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="employeeService" address="http://127.0.0.1:3721/employees" behaviorConfiguration="webBehavior"
binding="webHttpBinding" contract="Sory.CoreFramework.Interface.IEmployees">
</endpoint>
</client>
</system.serviceModel>

参考资料:

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

快速入门系列--WCF--03RESTFUL服务与示例的更多相关文章

  1. 前端学习 node 快速入门 系列 —— 服务端渲染

    其他章节请看: 前端学习 node 快速入门 系列 服务端渲染 在简易版 Apache一文中,我们用 node 做了一个简单的服务器,能提供静态资源访问的能力. 对于真正的网站,页面中的数据应该来自服 ...

  2. 快速入门系列--WebAPI--04在老版本MVC4下的调整

    WebAPI是建立在MVC和WCF的基础上的,原来微软老是喜欢封装的很多,这次终于愿意将http编程模型的相关细节暴露给我们了.在之前的介绍中,基本上都基于.NET 4.5之后版本,其System.N ...

  3. 快速入门系列--MVC--01概述

    虽然使用MVC已经不少年,相关技术的学习进行了多次,但是很多技术思路的理解其实都不够深入.其实就在MVC框架中有很多设计模式和设计思路的体现,例如DependencyResolver类就包含我们常见的 ...

  4. 快速入门系列--WebAPI--01基础

    ASP.NET MVC和WebAPI已经是.NET Web部分的主流,刚开始时两个公用同一个管道,之后为了更加的轻量化(WebAPI是对WCF Restful的轻量化),WebAPI使用了新的管道,因 ...

  5. 快速入门系列--WebAPI--03框架你值得拥有

    接下来进入的是俺在ASP.NET学习中最重要的WebAPI部分,在现在流行的互联网场景下,WebAPI可以和HTML5.单页应用程序SPA等技术和理念很好的结合在一起.所谓ASP.NET WebAPI ...

  6. [转]快速入门系列--WebAPI--01基础

    本文转自:http://www.cnblogs.com/wanliwang01/p/aspnet_webapi_base01.html ASP.NET MVC和WebAPI已经是.NET Web部分的 ...

  7. 前端学习 node 快速入门 系列 —— 初步认识 node

    其他章节请看: 前端学习 node 快速入门 系列 初步认识 node node 是什么 node(或者称node.js)是 javaScript(以下简称js) 运行时的一个环境.不是一门语言. 以 ...

  8. 前端学习 node 快速入门 系列 —— 简易版 Apache

    其他章节请看: 前端学习 node 快速入门 系列 简易版 Apache 我们用 node 来实现一个简易版的 Apache:提供静态资源访问的能力. 实现 直接上代码. - demo - stati ...

  9. 前端学习 node 快速入门 系列 —— 报名系统 - [express]

    其他章节请看: 前端学习 node 快速入门 系列 报名系统 - [express] 最简单的报名系统: 只有两个页面 人员信息列表页:展示已报名的人员信息列表.里面有一个报名按钮,点击按钮则会跳转到 ...

  10. vue 快速入门 系列 —— vue loader 上

    其他章节请看: vue 快速入门 系列 vue loader 上 通过前面"webpack 系列"的学习,我们知道如何用 webpack 实现一个不成熟的脚手架,比如提供开发环境和 ...

随机推荐

  1. 使用ShareSDK一键分享

    首先需要到ShareSDK官方网站注册并且下载SDK,创建应用,获得ShareSDK的Appkey:文件如图: 在ShareSDK中打开即可:输入项目名称和包名,选择要分享的平台,点击确定会自动生成一 ...

  2. iOS后台定位时授权提示一闪而过的解决办法

    今天做后台定位时,授权提示"允许 XXX 在您并未使用该应用时范文您的位置吗?"总是一闪而过,点不到,或者压根就不弹出.后来找到了解决问题的方法,那就是:将CLLocationMa ...

  3. blog搬迁

    因为一些个人原因,2年后继续写blog,但是blog搬到github上!具体的地址为: http://www.94geek.com 内容以linux的c开发,分布式存储和分布式计算,还有架构为主.

  4. 开启个人blog~

    希望自己能坚持写blog,不断的总结,不断的沉淀.

  5. 第十章 PageRank——Google的民主表决式网页排名技术

    搜索引擎的结果取决于两组信息:网页的质量信息,这个查询与每个网页的相关性信息.这里,我们介绍前一个. 1.PageRank算法原理 算法的原理很简单,在互联网上,如果一个网页被很多其他网页所链接,说明 ...

  6. Django如何搭建服务器

    建立django站点: 新建Django项目,我这里是使用命令创建项目的. django-admin startproject HelloDjango  创建HelloDjango项目 然后进入到He ...

  7. Hibernate自动创建表

    只要在hibernate.cfg.xml添加这句话,就可以自动生成数据表 <property name="hibernate.hbm2ddl.auto">update& ...

  8. 解剖SQLSERVER 第四篇 OrcaMDF里对dates类型数据的解析(译)

    解剖SQLSERVER 第四篇  OrcaMDF里对dates类型数据的解析(译) http://improve.dk/parsing-dates-in-orcamdf/ 在SQLSERVER里面有几 ...

  9. MongoDB for C#基础入门

    笔者这里采用的是mongoDB官网推荐使用.net驱动: http://mongodb.github.io/mongo-csharp-driver/2.0/getting_started/quick_ ...

  10. 3年的坚持,最终造就著作——《Learninghard C#学习笔记》

    前言 起初开始写博文主要是记录学习过程中对学到内容的自我总结和理解,同时也希望本人的理解可以帮助到一些走在学习路上的朋友.但是令我没有想到的是,我总结的博文得到了广大园友的评论和支持,正是博友的支持, ...