ASP.NET Web Api OData

ASP.NET Web API 2 Odata 基本使用

OData(开放数据协议)是一种ISO / IEC批准,OASIS标准定义的一组最佳实践用于构建和消费RESTful API中。OData 可帮助您在构建 RESTful API 的同时专注于业务逻辑,而无需担心定义请求和响应标头、状态代码、HTTP 方法、URL 约定、媒体类型、有效负载格式、查询选项等的各种方法。 OData 还提供跟踪更改、定义可重用过程的功能/操作以及发送异步/批处理请求的指南。
OData RESTful API 易于使用。OData 元数据是 API 数据模型的机器可读描述,支持创建强大的通用客户端代理和工具。

一、网址组件

URL 表示单个资源、资源集合或操作,客户端使用标准的 GET、PUT、PATCH、POST 和 DELETE 操作与这些资源进行交互。OData 服务 URL 由 3 部分组成。
在这里插入图片描述

  1. url 的服务根:是服务的基本 url。当对此 url发出GET请求时,它将返回一个服务文档,该文档定义了通过该服务可用的所有资源。
  2. 资源路径 :REST 定义的资源是一个对象,可以使用标准的 GET、POST、PUT、PATCH 和 DELETE 方法通过 HTTP 访问。它可以是单个对象或类似对象的集合,以有序或无序的方式呈现。一个对象由某种类型构成,与其他对象有关系,并有对其进行操作的方法。资源的一些示例可能是:客户、单个客户、与单个客户相关的订单等。数据模型公开的这些资源的可寻址方面的示例可能是:实体集合、单个实体、属性、链接、操作等。
  3. 查询选项:查询选项本质上是标准化的查询字符串参数,可以传递给 OData 服务以对请求的资源运行查询。他们可以帮助执行像某些操作select,filter,count,skip,order,search和format资源。所有 OData 查询选项都以$符号为前缀,并且不区分大小写。
    介绍完url地址的构成,下面开始构建服务端。

二、构建OData Api服务端

  1. 添加解决方案
    添加解决方案在这里插入图片描述
  2. 添加ASP.ENT Web 应用程序
    在这里插入图片描述
  3. 添加Web Api空模板
    在这里插入图片描述
    在这里插入图片描述
    在Model文件夹张中添加Product数据模型。
 public class Product
    {
        [Key]
        public String ID { get; set; }
        [Required]
        public String Name { get; set; }
        public String Description { get; set; }
    }

该Demo不使用EF框架,所以在添加控制器之前,将数据暂缓存到了内存中,创建DataSource文件夹,添加一下代码。

 public class DemoDataSources
    {
        private static DemoDataSources instance = null;
        public static DemoDataSources Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new DemoDataSources();
                }
                return instance;
            }
        }
        public List<Product> Product { get; set; }

        private DemoDataSources()
        {
            this.Reset();
            this.Initialize();
        }
        public void Reset()
        {
            this.Product = new List<Product>();
        }
        public void Initialize()
        {
            this.Product.AddRange(new List<Product>
            {
                new Product()
                {
                    ID = "001",
                    Name = "Angel",

                },
                new Product()
                {
                    ID = "002",
                    Name = "Clyde",
                    Description = "Contrary to popular belief, Lorem Ipsum is not simply random text.",
                },
                new Product()
                {
                    ID = "003",
                    Name = "Elaine",
                    Description = "It has roots in a piece of classical Latin literature from 45 BC, making Lorems over 2000 years old."
                }
            });
        }
    }

