小分享:我有幾張阿裡雲優惠券,用券購買或者升級阿裡雲相應產品最多可以優惠五折!領券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 在SOA的世界中,最重要的一個概念就是契約( ...
小分享:我有幾張阿裡雲優惠券,用券購買或者升級阿裡雲相應產品最多可以優惠五折!領券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03
在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/shanyou/WebApiOData.zip
參考頁面:http://qingqingquege.cnblogs.com/p/5933752.html