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();
        }
    }


  


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值