[Web API] 让 Web API 支持 OData 查询

OData 介绍,并且说明如何在 Web API 上使用 OData 的做法。


前言


  OData 这词也算是目前热门的词汇之一,而在 ASP.NET Web API 中也支持了 OData 查询服务,本篇就来看看如何在 Web API 中加入 OData 来进行操作。

OData 为何?


  OData 全名 Open Data Protocol (开放数据协议),是由微软所提出的协议,主要目的在于透过 HTTP 服务提供 CRUD 的存取服务,最早出现于 WCF Data Service 中,当 Web API 推出时也提供支持 OData 协议,OData 协议建构在 RESTful 服务上,透过公开的 URI 位置进行操作,例如以下的一个 URI 位置范例:

http://localhost:49988/api/products?$top=1

  上面网址中 $top 就是 OData 协议中的一个命令,可以发现使用 OData 的操作方式就是在原本的 URI 位置后附加相对应要操作的命令,以下列出常用的 OData 命令:

  • $top:同 T-SQL 的 TOP,指定取得数据的前几笔。
  • $orderby:同 T-SQL 的 ORDER BY,可指定想排序的字段。
  • $skip:略过的笔数,可用于数据分页查询。
  • $filter:过滤条件,额外区分 eg (等于)、ne (不等于) 、lt (小于)、le (小于等于)、gt (大于)、ge (大于等于)。

  上方列出的是常用的命令,当然,因为 OData 还在继续发展中,所以日后可能将提供更多的命令可以使用,在使用 OData 命令时需要注意命令都需要包含“$”符号,且当如果有多个命令需要串接时,可以使用“&”符号进行串接,例如: /api/products?$top=1&$orderby=Id 。

  在 Web API 中透过了使用 OData 的帮助,能够让开发者在开发时期专心于数据处理与逻辑的撰写,能先不考虑因使用者的需求而需要进行某些排序、筛选的问题,开发人员也不必因特定需求而要多撰写对应方法,只需要最后透过 OData 命令就能够很有弹性的筛选出目标数据。

实践 OData


  首先提醒一点,如果要在 .Net Framework 4.0 上使用 OData,需要额外安装 OData 扩充组件,我们可以透过使用 NuGet 来安装 OData 组件,如下:

  接下来使用前几篇所建立的范例程序,先来看一段程序,以下是未使用 OData 的取得产品数据方法:


public IEnumerable GetAllProducts()
{
    IEnumerable products = new ProductDao().GetProducts();
    if (products.FirstOrDefault() != null)
        return products;
    else
        throw new HttpResponseException(HttpStatusCode.NotFound);
}

  接着如果我们要让这个取得产品数据的方法变成能够支持 OData 时该如何处理呢? 我们只要稍微改变一下它,看到此方法回传的类型为 IEnumerable 类型,在使用 OData 时需要将 IEnumerable 类型置换成 IQueryable 类型,为何要使用 IQueryable 而不使用 IEnumerable ?

  IQueryable 与 IEnumerable 都是在去执行例如 Count() 方法实际产生列取时才会开始产生 SQL 语法捞取数据,但其实两者执行时是有差异的,IEnumerable 在建立其枚举时其 SQL 语法就已经固定不变了,如后续再针对此 IEnumerable 附加额外的查询条件时 SQL 语法也不会变更,附加的查询则是将数据捞取出来后才在内存内再做塞选,而 IQueryable 呢? 参考 MSDN 文档中可以发现 IQueryable 多了一个 IQueryProvider 界面,IQueryProvider 能够保存枚举前额外增加的查询条件并变动最终执行的 SQL 语法,如对于实际要去数据库捞取数据时差异就会显现,如 LINQ to SQL、Entity Framework,详情可参考黑大的 关于IQueryable特性的小实验 文章。

  修改回传 IEnumerable 类型改成 IQueryable 类型后还需要记得在 GetProducts() 方法时加入 AsQueryable 进行转换,最后在方法加上 [Queryable] 属性,如下:


[Queryable]
public IQueryable GetAllProducts()
{
    IQueryable products = 
        new ProductDao().GetProducts().AsQueryable();
    if (products.FirstOrDefault() != null)
        return products;
    else
        throw new HttpResponseException(HttpStatusCode.NotFound);
}

  以上修改完成后,我们就能开始测试看看使用 OData 的效果,如下:

 取得第一笔数据

 使用 Price 排序

 略过第 1 笔并使用 Price 排序

 查询分类为 MVC 且 ID 为 1

  如此就完成使用 OData 协议的查询功能了,另外如果需要针对 JSON 返回的数据把一些字段隐藏起来的话,可以加入 System.Runtime.Serialization 组件参考,加入后在 Entity Class 的公开属性上加入 [IgnoreDataMember] 属性,如下:


public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
    public string Price { get; set; }
    [IgnoreDataMember]
    public int Stock { get; set; }
}

  这样回传的 JSON 数据就看不到该字段了,如下:

参考数据


Working with OData Queries in ASP.NET Web API

Supported OData Query Options

存取 OData 服务 (WCF Data Services)

将数据公开为 OData 服务 (WCF Data Services)

Queryable 类

[Web API][OData][笔记] OData初体验

OData Security Guidance

www.odata.org

Open Data Protocol by Example




以上文章叙述如有错误及观念不正确,请不吝啬指教
如有侵权内容也请您与我反应~谢谢您 :)