仍是看OData官網的簡單說明:web
An open protocol to allow the creation and consumption of queryable and interoperable RESTful APIs in a simple and standard way.sql
這是一個開放的數據查詢和服務協議,目前已經有衆多廠商和平臺支持,已經造成了完整的生態鏈,這應該是將來數據查詢的標準,參見官網說明。api
OData的意義還在於,它可以大大簡小SOA架構裏面服務的粒度,只須要提供一個OData數據源,而查詢工做交給客戶端去作便可,這將大大減小服務端服務方法定義的數量。瀏覽器
OData的版本如今已是V4了,以前的不少類庫都是基於V1-V3版本的。如今的V4版本已經很完善了,並且成爲了工業標準,因此如今能夠放心的在項目中使用了。架構
OData 的前身是WCF Data Service,後來演變成跨平臺的數據查詢協議,如今,除了WCF支持OData,ASP.NET WebAPI 已經內置支持OData了,這將得到一種輕量級的,Rest架構的OData訪問方案,本文將講解如何在VS 2013上搭建一個OData 服務和客戶端程序。app
在閱讀本文以前,首先建議你參考下面的OData 學習資源,本文也是根據這裏的資源整理而成,之因此要從新整理一次,是由於原文說的並不清楚,給出的示例程序有些小小的問題,並且國內有關OData的文章介紹很是少。框架
http://www.odata.org/blog/how-to-use-web-api-odata-to-build-an-odata-v4-service-without-entity-framework/
http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint
http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-client-appasp.net
本文的實例程序相關代碼請在此下載。dom
新建一個ASP.NET WebAPI 項目,名字是 ODataWebApplication ,以下圖:ide
注意選擇一個空項目,併購選WebAPI,單擊肯定。
打開VS2013的程序包管理器控制檯,在下面輸入 Install-Package Microsoft.AspNet.OData 命令,以下圖:
這裏會添加不少附屬的程序集文件,下面是一個詳細的清單列表,若是你的符合下面的內容,就表示安裝成功了:
鍵入「get-help NuGet」以查看全部可用的 NuGet 命令。 PM> Install-Package Microsoft.AspNet.OData 正在嘗試解析依賴項「Microsoft.AspNet.WebApi.Client (≥ 5.2.2)」。 正在嘗試解析依賴項「Newtonsoft.Json (≥ 6.0.4)」。 正在嘗試解析依賴項「Microsoft.AspNet.WebApi.Core (≥ 5.2.2 && < 5.3.0)」。 正在嘗試解析依賴項「Microsoft.OData.Core (≥ 6.10.0 && < 7.0.0)」。 正在嘗試解析依賴項「Microsoft.Spatial (= 6.10.0)」。 正在嘗試解析依賴項「Microsoft.OData.Edm (= 6.10.0)」。 正在安裝「Newtonsoft.Json 6.0.8」。 已成功安裝「Newtonsoft.Json 6.0.8」。 正在安裝「Microsoft.AspNet.WebApi.Client 5.2.3」。 您正在從 Microsoft 下載 Microsoft.AspNet.WebApi.Client,有關此程序包的許可協議在 http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.AspNet.WebApi.Client 5.2.3」。 正在安裝「Microsoft.AspNet.WebApi.Core 5.2.3」。 您正在從 Microsoft 下載 Microsoft.AspNet.WebApi.Core,有關此程序包的許可協議在 http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.AspNet.WebApi.Core 5.2.3」。 正在安裝「Microsoft.Spatial 6.10.0」。 您正在從 Microsoft Corporation 下載 Microsoft.Spatial,有關此程序包的許可協議在 http://go.microsoft.com/?linkid=9809688 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.Spatial 6.10.0」。 正在安裝「Microsoft.OData.Edm 6.10.0」。 您正在從 Microsoft Corporation 下載 Microsoft.OData.Edm,有關此程序包的許可協議在 http://go.microsoft.com/?linkid=9809688 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.OData.Edm 6.10.0」。 正在安裝「Microsoft.OData.Core 6.10.0」。 您正在從 Microsoft Corporation 下載 Microsoft.OData.Core,有關此程序包的許可協議在 http://go.microsoft.com/?linkid=9809688 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.OData.Core 6.10.0」。 正在安裝「Microsoft.AspNet.OData 5.5.0」。 您正在從 Microsoft 下載 Microsoft.AspNet.OData,有關此程序包的許可協議在 http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.AspNet.OData 5.5.0」。 正在從 ODataWebApplication 刪除「Microsoft.AspNet.WebApi.Client.zh-Hans 5.0.0」。 已成功將「Microsoft.AspNet.WebApi.Client.zh-Hans 5.0.0」從 ODataWebApplication 中刪除。 正在從 ODataWebApplication 刪除「Microsoft.AspNet.WebApi.Core.zh-Hans 5.0.0」。 已成功將「Microsoft.AspNet.WebApi.Core.zh-Hans 5.0.0」從 ODataWebApplication 中刪除。 正在從 ODataWebApplication 刪除「Microsoft.AspNet.WebApi.Client 5.0.0」。 已成功將「Microsoft.AspNet.WebApi.Client 5.0.0」從 ODataWebApplication 中刪除。 正在從 ODataWebApplication 刪除「Newtonsoft.Json 5.0.6」。 已成功將「Newtonsoft.Json 5.0.6」從 ODataWebApplication 中刪除。 正在將「Newtonsoft.Json 6.0.8」添加到 ODataWebApplication。 已成功將「Newtonsoft.Json 6.0.8」添加到 ODataWebApplication。 正在將「Microsoft.AspNet.WebApi.Client 5.2.3」添加到 ODataWebApplication。 已成功將「Microsoft.AspNet.WebApi.Client 5.2.3」添加到 ODataWebApplication。 正在從 ODataWebApplication 刪除「Microsoft.AspNet.WebApi.Core 5.0.0」。 已成功將「Microsoft.AspNet.WebApi.Core 5.0.0」從 ODataWebApplication 中刪除。 正在將「Microsoft.AspNet.WebApi.Core 5.2.3」添加到 ODataWebApplication。 已成功將「Microsoft.AspNet.WebApi.Core 5.2.3」添加到 ODataWebApplication。 正在將「Microsoft.Spatial 6.10.0」添加到 ODataWebApplication。 已成功將「Microsoft.Spatial 6.10.0」添加到 ODataWebApplication。 正在將「Microsoft.OData.Edm 6.10.0」添加到 ODataWebApplication。 已成功將「Microsoft.OData.Edm 6.10.0」添加到 ODataWebApplication。 正在將「Microsoft.OData.Core 6.10.0」添加到 ODataWebApplication。 已成功將「Microsoft.OData.Core 6.10.0」添加到 ODataWebApplication。 正在將「Microsoft.AspNet.OData 5.5.0」添加到 ODataWebApplication。 已成功將「Microsoft.AspNet.OData 5.5.0」添加到 ODataWebApplication。 正在將「Microsoft.AspNet.WebApi.Client.zh-Hans 5.2.3」添加到 ODataWebApplication。 正在安裝「Microsoft.AspNet.WebApi.Client.zh-Hans 5.2.3」。 您正在從 Microsoft 下載 Microsoft.AspNet.WebApi.Client.zh-Hans,有關此程序包的許可協議在 http://www.microsoft.com/web/webpi/eula/net_library_eula_CHS.htm 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.AspNet.WebApi.Client.zh-Hans 5.2.3」。 已成功將「Microsoft.AspNet.WebApi.Client.zh-Hans 5.2.3」添加到 ODataWebApplication。 正在將「Microsoft.AspNet.WebApi.Core.zh-Hans 5.2.3」添加到 ODataWebApplication。 正在安裝「Microsoft.AspNet.WebApi.Core.zh-Hans 5.2.3」。 您正在從 Microsoft 下載 Microsoft.AspNet.WebApi.Core.zh-Hans,有關此程序包的許可協議在 http://www.microsoft.com/web/webpi/eula/net_library_eula_CHS.htm 上提供。請檢查此程序包是否有其餘依賴項,這些依賴項可能帶有各自的許可協議。您若使用程序包及依賴項,即構成您接受其許可協議。若是您不接受這些許可協議,請從您的設備中刪除相關組件。 已成功安裝「Microsoft.AspNet.WebApi.Core.zh-Hans 5.2.3」。 已成功將「Microsoft.AspNet.WebApi.Core.zh-Hans 5.2.3」添加到 ODataWebApplication。 正在卸載「Microsoft.AspNet.WebApi.Client.zh-Hans 5.0.0」。 已成功卸載「Microsoft.AspNet.WebApi.Client.zh-Hans 5.0.0」。 正在卸載「Microsoft.AspNet.WebApi.Core.zh-Hans 5.0.0」。 已成功卸載「Microsoft.AspNet.WebApi.Core.zh-Hans 5.0.0」。 正在卸載「Microsoft.AspNet.WebApi.Client 5.0.0」。 已成功卸載「Microsoft.AspNet.WebApi.Client 5.0.0」。 正在卸載「Newtonsoft.Json 5.0.6」。 已成功卸載「Newtonsoft.Json 5.0.6」。 正在卸載「Microsoft.AspNet.WebApi.Core 5.0.0」。 已成功卸載「Microsoft.AspNet.WebApi.Core 5.0.0」。 PM>
按照 http://www.odata.org/blog/how-to-use-web-api-odata-to-build-an-odata-v4-service-without-entity-framework/ 這個連接內容的文章,添加Model和控制器,具體過程請參考原文。在本篇文章的實例中,爲了更好的重用Model,我將它放到了一個獨立的Demo.Models 項目中。
注意,添加控制器的時候選擇空的 WebAPI 控制器,不要選擇帶OData 的。
下面是添加完整後的項目目錄結構:
馬上運行這個項目,發現報下面的錯誤:
未能加載文件或程序集「System.Web.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35」或它的某一個依賴項。找到的程序集清單定義與程序集引用不匹配。 (異常來自 HRESULT:0x80131040)
此時須要在Web.config 文件中加入下面的配置內容:
<system.web> <compilation debug="true" targetFramework="4.5"/> <httpRuntime targetFramework="4.5"/> </system.web> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.Http" publicKeyToken="31BF3856AD364E35" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31BF3856AD364E35" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0"/> </dependentAssembly> </assemblyBinding> </runtime>
也能夠在編譯項目的時候,注意查看「輸出窗口」,單擊「警告」的文字內容,會有下面的提示詢問,回答肯定便可自動爲你添加上面的內容:
再次運行,程序不報錯了,用谷歌瀏覽器來打開本程序,出現了下面的內容,就表示ASP.NET WebAPI OData V4 已經成功了:
{ "@odata.context":"http://localhost:20491/$metadata#People","value":[ { "ID":"001","Name":"Angel","Description":null },{ "ID":"002","Name":"Clyde","Description":"Contrary to popular belief, Lorem Ipsum is not simply random text." },{ "ID":"003","Name":"Elaine","Description":"It has roots in a piece of classical Latin literature from 45 BC, making Lorems over 2000 years old." } ] }
按照下面連接文章的內容,新建一個控制檯程序:
按照上面連接文章的內容,添加此工具,以下圖:
下載好該工具後讓你安裝運行,最後會讓你重啓動VS。
從新啓動後,若是看到下面的內容,表示該工具安裝成功了。
該工具運行後,會在項目下面添加一個OData Client T4 文件,添加後,運行該項目,會報下面的錯誤:
錯誤 1 正在運行轉換: System.ArgumentException: The value "" is not a valid MetadataDocumentUri because is it not a valid absolute Uri. The MetadataDocumentUri must be set to an absolute Uri referencing the $metadata endpoint of an OData service. 在 Microsoft.VisualStudio.TextTemplating0CFD4DFE54AE767D51F4D19A4964CA0B33E6E87CF53FFF790646D6E3F14916C4544A62E4C781ABB55BC19EE5225FDBA7E28D9767E56040F8F9A9EF5278D6B7CA.GeneratedTextTransformation.set_MetadataDocumentUri(String value) 位置 c:\Users\dth\Documents\Visual Studio 2013\Projects\ODataWebApplication\Demo.ConsoleClient\ODataClient1.ttinclude:行號 125 在 Microsoft.VisualStudio.TextTemplating0CFD4DFE54AE767D51F4D19A4964CA0B33E6E87CF53FFF790646D6E3F14916C4544A62E4C781ABB55BC19EE5225FDBA7E28D9767E56040F8F9A9EF5278D6B7CA.GeneratedTextTransformation.ApplyParametersFromConfigurationClass() 位置 c:\Users\dth\Documents\Visual Studio 2013\Projects\ODataWebApplication\Demo.ConsoleClient\ODataClient1.ttinclude:行號 313 在 Microsoft.VisualStudio.TextTemplating0CFD4DFE54AE767D51F4D19A4964CA0B33E6E87CF53FFF790646D6E3F14916C4544A62E4C781ABB55BC19EE5225FDBA7E28D9767E56040F8F9A9EF5278D6B7CA.GeneratedTextTransformation.TransformText() 位置 c:\Users\dth\Documents\Visual Studio 2013\Projects\ODataWebApplication\Demo.ConsoleClient\ODataClient1.ttinclude:行號 58 c:\Users\dth\Documents\Visual Studio 2013\Projects\ODataWebApplication\Demo.ConsoleClient\ODataClient1.ttinclude 125 1 Demo.ConsoleClient
根據錯誤信息,找到T4文件錯誤的位置,將前面的OData WebAPI項目的地址,寫在文件裏面,以下所示:
// The URI of the metadata document. The value must be set to a valid service document URI or a local file path // eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx" // ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of // MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail. public const string MetadataDocumentUri = "http://localhost:20491/";
此時再次運行該T4文件,咱們發現OData Client 代理類文件生成了,內容不少,這裏就不貼了。
添加下面的代碼,調用OData Client 代理類並運行:
class Program { static void Main(string[] args) { // TODO: Replace with your local URI. string serviceUri = "http://localhost:20491/"; var container = new DefaultContainer(new Uri(serviceUri)); foreach (var p in container.People) { Console.WriteLine("{0} {1} {2}", p.ID, p.Name, p.Description); } Console.Read(); } }
若是看到下面的運行結果,表示OData Client 程序成功了:
至此,OData WebAPI Serivce & Client 的工做就所有完成了。
通過前面的過程咱們看到,依託於OData 客戶端工具生成OData 代理類的過程仍是比較麻煩的,固然好處也有,但缺點就是沒有手工操控的那麼靈活自由。
仔細研究下前面的代理類,咱們發現這裏關鍵依賴於 Microsoft.OData.Client 程序集的DataServiceContext 對象,將代理類進行抽取封裝就能夠完成咱們手工的代理類了。
建立一個類庫項目,新建一個 ODataV4ContextBase.cs 文件,
接着爲該項目添加Nuget 依賴的包:
Install-Package Microsoft.OData.Client
而後在項目下增長了一個文件 packages.config,裏面有以下內容:
<?xml version="1.0" encoding="utf-8"?> <packages> <package id="Microsoft.OData.Client" version="6.11.0" targetFramework="net40" /> <package id="Microsoft.OData.Core" version="6.11.0" targetFramework="net40" /> <package id="Microsoft.OData.Edm" version="6.11.0" targetFramework="net40" /> <package id="Microsoft.Spatial" version="6.11.0" targetFramework="net40" /> </packages>
而後,編寫ODataV4ContextBase 類的具體內容:
using Microsoft.OData.Client; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PWMIS.OData.Client { /// <summary> /// OData V4 Version ASP.NET WebAPI OData RestFull Client Context /// <remarks>v1.0 2015.4.1 http://www.pwmis.com/sqlmap </remarks> /// </summary> public class ODataV4ContextBase : DataServiceContext { /// <summary> /// V4 OData Init /// </summary> /// <param name="serviceRoot">V4 OData ASP.NET WebAPI url base</param> public ODataV4ContextBase(string serviceRoot) : base(new System.Uri( serviceRoot), ODataProtocolVersion.V4) { if (!serviceRoot.EndsWith("/")) serviceRoot = serviceRoot + "/"; GeneratedEdmModel gem = new GeneratedEdmModel(serviceRoot); this.Format.LoadServiceModel = gem.GetEdmModel; this.Format.UseJson(); } public IQueryable<T> CreateNewQuery<T>(string name) where T : class { return base.CreateQuery<T>(name); } class GeneratedEdmModel { private string ServiceRootUrl; public GeneratedEdmModel(string serviceRootUrl) { this.ServiceRootUrl = serviceRootUrl; } public Microsoft.OData.Edm.IEdmModel GetEdmModel() { string metadataUrl = ServiceRootUrl + "$metadata"; return LoadModelFromUrl(metadataUrl); } private Microsoft.OData.Edm.IEdmModel LoadModelFromUrl(string metadataUrl) { System.Xml.XmlReader reader = CreateXmlReaderFromUrl(metadataUrl); try { return Microsoft.OData.Edm.Csdl.EdmxReader.Parse(reader); } finally { ((System.IDisposable)(reader)).Dispose(); } } private static System.Xml.XmlReader CreateXmlReaderFromUrl(string inputUri) { return System.Xml.XmlReader.Create(inputUri); } } } }
在解決方案裏面添加一個WinForm項目,在項目裏面添加一個ODataContainer.cs 文件,內容以下:
class ODataContainer : PWMIS.OData.Client.ODataV4ContextBase { public ODataContainer(string serviceRoot):base(serviceRoot) { } public IQueryable<Person> People { get { return base.CreateNewQuery<Person>("People"); } } }
很是的簡單,這裏只是添加了一個屬性 People。
而後,在窗體代碼中調用:
private void button1_Click(object sender, EventArgs e) { string serviceUri = "http://localhost:20491/"; var container = new ODataContainer(serviceUri); var query = container.People.Where(p => p.Description!=null); this.dataGridView1.DataSource = query.ToList(); }
最後運行該程序,出現下面的界面,就表示成功了:
至此,一個不依賴於EF的全內存的OData 應用程序就徹底作好了,更多OData的研究,請你們一塊兒來作吧。
感謝支持 PDF.NET SOD框架,相關代碼請在此下載。
注:本文說的 ODataV4ContextBase OData客戶端基類程序已經集成到了PDF.NET框架中,在上面的下載裏面便可看到。