转:http://www.cnblogs.com/shanyou/archive/2013/06/11/3131583.html

在SOA的世界中,最重要的一个概念就是契约(contract)。在云计算的世界中,有关通信的最重要的概念也是契约。XML具有强大对数据的描述能力,Atom格式和AtomPub都建立在XML之上,在Google和微软的推动下,也已经成为标准。但是,Atom/AtomPub和ODBC/OLEDB这样的真正数据交互协议相比较,还有着根本上的欠缺:缺乏数据类型的具体描述,降低了交互性能。缺乏对数据查询的控制能力,比如返回特定的数据集合的区间,或者说分页能力等等。微软基于EDM模型释出了:OData,这里也可以看出Entity Framework对于NHibernate这样的ORM的工具不同的战略考虑。

在.NET中,早期是用Remoting/Webservice来处理所有程序间的通信,从.NET 3.0开始使用WCF统一了通信模型,ASP.NET MVC4的推出,形成大的One ASP.NET战略,增加了WebAPI和SingalR作为通信服务:

开放数据协议(OData)是一个查询和更新数据的Web协议。OData应用了web技术如HTTP、Atom发布协议(AtomPub)和JSON等来提供对不同应用程序,服务和存储的信息访问。除了提供一些基本的操作(像增删改查),也提供了一些高级的操作类似过滤数据和实体的导航。OData扩展了上述的协议但是不是取代他们。他可以被XML(ATOM)或者JSON取代但是OData的重要在于它符合REST原则。在某种意义上,它建立在'简单'的REST HTTP 服务上,并且有着清晰的目标——简化和标准化我们操作和查询数据的方式。如果你过去在给你的REST服务创建搜索、过滤、或者分页API的时候感觉很麻烦,那么OData将是一个不错的选择。

目前很多接口,无论是基于SOAP、REST还是别的都在交换数据时使用不同的模式。这种方法随后返回一大堆客户记录。你随后可以决定添加分页支持。你希望将结果捆绑在一个网格中,并对数据排序。最后,决定想要查询的东西,通过比如邮政编码来查询。

  首先是,没有创建泛型客户端的途径,而这些和API紧密联系,因为它不知道参数的顺序或者模式被使用的顺序。因为不能创建泛型客户端,你必须为每一个你希望暴露的API创建客户端。简单的基础HTTP API可以实现,但其仍旧很昂贵。逐渐增多的多样性客户端与这些API通信加剧了这个问题。

  这种模式的第二个问题是它迫使开发人员进行很艰难的权衡。我应该暴露多少个查询?你必要在暴露每一个你能想到内容和少暴露一些,从而削弱服务之间协调。前者导致API 需要管理的界面的增加,后者会导致我们通常所说的“数据竖井”,也就是关键数据在特定模式中锁定,其他应用不能够简单应用,因为它没有以一种需要的方式暴露给这个应用。服务试图比单一应用要获得更长久一些,因此你需要以一种方式设计API,使其能够持久,所以如果你发现你需要添加服务借口的新版本可不太好办,比如创建新的客户端。在很多案例中,服务开发者和客户端开发者并不是同一个人,因而改变服务接口简直就是不可能的事情。

  通过OData,我们采取不同的方法。取代创建客户端签名和参数,我们问了如下的问题:“如果你将数据集作为源处理,并为最频繁使用的操作定义模式,像查询、分页、排序、新建、删除和更新,服务接口因该是什么样子的?” 这也就导致OData的创建。OData解决了上面提到的关键服务设计挑战。

我们来看一下启用OData协议的WebAPI的例子:

http://localhost:8080/api/meetings

http://localhost:8080/api/meetings?$filter=(Leader eq ‘Mark Nichols’)

http://localhost:8080/api/meetings?$top=2

http://localhost:8080/api/meetings?$filter=MeetingDate eq datetime’2013-01-17′

在项目中启用OData查询,首先在项目加入Web API的OData支持,通过Nuget 查找ASP.NET Web API OData

Microsoft.AspNet.WebApi.OData提供可一系列的类扩展了Web API。

在项目中启用OData查询:

public static void Register(HttpConfiguration config) 

    // ... 
    config.EnableQuerySupport(); 
    // ... 
}

如果是使用self-hosting方式,在HttpSelfHostConfiguration上启用EnableQuerySupport():

var config = new HttpSelfHostConfiguration(new Uri("http://localhost:8080")); 
config.EnableQuerySupport();

然后将Controls上的Action的返回结果更改为IQueryable,并打上标签[Queryable()]:

        // GET api/Meeting
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
public IQueryable<Meeting> Get()
{
return _scheduledMeetings.AsQueryable();
}
需要添加 using System.Web.Http.OData.Query; 我们下AllowedQueryOptions 看支持那些OData的类型:
   // Summary:
