本文章是由機器翻譯。

資料點

建立 OData 的新選項:Web API

Julie Lerman

下載代碼示例

Microsoft.NET 開發人員已經能夠創建 OData 源以來之前甚至還有 OData 規格。通過使用 WCF 資料服務,您可以通過 Web 使用具象狀態傳輸 (REST) 公開Entity Data Model(EDM)。換句話說,你可以使用消耗通過 HTTP 調用這些服務:獲取、 放、 刪除等。作為框架,用於創建這些服務演變 (和沿途改了幾次),輸出以及演變和最終成為了封裝在 OData 規格 (odata.org)。現在市面上有很大的用戶端 Api 消費 OData — — 從.NET、 PHP、 JavaScript 和許多其他客戶。但直到最近,創建一種服務只簡單方法是使用 WCF 資料服務。

WCF 資料服務是一種只是環繞您的EDM(.edmx 或通過代碼第一次定義一個模型),然後公開該模型用於查詢和更新通過 HTTP 的.NET 技術。因為該調用是 Uri (如 HTTP://mysite.com/mydataservice/­Clients(34)),您甚至可以從 Web 瀏覽器或工具如提琴手查詢。若要創建一個 WCF 資料服務,Visual Studio為建立 WCF 資料服務使用一組 Api 提供的項範本。

現在有另一種方法來創建 OData 源 — — 使用ASP.NETWeb API。在這篇文章我想提供高級別看看一些這兩種方法和你為什麼選擇另一個之間的差異。我也會看看 OData API 不同于創建一個 Web API 的方式創建。

API vs。在高級別資料服務

WCF 資料服務是環繞 ObjectCoNtext 或 DbCoNtext 已經定義了的 System.Data.Services.DataService。服務類聲明時,它是上下文的通用的 dataservice 中的您 (即,dataservice <MyDbCoNtext> 中)。因為它啟動完全鎖住了,你設置存取權限的建構函式中對 DbSets 從您要公開服務的上下文。這是所有你需要做的。Dataservice 中基礎 API 照顧的其餘部分:直接與上下文,以及查詢和更新資料庫中將您的用戶端應用程式的 HTTP 要求的回應的服務進行交互。它也是邏輯的可能要向服務,重寫一些它的查詢或更新中添加一些自訂設置。但大多數情況下,關鍵是讓照顧大多數與上下文交互的 dataservice。

與 Web API,另一方面,您定義上下文的互動回應 HTTP 要求 (放、 獲取和類似)。API 公開的方法和你定義的邏輯的方法。你不一定要與Entity Framework或甚至資料庫交互。你可能在記憶體中物件的用戶端是請求或發送。將存取點不只是會魔術般地創建像他們是與 WCF 資料服務 ; 相反,您可以控制對這些調用的回應中發生的。這是在一個 API 來公開您 OData 選擇服務的決定性因素。如果您想要公開的最簡單的創建、 讀取、 更新、 刪除 (CRUD) 而無需進行大量自訂,然後資料服務將是您的最佳選擇。如果您需要自訂行為的很多,一個 Web API 更有意義。

我像微軟整合最有價值球員Matt米爾納的方式把它放近期舉行聚會:WCF 資料服務是為當您開始使用的資料和模型並只是想要將其公開。Web API 是更好地當您開始使用該 API,並且想要定義它應該公開。

設置標準的 Web API 的舞臺

對於那些與 Web API 的經驗有限,看著我發現它的新 OData 支援之前説明 Web API 基礎知識得到一種感覺,然後看看它們是如何創建一個 Web API 公開 OData。在這裡可以做到 — — 第一次創建一個簡單的 Web API,作為其資料層,使用Entity Framework,然後進行轉換它作為 OData 提供它的結果。

Web API 的一個用途是作為一個標準模型-視圖-控制器 (MVC) 應用程式中,控制器的替代方法,您可以創建它作為ASP.NETMVC 4 專案的一部分。如果你不想要的前端,您可以開始空ASP.NETWeb 應用程式,添加 Web API 控制器。然而,為了新手,我會從開始ASP.NETMVC 4 範本因為,它提供了將吐出一些起始代碼的腳手架。一旦你理解了如何一起去的所有部分,一個空的專案從開始是正確的路要都走。

於是我創建一個新ASP.NETMVC 4 應用程式然後,出現提示時,選擇的空範本 (不 Web API 範本,其目的是為一個更可靠的應用程式,使用的意見,我的目的是矯枉過正)。這將導致在專案中的空資料夾結構 MVC 應用程式模型、 視圖和控制器。圖 1 到 Web API 範本的空範本的結果進行比較。你可以看到一個空的範本會導致結構簡單和我需要做的就是刪除幾個資料夾。


圖 1ASP.NETMVC 4 專案從空範本和 Web API 範本

因為我用一組現有的域類和 DbCoNtext 在單獨的專案中提供的模型,我也不會需要模型資料夾。然後我就會使用Visual Studio模具創建我的第一個控制器,這將是一個要與我 DbCoNtext 交互的 Web API 控制器和我已經從我的 MVC 專案引用的域類。我的模型包含的類為航空公司、 旅客、 航班和一些其他類型的航空公司相關的資料。

因為我用的空範本,我需要添加一些參考資料,以調入 DbCoNtext — — 一對 System.Data.Entity.dll 和一個到 EntityFramework.dll。您可以通過安裝 EntityFramework NuGet 包添加這些引用的兩個。

您可以在創建標準 MVC 控制器相同的方式創建一個新的 Web API 控制器:按右鍵解決方案中的控制器資料夾,選擇添加,然後控制器。正如你可以看到在圖 2,您現在有一個範本用於創建 API 控制器與 EF 讀取和寫入操作。也是一種空 API 控制器。讓我們開始點比較到控制器的 EF 讀/寫操作與我們想要為還將使用Entity Framework的 OData。


圖 2 範本使用預先填充操作創建 API 控制器

如果您已經創建 MVC 控制器之前,您將看到生成的類是相似的但此控制器而不是查看相關的操作方法,如索引、 添加和編輯,一套有一套的 HTTP 操作。

例如,有兩個 Get 方法,如中所示圖 3。第一,Get­航空公司、 有沒有參數和使用 AirlineCoNtext (該範本腳手架已命名為 db) 的實例返回一組航空公司實例中可枚舉的簽名。其他的 GetAirline,一個整數,並使用查找並返回某一特定航空公司。

圖 3 的一些 Web API 控制器方法創建由 MVC 腳手架

public class AirlineController : ApiController
  {
    private AirlineContext db = new AirlineContext2();
    // GET api/Airline
    public IEnumerable<Airline> GetAirlines()
    {
      return db.Airlines.AsEnumerable();
    }
    // GET api/Airline/5
    public Airline GetAirline(int id)
    {
      Airline airline = db.Airlines.Find(id);
      if (airline == null)
      {
        throw new HttpResponseException
          (Request.CreateResponse(HttpStatusCode.NotFound));
      }
      return airline;
    }

該範本添加注釋,以表明你將如何使用這些方法。

後向我 Web API 提供一些配置,我可以查閱它直接在瀏覽器中,在我的應用程式已分配的埠上使用的語法示例:HTTP://localhost:1702/api/Airline。 這是預設的 HTTP GET 調用,因此應用程式執行的 GetAirlines 方法被路由。 Web API 使用內容協商來確定應該如何設置結果集的格式。 我使用 Google Chrome 作為我的預設瀏覽器,觸發要格式化為 XML 的結果的。 來自用戶端的請求控制結果的格式。 互聯網資源管理器中,例如,發送什麼格式它接受,沒有特定的頭資訊,因此 Web API 將預設為返回 JSON。 我的 XML 結果所示圖 4

圖 4 航空公司 WebAPI 回應 GET,作為 XML 在我的瀏覽器中顯示

<ArrayOfAirline xmlns:i=http://www.w3.org/2001/XMLSchema-instance 
  xmlns="http://schemas.datacontract.org/2004/07/DomainClasses">
    <Airline>
      <Id>1</Id>
      <Legs/>
      <ModifiedDate>2013-02-22T00:00:00</ModifiedDate>
      <Name>Vermont Balloon Transporters</Name>
    </Airline>
    <Airline>
      <Id>2</Id>
      <Legs/>
      <ModifiedDate>2013-02-22T00:00:00</ModifiedDate>
      <Name>Olympic Airways</Name>
    </Airline>
    <Airline>
      <Id>3</Id>
      <Legs/>
      <ModifiedDate>2013-02-22T00:00:00</ModifiedDate>
      <Name>Salt Lake Flyer</Name>
    </Airline>
</ArrayOfAirline>

如果以下的 GetAirline 方法的指導,我是將一個整數參數添加到請求 — — HTTP: / / localhost:1702/api/航空公司/3 — — 然後將返回只單一其鍵 (Id) 是等於 3 的航空公司:

<Airline xmlns:i=http://www.w3.org/2001/XMLSchema-instance
  xmlns="http://schemas.datacontract.org/2004/07/DomainClasses">
    <Id>3</Id>
    <Legs/>
    <ModifiedDate>2013-02-22T00:00:00</ModifiedDate>
    <Name>Salt Lake Flyer</Name>
</Airline>

如果要使用互聯網資源管理器中或如提琴手工具哪裡我可以顯式控制到 API 請求,以確保我得到 JSON,將作為 JSON 返回為航空公司與 Id 3 請求的結果:

{"Id":3,
  "Name":"Salt Lake Flyer",
  "Legs":[],
  "ModifiedDate":"2013-03-17T00:00:00"
}

這些回應包含具有元素的每個屬性的航空公司類型的簡單標記法:Id、 雙腿、 ModifiedDate 和名稱。

控制器還包含一個 PutAirline 方法,Web API 將調用一個放的 HTTP 要求的回應。 PutAirline 包含代碼,使用 AirlineCoNtext 來更新一家航空公司。 也是一個用於刪除的 DeleteAirline 方法和插入 PostAirline 方法。 這些不能證明在瀏覽器的 URL,但你可以找到很多-入門內容為 Web API 上 MSDN、 Pluralsight 和其他地方,所以我會移轉換這來輸出其結果按照 OData 規範。

打開您的 Web API 到 OData 供應商

現在,你有一個基本的瞭解,如何可以使用 Web API 來公開資料使用的Entity Framework的讓我們看看特別要從你的資料模型創建 OData 提供程式的 Web API 的使用。 您可以強制您的 Web API 將返回的資料作為 OData 格式化您的控制器變成 OData 控制器 — — 使用ASP.NET和 Web 工具 2012.2 包中可用的類 — —,然後重寫其 OData 特定方法。 與這種新型的控制器,您甚至不需要由範本創建的方法。 事實上,一個更有效率的路徑創建 OData 控制器是選擇空 Web API 腳手架範本而不是創建的 CRUD 操作。

有我需要為這一過渡執行的四個步驟:

  1. 使一種類型的 ODataController 的控制器和執行它的 HTTP 方法。 為此,我將使用一個快捷方式。
  2. 在專案的 WebAPIConfig 檔中定義可用的 EntitySets。
  3. 配置在 WebAPIConfig 中的路由。
  4. 以複數形式表示要對齊與 OData 公約的控制器類的名稱。

創建 ODataController 而是比直接從 ODataController 繼承,我將使用 EntitySetController,從 ODataController 派生,並提供更高級別的支援的虛擬的 CRUD 方法的多。 我用 NuGet 來為包含這兩個控制器類的適當程式集安裝 MicrosoftASP.NETWeb API OData 包。

這裡是課的我,現在從 EntitySetController 繼承和指定的控制器課的為航空公司類型的開始:

public class AirlinesController : EntitySetController<Airline,int>
{
  private AirlineContext db = new AirlineContext();
  public override IQueryable<Airline> Get()
  {
    return db.Airlines;
  }

我過充實的 Get 方法,將返回 db 的重寫。航空公司。 請注意我不要求 ToList 或 AsEnumerable 航空公司 DbSet 上。 Get 方法需要返回航空公司 IQueryable,即哪些 db。航空公司沒有。 這種方式,OData 的消費者可以在這套,然後將執行的資料庫,而不是把所有航空公司拉到記憶體,然後進行查詢來他們定義查詢。

您可以重寫並添加到邏輯的 HTTP 方法是 GET、 POST (用於插入)、 (為更新) 投入、 修補程式 (對於合併更新) 和刪除。 但對於更新你會實際上使用 CreateEntity 的虛擬方法重寫調用的帖子,對於邏輯用投入和 PatchEntity 的邏輯所需的修補程式的 HTTP 調用調用 UpdateEntity 的邏輯。 額外的虛擬方法,可以作為此 OData 提供程式的一部分是:CreateLink、 DeleteLink 和 GetEntityByKey。

在 WCF 資料服務中,您控制通過配置 SetEntitySetAccessRule 所允許每 EntitySet 的 CRUD 操作。 但與 Web API,你只需添加您想要支援,離開了你不想讓消費者能夠獲得的方法的方法。

Api 指定 EntitySets Web API 需要知道哪個 EntitySets 應該是提供給消費者。 這在第一次把我弄糊塗。 預計通過閱讀 AirlineCoNtext 發現這。 但作為我思考更多,我意識到這是類似于使用 WCF 資料服務中的 SetEntitySetAccessRule。 在 WCF 資料服務中,您定義在您公開一組特定的同時允許哪些 CRUD 操作。 但與 Web API,你開始通過修改 WebApiConfig.Register 方法來指定哪些集將是 API 的一部分,然後使用在控制器中的方法公開特定的 CRUD 操作。 指定使用 ODataModelBuilder 的集 — — 類似于 DbCoNtext.ModelBuilder 您可能使用了與代碼第一次。 下面是代碼中的 WebApiConfig 檔,以便讓我的 OData 飼料的暴露航空公司和腿的註冊方法:

ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
                  modelBuilder.EntitySet<Airline>("Airlines");
                  modelBuilder.EntitySet<FlightLeg>("Legs");

定義路由查找 OData 下一步,註冊方法需要一個路由,指向此模型,這樣,當你進入 Web API 呼叫時,它將向您定義的 EntitySets 提供的訪問:

Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute("ODataRoute", "odata", model);

你會看到很多演示使用"odata"的 RoutePrefix 參數,定義你的 API 方法的 URL 首碼。 雖然這是一個很好的標準,您可以命名它,無論你是喜歡。

所以我就會改變它只是為了證明我的觀點:

config.Routes.MapODataRoute("ODataRoute", "oairlinedata", model);

重命名控制器類應用程式範本生成代碼,對於控制器,AirlineController 和 LegController 等使用奇異的命名約定。 然而,OData 的重點是 EntitySets,通常使用複數形式的機構名稱進行命名。 因為我 EntitySets 的確複數,我需要將我的控制器類的名稱更改為 AirlinesController,使與航空公司 EntitySet 對齊。

消費 OData

現在我可以工作與 API 使用熟悉的 OData 查詢語法。 我會首先要求的是什麼可使用請求的清單:HTTP://localhost:1702/oairlinedata/。 所得的結果顯示在 [圖 5] 中。

圖 5。 請求可用資料的清單

http://localhost:1702/oairlinedata/
<service xmlns="http://www.w3.org/2007/app" xmlns:atom=
  "http://www.w3.org/2005/Atom" 
  xml:base="http://localhost:1702/oairlinedata /">
    <workspace>
      <atom:title type="text">Default</atom:title>
      <collection href="Airlines">
        <atom:title type="text">Airlines</atom:title>
      </collection>
      <collection href="Legs">
        <atom:title type="text">Legs</atom:title>
      </collection>
    </workspace>
</service>

調查結果顯示我該服務公開航空公司和雙腿。 下一步,我會問的航空公司的清單作為 OData 與 HTTP://localhost:1702/oairlinedata/Airlines。 OData 可以作為 XML 或 JSON 返回。 Web API 結果的預設值是 JSON 格式:

{
  "odata.metadata":
    "http://localhost:1702/oairlinedata/$metadata#Airlines","value":[
    {
      "Id":1,"Name":"Vermont Balloons","ModifiedDate":"2013-02-26T00:00:00"
    },{
      "Id":2,"Name":"Olympic Airways","ModifiedDate":"2013-02-26T00:00:00"
    },{
      "Id":3,"Name":"Salt Lake Flyer","ModifiedDate":"2013-02-26T00:00:00"
    }
  ]
}

OData URI 的眾多功能之一查詢。 預設情況下,Web API 不會啟用查詢,如,規定了伺服器上的額外負載。 所以你不能與您的 Web API 一起使用這些查詢的功能,直到您將可查詢批註添加到適當的方法。 例如,在這裡我已經添加 Queryable 對 Get 方法:

[Queryable]
public override IQueryable<Airline> Get()
{
  return db.Airlines;
}

現在你可以使用的 $filter、 $inlinecount、 $orderby、 $sort 和 $top 的方法。 這裡是一個查詢使用 OData 篩選方法:

http://localhost:1702/oairlinedata/Airlines?$filter=startswith(Name,'Vermont')

ODataController 允許你要約束的查詢,以便消費者不會導致您的伺服器上的性能問題。 例如,您可以限制在單個回應中返回的記錄的數目。 請參閱 Web API 特定"OData 安全指導"文章在 bit.ly/X0hyv3 更多詳細資訊。

只表面文章

我看只是您可以提供的 Web API OData 支援的查詢功能的一部分。 您還可以使用虛擬方法的 EntitySetController,允許更新到資料庫。 開機自檢,有趣另外付諸表決,並刪除是修補程式,該對話方塊允許您發送更新時只有少量的欄位已更改,而不是發送完整的實體為一個職位明確和有效的請求。 但您的修補程式方法內的邏輯需要來處理一個適當的更新,也就是說,如果你使用的Entity Framework,最有可能從資料庫中檢索當前物件並更新它的新值。 您是如何實現這種邏輯取決於在你要付出代價的線路上推送資料的工作流中的什麼時候知道。 它也是重要的是要注意此版本 (與ASP.NET和 Web 工具 2012.2 包) 支援僅 OData 功能的子集。 這意味著並不是所有的 API 呼叫,你可以把做成的 OData 源將工作與用 Web API 創建 OData 提供程式。 版本資訊,瞭解支援哪些功能的ASP.NET和 Web 工具 2012.2 包清單。

有很多要學習比我可以分享在此列的有限的空間。 我建議在官方 Web API 文檔中的關於 OData 邁克華士信優秀系列 bit.ly/14cfHIm。 您將學習有關建築所有的 CRUD 方法、 使用修補程式,甚至使用批註來限制哪些類型的篩選允許在您 OData Api 和使用關係。 請記住,許多其他的 Web API 功能適用于 OData API,例如,如何使用授權來限制可以訪問哪些操作。 此外,.NET Web 開發和工具博客 (blogs.msdn.com/webdev) Web API 中有詳細的博客張貼內容有關 OData 支援數。

Julie Lerman 是 Microsoft MVP,.NET 的導師和顧問住在佛蒙特州的山裡。 你可以找到她提出關於資料訪問和使用者組和會議,世界各地其他 Microsoft.NET 主題。 在她的博客 thedatafarm.com/blog 是從 O'Reilly 媒體和眾多的線上課程,在 Pluralsight.com 的"程式設計Entity Framework"書籍的作者。 跟著她在 Twitter 上 twitter.com/julielerman

衷心感謝以下技術專家對本文的審閱:喬恩 · 加洛韋 (Microsoft) 和麥克華士信 (Microsoft)
喬恩 · 加洛韋 (Jon.Galloway@microsoft.com) 是一技術傳教士的 Windows Azure 佈道隊,側重于ASP.NETMVC 和ASP.NETWeb API。 他在講話會議和國際 Web 營地從伊斯坦布爾到班加羅爾到布宜諾斯艾利斯。 他是 Wrox 專業ASP.NETMVC 書系列,對報告的合著者,是關於放牧代碼播客共同主辦。
邁克華士信 (mwasson@microsoft.com) 是在微軟的程式師-作家。 許多年來他記錄了 Win32 的多媒體 Api。 他目前正在寫ASP.NET,側重于 Web API。