本文转自:https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options

by Mike Wasson

OData defines parameters that can be used to modify an OData query. The client sends these parameters in the query string of the request URI. For example, to sort the results, a client uses the $orderby parameter:

http://localhost/Products?$orderby=Name

The OData specification calls these parameters query options. You can enable OData query options for any Web API controller in your project — the controller does not need to be an OData endpoint. This gives you a convenient way to add features such as filtering and sorting to any Web API application.

Before enabling query options, please read the topic OData Security Guidance.

  • Enabling OData Query Options
  • Example Queries
  • Server-Driven Paging
  • Limiting the Query Options
  • Invoking Query Options Directly
  • Query Validation

Enabling OData Query Options

Web API supports the following OData query options:

Option Description
$expand Expands related entities inline.
$filter Filters the results, based on a Boolean condition.
$inlinecount Tells the server to include the total count of matching entities in the response. (Useful for server-side paging.)
$orderby Sorts the results.
$select Selects which properties to include in the response.
$skip Skips the first n results.
$top Returns only the first n the results.

To use OData query options, you must enable them explicitly. You can enable them globally for the entire application, or enable them for specific controllers or specific actions.

To enable OData query options globally, call EnableQuerySupport on the HttpConfiguration class at startup:

C#Copy
public static void Register(HttpConfiguration config) { // ... config.EnableQuerySupport(); // ... } 

The EnableQuerySupport method enables query options globally for any controller action that returns an IQueryable type. If you don't want query options enabled for the entire application, you can enable them for specific controller actions by adding the [Queryable] attribute to the action method.

C#Copy
public class ProductsController : ApiController
{[Queryable]IQueryable<Product> Get() {} } 

Example Queries

This section shows the types of queries that are possible using the OData query options. For specific details about the query options, refer to the OData documentation at www.odata.org.

For information about $expand and $select, see Using $select, $expand, and $value in ASP.NET Web API OData.

Client-Driven Paging

For large entity sets, the client might want to limit the number of results. For example, a client might show 10 entries at a time, with "next" links to get the next page of results. To do this, the client uses the $top and $skip options.

http://localhost/Products?$top=10&$skip=20

The $top option gives the maximum number of entries to return, and the $skip option gives the number of entries to skip. The previous example fetches entries 21 through 30.

Filtering

The $filter option lets a client filter the results by applying a Boolean expression. The filter expressions are quite powerful; they include logical and arithmetic operators, string functions, and date functions.

Return all products with category equal to "Toys". http://localhost/Products?$filter=Category eq 'Toys'
Return all products with price less than 10. http://localhost/Products?$filter=Price lt 10
Logical operators: Return all products where price >= 5 and price <= 15. http://localhost/Products?$filter=Price ge 5 and Price le 15
String functions: Return all products with "zz" in the name. http://localhost/Products?$filter=substringof('zz',Name)
Date functions: Return all products with ReleaseDate after 2005. http://localhost/Products?$filter=year(ReleaseDate) gt 2005

Sorting

To sort the results, use the $orderby filter.

Sort by price. http://localhost/Products?$orderby=Price
Sort by price in descending order (highest to lowest). http://localhost/Products?$orderby=Price desc
Sort by category, then sort by price in descending order within categories. http://localhost/odata/Products?$orderby=Category,Price desc

Server-Driven Paging

If your database contains millions of records, you don't want to send them all in one payload. To prevent this, the server can limit the number of entries that it sends in a single response. To enable server paging, set the PageSize property in the Queryable attribute. The value is the maximum number of entries to return.

C#Copy
[Queryable(PageSize=10)]
public IQueryable<Product> Get() { return products.AsQueryable(); } 

If your controller returns OData format, the response body will contain a link to the next page of data:

JSONCopy
{"odata.metadata":"http://localhost/$metadata#Products","value":[{ "ID":1,"Name":"Hat","Price":"15","Category":"Apparel" }, { "ID":2,"Name":"Socks","Price":"5","Category":"Apparel" }, // Others not shown ],  "odata.nextLink":"http://localhost/Products?$skip=10" } 

The client can use this link to fetch the next page. To learn the total number of entries in the result set, the client can set the $inlinecount query option with the value "allpages".

http://localhost/Products?$inlinecount=allpages

The value "allpages" tells the server to include the total count in the response:

JSONCopy
{"odata.metadata":"http://localhost/$metadata#Products",
  "odata.count":"50", "value":[ { "ID":1,"Name":"Hat","Price":"15","Category":"Apparel" }, { "ID":2,"Name":"Socks","Price":"5","Category":"Apparel" }, // Others not shown ] } 
Note

Next-page links and inline count both require OData format. The reason is that OData defines special fields in the response body to hold the link and count.

For non-OData formats, it is still possible to support next-page links and inline count, by wrapping the query results in a PageResult<T> object. However, it requires a bit more code. Here is an example:

C#Copy
public PageResult<Product> Get(ODataQueryOptions<Product> options)
{ODataQuerySettings settings = new ODataQuerySettings() { PageSize = 5 }; IQueryable results = options.ApplyTo(_products.AsQueryable(), settings); return new PageResult<Product>( results as IEnumerable<Product>, Request.GetNextPageLink(), Request.GetInlineCount()); } 

Here is an example JSON response:

JSONCopy
{"Items": [{ "ID":1,"Name":"Hat","Price":"15","Category":"Apparel" }, { "ID":2,"Name":"Socks","Price":"5","Category":"Apparel" }, // Others not shown ], "NextPageLink": "http://localhost/api/values?$inlinecount=allpages&$skip=10", "Count": 50 } 

Limiting the Query Options

The query options give the client a lot of control over the query that is run on the server. In some cases, you might want to limit the available options for security or performance reasons. The [Queryable] attribute has some built in properties for this. Here are some examples.

Allow only $skip and $top, to support paging and nothing else:

C#Copy
[Queryable(AllowedQueryOptions=AllowedQueryOptions.Skip | AllowedQueryOptions.Top)]

Allow ordering only by certain properties, to prevent sorting on properties that are not indexed in the database:

C#Copy
[Queryable(AllowedOrderByProperties="Id")] // comma-separated list of properties

Allow the "eq" logical function but no other logical functions:

C#Copy
[Queryable(AllowedLogicalOperators=AllowedLogicalOperators.Equal)]

Do not allow any arithmetic operators:

C#Copy
[Queryable(AllowedArithmeticOperators=AllowedArithmeticOperators.None)]

You can restrict options globally by constructing a QueryableAttribute instance and passing it to the EnableQuerySupport function:

C#Copy
var queryAttribute = new QueryableAttribute()
{AllowedQueryOptions = AllowedQueryOptions.Top | AllowedQueryOptions.Skip,MaxTop = 100
};config.EnableQuerySupport(queryAttribute);

Invoking Query Options Directly

Instead of using the [Queryable] attribute, you can invoke the query options directly in your controller. To do so, add an ODataQueryOptionsparameter to the controller method. In this case, you don't need the [Queryable] attribute.

C#Copy
public IQueryable<Product> Get(ODataQueryOptions opts)
{var settings = new ODataValidationSettings() { // Initialize settings as needed. AllowedFunctions = AllowedFunctions.AllMathFunctions }; opts.Validate(settings); IQueryable results = opts.ApplyTo(products.AsQueryable()); return results as IQueryable<Product>; } 

Web API populates the ODataQueryOptions from the URI query string. To apply the query, pass an IQueryable to the ApplyTo method. The method returns another IQueryable.

For advanced scenarios, if you do not have an IQueryable query provider, you can examine the ODataQueryOptions and translate the query options into another form. (For example, see RaghuRam Nadiminti's blog post Translating OData queries to HQL, which also includes a sample.)

Query Validation

The [Queryable] attribute validates the query before executing it. The validation step is performed in the QueryableAttribute.ValidateQuerymethod. You can also customize the validation process.

Also see OData Security Guidance.

First, override one of the validator classes that is defined in the Web.Http.OData.Query.Validators namespace. For example, the following validator class disables the 'desc' option for the $orderby option.

C#Copy
public class MyOrderByValidator : OrderByQueryValidator
{// Disallow the 'desc' parameter for $orderby option. public override void Validate(OrderByQueryOption orderByOption, ODataValidationSettings validationSettings) { if (orderByOption.OrderByNodes.Any( node => node.Direction == OrderByDirection.Descending)) { throw new ODataException("The 'desc' option is not supported."); } base.Validate(orderByOption, validationSettings); } } 

Subclass the [Queryable] attribute to override the ValidateQuery method.

C#Copy
public class MyQueryableAttribute : QueryableAttribute
{public override void ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions) { if (queryOptions.OrderBy != null) { queryOptions.OrderBy.Validator = new MyOrderByValidator(); } base.ValidateQuery(request, queryOptions); } } 

Then set your custom attribute either globally or per-controller:

C#Copy
// Globally:
config.EnableQuerySupport(new MyQueryableAttribute());// Per controller:
public class ValuesController : ApiController { [MyQueryable] public IQueryable<Product> Get() { return products.AsQueryable(); } } 

If you are using ODataQueryOptions directly, set the validator on the options:

C#Copy
public IQueryable<Product> Get(ODataQueryOptions opts)
{if (opts.OrderBy != null) { opts.OrderBy.Validator = new MyOrderByValidator(); } var settings = new ODataValidationSettings() { // Initialize settings as needed. AllowedFunctions = AllowedFunctions.AllMathFunctions }; // Validate opts.Validate(settings); IQueryable results = opts.ApplyTo(products.AsQueryable()); return results as IQueryable<Product>; } 

[转]Supporting OData Query Options in ASP.NET Web API 2相关推荐

  1. [转]Web API Introduction to OData Services using ASP.NET Web API

    本文转自:http://mahedee.net/tag/web-api/ What is OData? OData Stands for Open Data Protocol. It is a dat ...

  2. 在ASP.NET Web API中使用OData的Action和Function

    本篇体验OData的Action和Function功能.上下文信息参考"ASP.NET Web API基于OData的增删改查,以及处理实体间关系".在本文之前,我存在的疑惑包括: ...

  3. Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)...

    原文:Asp.Net Web API 2第十七课--Creating an OData Endpoint in ASP.NET Web API 2(OData终结点) 前言 很久没更新博客了,加上刚过 ...

  4. ASP.NET Web Api OData

    ASP.NET Web API 2 Odata 基本使用 OData(开放数据协议)是一种ISO / IEC批准,OASIS标准定义的一组最佳实践用于构建和消费RESTful API中.OData 可 ...

  5. ASP.NET Core:从ASP.NET Web API迁移的多层数据服务应用程序

    目录 介绍 设置和运行示例应用程序 类库项目 依赖注入 访问应用程序设置 实体框架核心相关更改 主键标识插入问题 数据上下文和连接字符串 自定义存储库(Repositories) LINQ表达式翻新( ...

  6. 生成用于ASP.NET Web API的C#客户端API

    目录 介绍 主要特征 主要好处 背景 推定(Presumptions) 使用代码 步骤0:将NuGet软件包WebApiClientGen安装到Web MVC/API项目 步骤1:建立.NET Cli ...

  7. 生成用于ASP.NET Web API的TypeScript客户端API

    目录 介绍 备注 背景 推定(Presumptions) 使用代码 步骤0:将NuGet package WebApiClientGen和WebApiClientGen.jQuery安装到Web AP ...

  8. 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查

    首页 > 技术 > 编程 > NET > 前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查 前端使用AngularJS的$res ...

  9. 【ASP.NET Web API教程】2.3.3 创建Admin控制器

    原文:[ASP.NET Web API教程]2.3.3 创建Admin控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 3 ...

最新文章

  1. 【百度地图API】百度API卫星图使用方法和卫星图对比工具
  2. Nacos Go 微服务生态系列(一)| Dubbo-go 云原生核心引擎探索
  3. 中国智能控制器行业运营分析与竞争趋势展望报告2022-2027年版
  4. HDU 3062 Party(2-sat题模板+tarjan )
  5. tfidf算法 python_tf–idf算法解释及其python代码实现(下)
  6. Mysql 分组后组内排序按字段取最大或最小的数据
  7. linux系统修改为静态IP地址
  8. 事件CEvent的使用
  9. 【渝粤教育】电大中专电子商务网站建设与维护_1作业 题库
  10. cgroup: Control Group 分析 转载
  11. Microsoft Office Visio 2003画ER图
  12. Java项目源码下载S2SH基于java的保险业务管理系统
  13. 液晶显示技术 TCON介绍
  14. cat 常用的日志分析架构方案_深度剖析|数据库生产常用架构方案
  15. 【转】Boost和loki智能指针
  16. python3 基础语法分享
  17. Android逆向之旅—Hook神器Cydia Substrate使用详解
  18. 工作流调度系统Apache DolphinScheduler介绍和设计原理
  19. VMware虚拟化- vSphere vCenter HA理论与应用
  20. CSDN《原力计划—打卡挑战》为你而来,新升级, 多流量,抓住春季的小尾巴,冲冲冲!

热门文章

  1. python在财务中的应用实训报告-DATATOM | 大数据实训
  2. python入门教程书-清华大学出版社-图书详情-《Python快速入门精讲》
  3. 解决Linux中使用google chrome浏览器出现:ERR_PROXY_CONNECTION_FAILED 代理错误,导致不能够上网
  4. 界面 高炉系统_浅议工业互联网与传统计算机系统的关系
  5. mybatis不使用动态代理查询时设计与实现
  6. Shell中的循环语句for、while、until实例讲解
  7. 8786:方格取数 (多线程dp)
  8. IIS配置不正确可能导致“远程服务器返回错误: (404) 未找到错误一例。
  9. BZOJ 3432: [Usaco2014 Jan]Cross Country Skiing (二分+染色法)
  10. HDU 4565So Easy!2012长沙邀请赛A题(共轭构造+矩阵的快速幂)