// OData query options to allow for querying.
[Flags]
public enum AllowedQueryOptions
{
// Summary:
// A value that corresponds to allowing no query options.
None = 0,
//
// Summary:
// A value that corresponds to allowing the $filter query option.
Filter = 1,
//
// Summary:
// A value that corresponds to allowing the $expand query option.
Expand = 2,
//
// Summary:
// A value that corresponds to allowing the $select query option.
Select = 4,
//
// Summary:
// A value that corresponds to allowing the $orderby query option.
OrderBy = 8,
//
// Summary:
// A value that corresponds to allowing the $top query option.
Top = 16,
//
// Summary:
// A value that corresponds to allowing the $skip query option.
Skip = 32,
//
// Summary:
// A value that corresponds to allowing the $inlinecount query option.
InlineCount = 64,
//
// Summary:
// A value that corresponds to the default query options supported by System.Web.Http.QueryableAttribute.
Supported = 121,
//
// Summary:
// A value that corresponds to allowing the $format query option.
Format = 128,
//
// Summary:
// A value that corresponds to allowing the $skiptoken query option.
SkipToken = 256,
//
// Summary:
// A value that corresponds to allowing all query options.
All = 511,
}

上面有个Format,我们可以进行格式化输出。使用下面的代码对Format进行数据格式化:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json"); config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");

            config.EnableQuerySupport();
}

另外需要注意的一点是OData查询是大小写敏感的。

我将使用Fiddler去测试这个服务

我们没有写任何一个特别的逻辑去支持这些功能,全部都由框架来提供的。是不是OData为你的搜索、过滤、或者分页API的时候提供了一个很好的选项。

然而,如果要向组织外部公开可查询的操作,可以利用查询验证添加一个保护层以保护我们的服务。微软的程序经理Hongmei Ge介绍了几种在Queryable API中添加验证的场景。

Hongmei指出的第一个场景是,使用AllowedQueryOptions属性,只允许包含$top和$skip的查询。如下所示:

[Queryable(AllowedQueryOptions = AllowedQueryOptions.Skip | AllowedQueryOptions.Top)] 
public IQueryable Get(int projectId)

还可以使用MaxTop和MaxSkip属性将$top和$skip的最大值限制在100和200:

[Queryable(MaxTop = 100)] 
public IQueryable Get(int projectId)

[Queryable(MaxSkip = 200)] 
public IQueryable Get(int projectId)

利用AllowedOrderByProperties,可以将结果按Id属性排序,因为按其他属性排序可能会很慢:

[Queryable(AllowedOrderByProperties = "Id")] 
public IQueryable Get(int projectId)

如果允许客户端在$filter内使用相等比较,应该使用AllowedLogicalOperators对其进行验证:

[Queryable(AllowedLogicalOperators = AllowedLogicalOperators.Equal)] 
public IQueryable Get(int projectId)

将AllowedArithmeticOperators设置为None,就可以关闭$filter中的算术操作:

[Queryable(AllowedArithmeticOperators = AllowedArithmeticOperators.None)] 
public IQueryable Get(int projectId)

你还可以使用AllowedFunctions属性来限制$filter中的函数使用:

[Queryable(AllowedFunctions = AllowedFunctions.StartsWith)] 
public IQueryable Get(int projectId)

上面的代码意味着只能在$filter中使用StartsWith函数。

Hongmei还演示了高级场景中的查询验证,如为$skip、$top、$orderby、$filter自定义默认验证逻辑,以及使用ODataQueryOptions来验证查询。

相关文章:

OData Developers Reference: http://www.odata.org/developers/

OData in ASP.NET: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api

Limiting OData Query Options: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options

OData Security: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-security-guidance

Add an OData Feed to Your App Using Web API:http://marknic.net/2013/03/02/add-an-odata-feed-to-your-app-using-web-api/

Working with OData Queries in ASP.NET Web API:http://www.codeguru.com/csharp/.net/working-with-odata-queries-in-asp.net-web-api.htm

在ASP.NET Web API OData中利用Queryable API进行验证: http://www.infoq.com/cn/news/2013/02/queryable-api

一个创建 OData 的新选项: Web API:http://msdn.microsoft.com/zh-cn/magazine/dn201742.aspx

Building OData Service using ASP.Net Web API Tutorial – Part 1

示例代码下载 : 原例子有点小问题,堪正如下: http://files.cnblogs.com/files/HouZhiHouJueBlogs/WebApiOData.zip

Odata简介和Demo的更多相关文章

  1. Web Api系列教程第2季(OData篇)(一)——OData简介和一个小应用

    第一季的链接以及系列导航:http://www.cnblogs.com/fzrain/p/3490137.html 在这里,首先要感谢Taiseer Joudeh不断的为我们带来最新的技术分享,楼主对 ...

  2. Disruptor并发框架(一)简介&上手demo

    框架简介 Martin Fowler在自己网站上写了一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金融交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平台上,其核心是一 ...

  3. 【JSONCpp】简介及demo

    一.JSON简介 JSON 一种轻量级的数据交换格式,易于阅读.编写.解析,全称为JavsScript ObjectNotation. JSON由两种基本结构组成 ①   名字/值 对的集合,可以理解 ...

  4. PyQt5简介及demo

    PyQt5说明 pyqt5是一套Python绑定Digia QT5应用的框架.它可用于Python 2和3.本教程使用Python 3.Qt库是最强大的GUI库之一.pyqt5的官方网站http:// ...

  5. 国外源码精品-Android-PullToRefresh 简介与DEMO导入

    转载地址:http://my.oschina.net/cuitongliang/blog/170708 (一)&&http://my.oschina.net/cuitongliang/ ...

  6. Flask简介,安装,demo,快速入门

    1.Flask简介 Flask是一个相对于Django而言轻量级的Web框架. 和Django大包大揽不同,Flask建立于一系列的开源软件包之上,这其中 最主要的是WSGI应用开发库Werkzeug ...

  7. JWT令牌简介及demo

    一.访问令牌的类型 二.JWT令牌 1.什么是JWT令牌 ​ JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌. JWT的使用场景: 一种情况是webapi,类似之 ...

  8. bluebird-api简介及demo

    var Promise = require("bluebird"); var fs = require("fs"); //方法Promise化 var read ...

  9. 轻量级通信引擎StriveEngine —— C/S通信demo(附源码)

    前段时间,有几个研究ESFramework的朋友对我说,ESFramework有点庞大,对于他们目前的项目来说有点“杀鸡用牛刀”的意思,因为他们的项目不需要文件传送.不需要P2P.不存在好友关系.也不 ...

随机推荐

  1. linux 动态库加载路径修改

    1.在 /etc/ld.so.conf 文件中添加搜索路径,重启或者 ldconfig 生效: 2.在 /etc/ld.so.conf.d 目录下添加 *.conf 文件,其中可以添加搜索路径,重启获 ...

  2. “全栈2019”Java第一百章:局部内部类可以实现接口吗?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  3. iOS没你想的那么安全?

    iOS应用由于直接运行在用户的手机上,而不是运行在后台服务器上,所以更容易被攻击. 任何系统都会有木马病毒的产生,不存在绝对的安全,iOS应用由于直接运行在用户的手机上,而不是运行在后台服务器上,所以 ...

  4. elasticsearch-5.1.1 安装的问题

    elasticsearch 5.1 安装过程中遇到了一些问题做一些记录. 问题一:警告提示 [2016-12-20T22:37:28,543][INFO ][o.e.b.BootstrapCheck ...

  5. mybatis常用默认配置

    设置参数 描述 有效值 默认值 cacheEnable 该配置影响所有映射器中配置的缓存全局开关 true.false true lazyLoadingEnable 延迟加载的全局开关.当它开启时,所 ...

  6. Working with Metal—Overview

    看完这个 WWDC 之后的总结. Metal 可以在单位时间内提供 10 倍的 draw call 调用. Background About Draw Call 每一次 draw call 调用都必须 ...

  7. ubuntu 14.04网卡配置以及关闭防火墙

    一.Ubuntu网卡配置如下: 在文件/etc/network/interfaces中进行以下配置 auto lo iface lo inet lookback auto eth0 iface eth ...

  8. javaweb Servlet接收Android请求,并返回json数据

    1.实现功能 (1)接收http请求 (2)获取Android客户端发送的参数对应的内容 (3)hibernate查询数据库 (4)返回json数据 2.java代码 import EntityCla ...

  9. Unity脚本生命周期与执行顺序

    文章目录 脚本生命周期 MonoBehavior生命周期图 脚本执行顺序 自定义执行顺序 在Unity中,脚本可以理解为附加在游戏对象上的用于定义游戏对象行为的指令代码.必须绑定在游戏对象上才能开始它 ...

  10. 一段关于Unix、Linux和Windows的暗黑史

    "SCO在言语上变得越来越好斗,而且还拒绝展示有关诉讼的任何证据,一切都似乎在表明,SCO只不过是在那里拉虎皮做大旗地狂言乱语.但是,微软 决不会轻易放弃这么可以一个利用这些狂言乱语的好机会 ...