文章出處

問題

Web API 怎么支持通用的 OData 系統查詢項,例如 $select 或 $filter。

 

解決方案

為了在 Web API 中啟用查詢項,我們需要在 Action 上使用 EnableQueryAttribute。

如果 Action 沒有返回集合,而是返回單個對象的實例,調用端仍然可以使用 $expand 和 $select 兩個查詢語句,要達到這個目的,我們必須將返回對象包裝在 SingleResult<T> 中。集合和單個對象實例作為返回值的例子如訂單 12-7 所示

清單 12-7. 在兩個路由上啟用查詢語句

 1     public class PlayersController : ODataController
 2 
 3     {
 4 
 5         private readonly PlayersContext playersDbContext = new PlayersContext();
 6 
 7         [EnableQuery]
 8 
 9         public IQueryable<Player> GetAllPlayers()
10 
11         {
12 
13             Return playersDbContext;
14 
15         }
16 
17         [EnableQuery]
18 
19         public SingleResult<Player> GetSinglePlayers(int key)
20 
21         {
22 
23             return SingleResult.Create(playersDbContext.Where(x => x.Id == key).AsQueryable());
24 
25         }
26 
27     }

 

工作原理

OData 查詢選項是被定義在 OData 規范中,如,查詢字符串的參數控制的是返回資源的數量和順序。ASP.NET Web API 幾乎支持所有的標準查詢項:

  • $expand:允許響應給客戶端的信息包含關聯資源(導航屬性)
  • $select:限制返回的屬性
  • $filter:過濾 Api 暴露出來的資源
  • $count:獲取集合中實體的總數
  • $orderby:指定集合的排序 key
  • $skip:獲取集合跳過的數量
  • $top:限制集合返回集合的數量
  • $format:請求特定的響應格式

唯一不支持的是 $search 查詢參數。

 

小提示 可以查看 OData 4.0 支持的完整的文檔地址:http://docs.oasis-open.org/OData/new-in-OData/v4.0/cn01/new-in-OData-v4.0-cn01.html

查詢項是在 ASP.NET Web API 中被 ODataQueryOption 類所描述的。EnableQueryAttribute 的工作方式實際是非常簡單的。因為他是 Action 的 Filter,在 OnActionExecuted 方法中會獲取 Action 的響應,并轉換 HttpContent 為ObjectContent<T>。然后根據 HttpRequest 基于客戶端的參數構造 ODataQueryOptions 實例,并返回相應的響應給客戶端。如果響應是集合的話,可以響應客戶端所有的查詢項。如果響應不是集合,就會通過 ObjectContent 包裝成 SingleResult<T>。這些時候,$expand 和 $select 都是可用的。

不使用 EnableQueryAttribute,也可以使用 ODataQueryOptions,他是可以接受 Action 的參數的。這種方式是通過自定義 HttpParameterBinding 類型的 ODataQueryParameterBinding 來支持的。我們也可以使用 ODataQueryOptions 實例中的信息手動執行相關查詢。

在 Web API 中我們不需要完全掌握 OData 就可以體會到查詢項給我們帶來的便利。就算不是基于 ODataCotrollers,只要 Action 上使用了 EnableQueryAttribute 屬性標簽,我們還是可以在 Web API 上使用一些基礎查詢項,例如,$top,$skip,$select。

 

代碼演示

在 Controller 的 Action 上使用 EnableQueryAttribute,這樣的請求就可以使用 OData 查詢項,如清單 12-7

  • Host/Plays(1)$select=Name,Team:使用 Player 實體的 Id 進行過濾,僅僅返回 Name 和 Team 兩個屬性。這個例子的響應,如清單 12-8.

 

清單 12-8. 從 OData 的 Web API 查詢響應例子

{
  "@OData.context":"http://localhost:43539/OData/$metadata#Players(Name,Team)/$entity","Name":"Name1","Team":"Team"
} 
  • Host/Players?skip=1&$top=2:忽略集合中第一個實體,然后再剩下的實體中獲取兩個返回(可以理解為分頁的第二頁數據,每頁大小是 2)。具體響應,如清單 12-9 所示。

清單 12-9. 從 OData 的 Web API 查詢響應例子

{
  "@OData.context":"http://localhost:43539/OData/$metadata#Players","value":[
    {
      "Id":1,"Name":"Name1","Team":"Team"
    },{
      "Id":2,"Name":"Name11","Team":"Team"
    }
  ]
}
  • Host/Players?$format=application/json;OData.metadata=full&$filter=Team%20eq%20%27Team2%27:請求條件你為 Team 屬性值為 Whales,以 json 格式返回 ,包含 OData 元數據的所有信息,包含類型和導航鏈接。具體響應結果,如清單 12-10 所示
{
  "@OData.context":"http://localhost:43539/OData/$metadata#Players","value":[
    {
      "@OData.type":"#BoiledCode.WebApi.Recipe.ODataDemo.Models.Player","@OData.id":"http://localhost:43539/OData/Players(3)","@OData.editLink":"http://localhost:43539/OData/Players(3)","Id":3,"Name":"Name2","Team":"Team2"
    },{
      "@OData.type":"#BoiledCode.WebApi.Recipe.ODataDemo.Models.Player","@OData.id":"http://localhost:43539/OData/Players(4)","@OData.editLink":"http://localhost:43539/OData/Players(4)","Id":4,"Name":"Name21","Team":"Team2"
    }
  ]
}

 

就像上面提到的,我們可以通過在 Action 方法中使用 ODataQueryOptions 參數,來手動的實現詢項。ODataQueryParameterBinding 會幫我完成將對象傳入到 Action 的操作,這樣我們就可以 Action 內部提取 OData 相關的查詢項了。 

清單 12-11. 在 Action 中使用 ODataQueryOptions

 1         public IQueryable<Player> GetAllPlayers(ODataQueryOptions queryOptions)
 2 
 3         {
 4 
 5             // 客戶端傳入的 top 和 skip
 6 
 7             var filtered = db.Players.Skip(queryOptions.Skip.Value);
 8 
 9             if (queryOptions.Top.Value > 0)
10 
11             {
12 
13                 filtered = filtered.Take(queryOptions.Top.Value);
14 
15             }
16 
17             return filtered.AsQueryable();
18 
19         }

 

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()