1. 程式人生 > >ASP.NET Web API 2 OData v4教程

ASP.NET Web API 2 OData v4教程

數據 選項 readonly void runtime tca end add serve

程序數據庫格式標準化的開源數據協議 為了增強各種網頁應用程序之間的數據兼容性,微軟公司啟動了一項旨在推廣網頁程序數據庫格式標準化的開源數據協議(OData)計劃,於此同時,他們還發 布了一款適用於OData協議的開發工具,以方便網頁程序開發者們使用。 Open Data Protocol (開放數據協議,OData)是用來查詢和更新數據的一種Web協議,其提供了把存在於應用程序中的數據暴露出來的方式。OData運用且構建於很多 Web技術之上,比如HTTP、Atom Publishing Protocol(AtomPub)和JSON,提供了從各種應用程序、服務和存儲庫中訪問信息的能力。OData被用來從各種數據源中暴露和訪問信息, 這些數據源包括但不限於:關系數據庫、文件系統、內容管理系統和傳統Web站點。

創建項目

在VS中創建一個新的Asp.Net Web應用項目,命名為“PersonsService”,如下圖:技術分享圖片

技術分享圖片

安裝Nuet包

技術分享圖片

搜索Microsoft.AspNet.Odata包跟EntityFramework包安裝

技術分享圖片

技術分享圖片

添加Model類

Model類是一個表示應用中的數據實體的對象。

在解決方案資源管理器中的Models文件夾下,創建一個Person類:

namespace PersonsService.Models
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool Gender { get; set; }
        public string UserName { get; set; }
    }
}  

生成數據庫

打開Web.config文件,在configuration元素中添加下面的connectionStrings節點:

  <connectionStrings>
    <add name="PersonsContext" connectionString="Server=.;Database=PersonsDB;Integrated Security=True" providerName="System.Data.SqlClient"/>
  </connectionStrings>

在Models文件夾下添加一個PersonsContext類:

using System.Data.Entity;
namespace PersonsService.Models
{
    public class PersonsContext : DbContext
    {
        public PersonsContext()
    : base("name=PersonsContext")
        {
        }
        public DbSet<Person> Persons { get; set; }
    }
}

 打開NuGet包管理器,程序包管理器控制臺輸入以下命令 "enable-migrations" ,"add-migration","update-database "

技術分享圖片

這個時候打開SQL Server 就可以看到已經創建好的數據庫

技術分享圖片

配置OData終結點

打開App_Start/WebApiConfig.cs文件,配置下面的新代碼

using Microsoft.OData.Edm;
using PersonsService.Models;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
namespace PersonsService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服務
            // Web API 路由
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            //構建路由服務
            config.MapODataServiceRoute(
                routeName: "odata",
                routePrefix: "odata",
                model: GetModel()
                );
        }
        private static IEdmModel GetModel()
        {
            var builder = new ODataConventionModelBuilder();
            var esPerson = builder.EntitySet<Person>("Persons");
            return builder.GetEdmModel();
        }
    }
}

  

上面的代碼做了兩件事:

  • 創建了一個實體數據模型(Entity Data Model【簡稱EDM】)。
  • 添加了一個路由。

EDM是一個抽象的數據模型。EDM用於創建服務元數據文檔。ODataConventionModelBuilder類使用默認的命名規範創建了一個EDM。這種方式需要寫的代碼最少。如果你想更多地控制EDM,那麽你可以使用 ODataModelBuilder類來創建EDM類,這樣做就要顯式添加屬性,鍵和導航屬性。

路由(route)會告訴Web API如何將HTTP請求路由到終結點。調用MapODataServiceRoute 擴展方法可以創建一個OData v4路由。

如果你的應用有了多個OData終結點,那麽要為每個終結點創建一個單獨的路由,給每個路由一個唯一的路由名和前綴(prefix)。

添加OData控制器

控制器是處理HTTP請求的一個類。在OData應用中,應該為每個實體集創建一個單獨的控制器。而在這篇博客中,我們只要為Person實體創建一個控制器就行了。

在Controllers文件夾下添加一個控制器,如下:

技術分享圖片

修改控制器代碼,如下:

using PersonsService.Models;
using System.Linq;
using System.Web.OData;
namespace PersonsService.Controllers
{
    public class PersonsController : ODataController
    {
        private readonly PersonsContext db = new PersonsContext();
        [EnableQuery]
        public IQueryable<Person> Get()
        {
            return db.Persons;
        }
        [EnableQuery]
        public IQueryable<Person> Get([FromODataUri] int key)
        {
            return db.Persons.Where(r=> r.Id==key);
        }
    }
}

  這時我們手動給數據庫添加些數據,

技術分享圖片

好了,現在我們運行項目嘗試請求下

請求http://localhost:3370/odata/Persons

技術分享圖片

現在數據都出來了,試下請求單個Person

http://localhost:3370/odata/Persons(1)

技術分享圖片

一切正常

無參數的Get()方法會返回整個Person表的集合。
Get([FromODataUri] int key)方法會返回指定Id的Person。

[EnableQuery]特性允許客戶端使用查詢選項(如$filter,$sort和$page)修改查詢。

添加一個Post方法來添加Person

        [HttpPost]
        public IHttpActionResult Post(Person person)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            db.Persons.Add(person);
            db.SaveChanges();
            return Created(person);
        }

 使用post請求http://localhost:3370/odata/Persons

技術分享圖片

看下數據庫趙六已經添加進去了,現在添加一個修改方法

OData支持兩種不同語義更新實體,包括PATCH和PUT。

  • PATCH執行一個部分更新,客戶端只識別要更新的屬性。
  • PUT會替換整個實體。

PUT的劣勢在於客戶端必須發送實體的所有屬性,包括沒有改變的值。
OData說明書陳述了PATCH是首選。

        [AcceptVerbs("PATCH", "MERGE")]
        public IHttpActionResult Patch([FromODataUri] int key, Delta<Person> patch)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            Person person = db.Persons.Find(key);
            if (person == null)
            {
                return NotFound();
            }
            patch.Patch(person);
            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                    throw;
            }
            return Updated(person);
        }

 在PATCH中,控制器使用了Delta類型來跟蹤改變。

刪除實體

允許客戶端從數據庫刪除一個Person:

// DELETE: odata/Persons(5)
        public IHttpActionResult Delete([FromODataUri] int key)
        {
            Person person = db.Persons.Find(key);
            if (person == null)
            {
                return NotFound();
            }

            db.Persons.Remove(person);
            db.SaveChanges();

            return StatusCode(HttpStatusCode.NoContent);
        }

  後續會補充下odata配置自定義路由的問題.

Odata 自定義路由

        [EnableQuery, HttpGet]
        [ODataRoute("Products({id})/Default.GetCatAndTown")]
        public IHttpActionResult GetCatAndTown([FromODataUri] int id)
        {
            var list = db.Products.Where(r => r.Id == id);
            return Ok(list);
        }

  當然這個時候我們請求http://localhost:6785//Odata/Products(1)/Default.GetCatAndTown會報錯404,解決方案是添加一個尾部的斜杠到請求的網址

這個時候我們http://localhost:6785//Odata/Products(1)/Default.GetCatAndTown/就會好了,具體原因不詳。或者是修改web.config文件

  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0Custom" path="/odata*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

  

ASP.NET Web API 2 OData v4教程