创建控制器:
在这里插入图片描述
在这里插入图片描述
注:如果使用的是OData V4 , 请将using System.Web.Http.OData改成using Microsoft.AspNet.OData。不然访问OData Api时会出现406的错误。Microsoft.AspNet.OData可通过Nuget安装。

 [EnableQuery]
    public class ProductController : ODataController
    {
        //Product
        public IHttpActionResult Get()
        {
            return Ok(DemoDataSources.Instance.Product.AsQueryable());
        }
        //Product(key)
        public IHttpActionResult Get([FromODataUri]string key)
        {
            var res = DemoDataSources.Instance.Product.Where(p => p.ID == key).FirstOrDefault();
            if (res == null)
                return Ok();
            return Ok(res);
        }
        public IHttpActionResult Post(Product product)
        {
            if (!ModelState.IsValid)
                return StatusCode(HttpStatusCode.BadRequest);
            DemoDataSources.Instance.Product.Add(product);
            return Created(product);
        }
        //局部更新
        public IHttpActionResult Patch([FromODataUri] string key, Delta<Product> product)
        {
            var res = DemoDataSources.Instance.Product.Where(p => p.ID == key).FirstOrDefault();
            return Updated(res);
        }
        //全部更新
        public IHttpActionResult Put([FromODataUri]string key, Product product)
        {
            var res = DemoDataSources.Instance.Product.Where(p => p.ID == product.ID).FirstOrDefault();
            if (res == null)
            {
                return NotFound();
            }
            res.Description = product.Description;
            return Ok(res);
        }
        //删除
        public IHttpActionResult Delete([FromODataUri] string key)
        {
            var people = DemoDataSources.Instance.Product.Where(p => p.ID == key).FirstOrDefault();
            if (people == null)
            {
                return Ok();
            }
            DemoDataSources.Instance.Product.Remove(people);
            return Ok(people);
        }
    }

对于ProductController中添加的这几个方法,就是对实体进行一些基本操作,在这里不做介绍。到这里,我们的OData Api 基本上就完成了,但要正确的访问这些接口,还要做一些路由配置。在WebApiConfig里面添加一下代码,需要引用的命名空间
using Microsoft.AspNet.OData.Builder;
using Microsoft.AspNet.OData.Extensions;

public static void Register(HttpConfiguration config)
        {
        //以下为新增代码
            ODataModelBuilder builder = new ODataConventionModelBuilder();
            builder.Namespace = "Demos";
            builder.ContainerName = "DefaultContainer";
            builder.EntitySet<Product>("Product");
            config.MapODataServiceRoute(
                //要映射的路径名称
                routeName: "ODataRoute",
                //添加到 OData 路由路径模板的前缀
                routePrefix: null,
                //用于解析 OData 路径的 EDM 模型
                model: builder.GetEdmModel());
             }

运行工程:到这里,我们就可以通过Fiddler来访问我们创建的接口了。
在这里插入图片描述
在Fiddler中,http://localhost:12786/$metadata 可获取到元数据文档
在这里插入图片描述

  1. Get: http://localhost:12786/Product 访问Get()接口
  2. Get: http://localhost:12786/Product(‘001’) 访问Get([FromODataUri]string key)接口
  3. Post: http://localhost:12786/Product 访问Post(Product product) 接口,注:访问该接口时要设置content-type: application/json,请求体: {“ID”:“004”,“Name”:“zhangsan”,“Description”:“Test”}
  4. Patch: http://localhost:12786/Product(‘004’) 访问:Patch([FromODataUri] string key, Delta product) 注:访问该接口时要设置content-type: application/json,请求体: {“ID”:“004”,“Name”:“zhangsan”,“Description”:“TestPatch”}
  5. Put: http://localhost:12786/Product(‘004’) 访问:Put([FromODataUri]string key, Product product) 注:访问该接口时要设置content-type: application/json,请求体: {“ID”:“004”,“Name”:“zhangsan”,“Description”:“TestPut”}
  6. Delete:http://localhost:12786/Product(‘004’) 访问:Delete([FromODataUri] string key)
    到目前为止,访问OData Api的操作和普通的Web Api没什么区别。接下来创建客户端,在客户端中体现OData Api的便捷。

三、创建客户端

