開放資料協定Open Data Protocol(OData)是web的一種資料存取協定,OData通過設定CRUD操作(Create建立。Read讀取。Update更新,Delete删除)提供一種統一的方式來查詢或者操作資料。
ASP.Net Web API同一時候支援該協定v3和v4版本号,你甚至能夠在執行v4的端點(Endpoint)時執行v3的端點(Endpoint)。
本課程展示了怎樣建立OData v4的端點(Endpoint)來提供CRUD操作。
教程裡使用的軟體版本号
-
- Web API 2.2
- OData v4
- Visual Studio 2013 Update 2
- Entity Framework 6
- .NET 4.5
教程版本号
點選Creating an OData v3 Endpoint可跳轉至OData Version 3.
建立Visual Studioproject
打開Visual Studio,在File(檔案)菜單中。選擇New > Project(建立>項目)。
展開 Installed > Templates > Visual C# > Web(已安裝>模闆>Visual C#>Web)。選擇ASP.NET Web Application(ASP.NET Web應用程式)模闆,将project名稱命名為“ProductService”。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0NXYFhGd192UvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1TP3pVdGd1V1Y1RUZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TMwYzMzITN5ADMxATM0EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
在New Project(建立項目)對話框裡選擇Empty(空模闆)。在"Add folders and core references..."(為下面對象加入目錄和核心引用)。擇Web API,然後點選OK(确定)。
選
安裝OData包
在Tools(工具)菜單裡。選擇NuGet Package Manager > Package Manager Console(NuGet程式包管理>程式包管理器控制台)。在程式包管理器控制台視窗裡輸入:
Install-Package Microsoft.AspNet.Odata
該指令将會安裝最新的OData NuGet包。
加入一個Model 類(模型類)
在你的應用程式裡。一個Model(模型)就是一個展現資料實體的對象。
在Solution Explorer(解決方式資料總管)裡,右擊名為Models的目錄,在右鍵菜單裡,選擇Add > Class(加入>類)。
依照慣例。model classes(模型類)會被放入名為Models的目錄裡,隻是在你project裡你并不一定要遵循這種規則。
将該類命名為Product,在Product.cs檔案中,使用下面代碼替換樣本代碼。
namespace ProductService.Models
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
}
Id
屬性是這個實體的鍵。client能夠依據鍵來查詢實體。要查詢并得到
Id
是5的 Product,它的資源路徑便是 /Products(5),在背景資料庫裡
Id
也是主鍵。
啟用實體架構
在本次教程裡,我們将使用Entity Framework (EF) Code First來建立背景資料庫。
Web API OData并不一定須要EF,你能夠使用不論什麼可将資料實體轉換為models(模型)的資料訪問層。
首先,安裝EF的NuGet包。在Tools(工具)菜單裡。選擇NuGet Package Manager > Package Manager Console(NuGet程式包管理>程式包管理器控制台)。
在程式包管理器控制台視窗裡輸入:
Install-Package EntityFramework
打開Web.config檔案,将下面位于configuration 節點内。configSections節點後的部分加入至該檔案裡對應位置。
<configuration>
<configSections>
<!-- ... -->
</configSections>
<span style="background-color: rgb(255, 255, 0);"><!-- Add this: --></span>
<connectionStrings>
<add name="ProductsContext" connectionString="Data Source=(localdb)\v11.0;
Initial Catalog=ProductsContext; Integrated Security=True; MultipleActiveResultSets=True;
AttachDbFilename=|DataDirectory|ProductsContext.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
該設定裡加入了一個連結LocalDB(本地資料庫)的連結字元串。
當你在本地執行此程式時,本地資料庫将被使用。
下一步。在Models目錄裡加入一個名為
ProductsContext
的類。
using System.Data.Entity;
namespace ProductService.Models
{
public class ProductsContext : DbContext
{
public ProductsContext()
: base("name=ProductsContext")
{
}
public DbSet<Product> Products { get; set; }
}
}
在構造函數裡, "name=ProductsContext"給出了連接配接字元串的名稱。
配置OData Endpoint
打開檔案App_Start/WebApiConfig.cs,加入下面引用語句。
using ProductService.Models;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
然後加入下面代碼至 Register方法中:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code:
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
}
}
這段代碼做了兩件事情
- 建立Entity Data Model(EDM實體資料模型)
- 添加一個Route(路由)
EDM是資料的抽象模型,EDM被用來建立服務的中繼資料檔案。
ODataConventionModelBuilder使用預設的命名規則建立EDM。這樣的方法須要少量的代碼。假設你想很多其它支配EDM的話,你能夠使用通過明白地加入屬性、鍵和導航屬性來建立EDM。
Route告訴了Web API應該如何路由Http請求至Endpoint(端點)中。你能夠通過調用MapODataServiceRoute 擴充的方法來建立OData v4 route(路由)。
假設你的程式裡有多個OData Endpoint,你須要為它們分别建立一個route,且給它們不同的Route路由名稱和字首。
加入OData控制器
控制器是處理Http請求的類。你能夠為每個OData服務的實體建立不同的控制器。
在本教程裡,你将為
Product
實體建立一個控制器。
在Solution Explorer(解決方式資料總管)裡,右擊名為Controllers 的目錄,在右鍵菜單裡,選擇Add > Class(加入>類)。将其命名為ProductsController。
在OData v3教程裡我們使用了Add Controller對話框,但眼下還沒有OData v4版的。
在ProductsController.cs中用下面代碼替換樣本代碼。
using ProductService.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
namespace ProductService.Controllers
{
public class ProductsController : ODataController
{
ProductsContext db = new ProductsContext();
private bool ProductExists(int key)
{
return db.Products.Any(p => p.Id == key);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
控制器使用ProductsContext類通過EF來訪問資料庫。注意,該控制器重寫了Dispose 方法來釋放ProductsContext。
這是控制的開始。下一步,我們将為全部的CRUD操作加入方法。
Querying the Entity Set 查詢實體集
加入下面代碼至ProductsController。
[EnableQuery]
public IQueryable<Product> Get()
{
return db.Products;
}
[EnableQuery]
public SingleResult<Product> Get([FromODataUri] int key)
{
IQueryable<Product> result = db.Products.Where(p => p.Id == key);
return SingleResult.Create(result);
}
當中一個沒有參數的
Get
方法傳回
Product
的實體集合。而有一個參數的
Get
方法則是通過 Product的鍵來查找對應的 Product(在這樣的情況下。鍵就是 Id屬性)。
[EnableQuery]标簽通過使用查詢設定$filter, $sort, $page 來改動查詢。具體資訊請點選Supporting OData Query Options。
Adding an Entity to the Entity Set 加入實體至實體集
為了使client能夠加入新
Product
至資料庫中,我們加入例如以下方法至ProductsController。
public async Task<IHttpActionResult> Post(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return Created(product);
}
Updating an Entity 更新實體
OData支援兩種不同的文法來更新實體。PATCH 和PUT。
- PATCH運作部分更新。client僅僅需指定須要更新的屬性。
- PUT 替換整個實體。
PUT 的不利之處是client必須發送實體全部屬性的值,包含那些沒有改變的值。OData 規範書推薦使用PATCH。
無論如何。下面是PATCH和PUT 方法的代碼:
public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var entity = await db.Products.FindAsync(key);
if (entity == null)
{
return NotFound();
}
product.Patch(entity);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(entity);
}
public async Task<IHttpActionResult> Put([FromODataUri] int key, Product update)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (key != update.Id)
{
return BadRequest();
}
db.Entry(update).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(update);
}
在 PATCH情況下,控制器使用 Delta<T>來跟蹤實體的改變。
Deleting an Entity 删除實體
為了能讓client從資料庫中删除實體,我們能夠在ProductsController中加入下面方法。
public async Task<IHttpActionResult> Delete([FromODataUri] int key)
{
var product = await db.Products.FindAsync(key);
if (product == null)
{
return NotFound();
}
db.Products.Remove(product);
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
原文位址:http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint