VS2015 使用ODataV4創建Web Api和OData客戶端

OData - Open Data Protocol,是一個設計和使用RESTful API的標準。REST本身只是一個構建web服務的思想和理念,其沒有規定一個統一的標準來限制開發人員該如何設計RESTful API。其實我們實際開發中的確也沒有遵循某個統一的標準去設計WebAPI。因爲大多數場景下,遵循一個統一的標準並不是必要的。但在某些場景下,有這樣一個標準卻能帶來很大的好處。

OData的理想是, 無論哪個組織構建的RESTful API,只要其符合OData標準。其他組織就可以按照OData標準中定義的方式去使用這個API獲取/修改資源。這個可以類比SQL標準之於RDBMS關係。無論什麼關係型數據庫,如果其聲稱支持SQL標準,任何人就可以使用標準SQL查詢語句來查詢數據。

標準化的另一個好處:可以將Odata協議實現到一個通用的類庫中,通過這個類庫去創建和訪問RESTful API可以減少開發人員的工作量。

一、新建一個空的WebApi項目


、添加包Microsoft.AspNet.OData包

1、工具菜單--NuGet包管理器--程序包管理器控制檯:

2、輸入Install-Package Microsoft.AspNet.OData 命令


三、添加EntityFramework(如何已經有數據則可以使用自己的數據源,直接跳過)

1、輸入Install-Package EntityFramework 命令

2、創建一個實體對象

設置數據庫連接

public class Product
    {
        [Key]
        public int ID { get; set; }

        public String Name { get; set; }

        // [IgnoreDataMember] 屬性表示在EDM中不可見
        [IgnoreDataMember]
        public string Category { get; set; }
    }

三、配置OData終結點

1、打開WebApiConfig配置EDM

 private static IEdmModel GenerateEdmModel()
        {
            var builder = new ODataConventionModelBuilder
            {
                Namespace = "OdataModel",
                ContainerName = "DefaultContainer",
            };
            builder.EntitySet<Product>("Products");
            
            return builder.GetEdmModel();
        }

2、添加路由並設置查詢參數

public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服務
            config.MapODataServiceRoute("ProductOData", null, GenerateEdmModel());

            //設置查詢參數方式一
            //config.Select().OrderBy().Filter().Expand().MaxTop(100).Count();

            //設置查詢參數方式二
            DefaultQuerySettings query = new DefaultQuerySettings()
            {
                EnableCount = true,
                EnableExpand = true,
                EnableFilter = true,
                EnableOrderBy = true,
                EnableSelect = true,
                MaxTop = 100
            };
            config.SetDefaultQuerySettings(query);

        }

四、添加OData控制器



public class ODataAPIContext : DbContext
    {
        public ODataAPIContext() : base("ODataDB")
        { }

        public DbSet<Product> Products { get; set; }

        static ODataAPIContext()
        {
            //關閉數據庫初始化操作
            Database.SetInitializer<ODataAPIContext>(null);
        }
}

數據庫連接


public class ProductsController : ODataController
    {
        private ODataAPIContext db = new ODataAPIContext();

        // GET Products
        //[Queryable]
        [EnableQuery]
        public IQueryable<Product> GetProducts()
        {
            return db.Products;
        }

        // GET Products(5)
        //[Queryable]
        [EnableQuery]
        public SingleResult<Product> GetProduct([FromODataUri] int key)
        {
            return SingleResult.Create(db.Products.Where(product => product.ID == key));
        }

        /// <summary>
        /// 更新、 修改
        /// </summary>
        /// <param name="key"></param>
        /// <param name="product"></param>
        /// <returns></returns>
        // PUT Products(5)
        public async Task<IHttpActionResult> Put([FromODataUri] int key, Product product)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (key != product.ID)
            {
                return BadRequest();
            }

            db.Entry(product).State = EntityState.Modified;

            try
            {
                await db.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ProductExists(key))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return Updated(product);
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="product"></param>
        /// <returns></returns>
        // POST Products
        public async Task<IHttpActionResult> Post(Product product)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            db.Products.Add(product);
            await db.SaveChangesAsync();

            return Created(product);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="patch"></param>
        /// <returns></returns>
        // PATCH Products(5)
        [AcceptVerbs("PATCH", "MERGE")]
        public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> patch)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            Product product = await db.Products.FindAsync(key);
            if (product == null)
            {
                return NotFound();
            }

            patch.Patch(product);

            try
            {
                await db.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ProductExists(key))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return Updated(product);
        }

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        // DELETE Products(5)
        public async Task<IHttpActionResult> Delete([FromODataUri] int key)
        {
            Product product = await db.Products.FindAsync(key);
            if (product == null)
            {
                return NotFound();
            }

            db.Products.Remove(product);
            await db.SaveChangesAsync();

            return StatusCode(HttpStatusCode.NoContent);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }

        private bool ProductExists(int key)
        {
            return db.Products.Count(e => e.ID == key) > 0;
        }
    }

運行查看


2查看$metadata



3、查看集合



五、添加OData客戶端

1、工具--擴展和更新--安裝“OData v4 Client Code Generator



2、添加控制檯程序


3、添加新建項



 

4、ODataClient.tt文件中修改MetadataDocumentUri路徑


5、保存或者在文件上面右擊運行自定義工具,生成相應文件




6、執行

class Program
    {
        static void Main(string[] args)
        {
            const string serviceUri = "http://localhost:57244/";
             var container = new DefaultContainer(new Uri(serviceUri));
            foreach (var p in container.Products)
            {
                Console.WriteLine("{0} {1}", p.ID, p.Name);
            }
            Console.Read();
        }
    }


  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章