创建客户端之前,需要安装一个OData的客户端模板,如下图所示:
![(https://img-blog.csdnimg.cn/3d7416cead8a441c982b00319d85b184.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODc5Mzg1NQ==,size_16,color_FFFFFF,t_70)
在这里插入图片描述
在这里插入图片描述
添加好这个tt模板之后,系统会报一个异常错误,这个暂时可以忽略。如下:在这里插入图片描述
这是因为我们还没设置要设置元数据的uri地址。我们的项目中会新增两个文件,ODataServer.tt 和 ODataServer.ttinclude。 元数据文档的uri地址在ODataServer.tt 文件里面,打开这个文档,里面会有public const string MetadataDocumentUri = “”;这句代码,我们只需将之前新建的web api地址,填写到这里里面即可。public const string MetadataDocumentUri = “http://localhost:12786/”;
接下来我们生成元数据文档,在生成元数据之前,我们要保证web api 服务是运行的,这一点比较重要。web api运行只有,选中ODataServer.tt 文件,选择调试T4模板。运行只有,在ODataServer.cs 就可以看到生成的元数据文档。在这里插入图片描述
开发在这里插入图片描述
这些操作完成之后,我们就可以在客户端使用了,在客户端中,实现最基本的增删改查操作,在这里解释客户端的增删改查与OData Api对应的关系。

const string serverUri = “http://localhost:12786/”;
static void Main(string[] args)
{
DefaultContainer defaultContainer = new DefaultContainer(new Uri(serverUri));
foreach(var item in defaultContainer.Product)
{
Console.WriteLine(KaTeX parse error: Expected 'EOF', got '}' at position 54: …on}"); }̲ } 1、获取所有…"{item.ID},{item.Name},{item.Description}");
}
defaultContainer.Product是一个只读的DataServiceQuery类型的数据,它将访问OData Api中的Get()接口。
2、根据ID获取对应的Product。
//该语句会直接访问 OData Api的Get([FromODataUri]string key)接口。
var product = defaultContainer.Product.Where(p => p.ID == “1”).FirstOrDefault();
3、添加一个新对象
var newProduct = Product.CreateProduct(“004”, “add_test”);
//defaultContainer.AddObject(“Product”, newProduct);
// 个人理解:该语句构建了一个待要访问uri地址,并且带上相应的数据。
defaultContainer.AddToProduct(newProduct);
//个人理解:该语句向上一步都建好的地址,发送请求数据。
//该语句会直接访问 OData Api的Post(Product product)接口。
defaultContainer.SaveChanges();
4、更新一个对象操作:
var update = defaultContainer.Product.Where(p => p.ID == “001”).FirstOrDefault();
update.Description = “更新描述”;
// 个人理解:该语句构建了一个待要访问uri地址,并且带上相应的数据。
defaultContainer.UpdateObject(update);
//个人理解:该语句向上一步都建好的地址,发送请求数据。
//该语句会直接访问 OData Api的 Patch([FromODataUri] string key, Delta product)接口。
defaultContainer.SaveChanges();
5、删除一个指定的对象
var delete = defaultContainer.Product.Where(p => p.ID == “001”).FirstOrDefault();
defaultContainer.DeleteObject(delete);
//该语句会直接访问 OData Api的 Delete([FromODataUri] string key)接口。
defaultContainer.SaveChanges();

实体关系

三、OData对查询选项支持

  1. $expand 以内联方式展开相关实体。
  2. $filter 根据布尔条件筛选结果。
  3. $inlinecount 通知服务器在响应中包括匹配实体的总数。 (适用于服务器端分页。 )
  4. $orderby 对结果进行排序。
  5. $select 选择要包括在响应中的属性。
  6. $skip 跳过前 n 个结果。
  7. $top 仅返回结果的前 n 个。
    若要使用 OData 查询选项,则必须显式启用它们。 你可以为整个应用程序全局启用它们,也可以为特定控制器或特定操作启用它们。
    若要全局启用 OData 查询选项,请在启动时调用HttpConfiguration类上的EnableQuerySupport
    config.EnableQuerySupport();该方法在v4版本中已过时,不起作用
    全局设置:config.MaxTop(null); config.Filter(); config.OrderBy();config.Expand();config.SkipToken();config.MaxTop(100);config.SkipToken();
    以下为单个接口设置
    仅允许 $skip 和 $top 支持分页,无其他操作:
    [Queryable(AllowedQueryOptions=AllowedQueryOptions.Skip | AllowedQueryOptions.Top)]
    仅允许按某些属性排序,以防止对未在数据库中编制索引的属性进行排序:
    [Queryable(AllowedOrderByProperties=“Id”)] // comma-separated list of properties
    允许 “eq” 逻辑函数,但不允许其他逻辑函数:
    [Queryable(AllowedLogicalOperators=AllowedLogicalOperators.Equal)]
    不允许任何算术运算符:
    [Queryable(AllowedArithmeticOperators=AllowedArithmeticOperators.None)]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值