.NET Core开发日志之OData(Open Data Protocol)
简述
OData,即Open Data Protocol,是由微软在2007年推出的一款开放协议,旨在通过简单、标准的方式创建和使用查询式及交互式RESTful API。
类库
在.NET Core中想要使用OData功能的话需要添加Microsoft.AspNetCore.OData包。
dotnet add package Microsoft.AspNetCore.OData
准备模型类
public class Address { public string City { get; set; } public string Street { get; set; } } public enum Category { Book, Magazine, EBook } public class Press { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public Category Category { get; set; } } public class Book { public int Id { get; set; } public string ISBN { get; set; } public string Title { get; set; } public string Author { get; set; } public decimal Price { get; set; } public Address Address { get; set; } public Press Press { get; set; } }
创建Edm模型
OData使用EDM,即Entity Data Model来描述数据的结构。在Startup文件中添加创建方法。
private static IEdmModel GetEdmModel() { var builder = new ODataConventionModelBuilder(); builder.EntitySet<Book>("Books"); builder.EntitySet<Press>("Presses"); return builder.GetEdmModel(); }
注册OData服务
在Startup文件的ConfigureServices方法里注册OData服务。
services.AddOData(); services.AddMvc(options => { options.EnableEndpointRouting = false; }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
这里要注意的是在.NET Core 2.2里,默认已经有终结点,所以要使用OData的终结点的话需要将默认选项禁用掉。
注册OData终结点
同样在Startup文件里,在其Configure方法内将原来的注册路由内容改为注册OData的终结点。
app.UseMvc(b => { b.MapODataServiceRoute("odata", "odata", GetEdmModel()); });
显示元数据
运行程序后访问https://localhost:5001/odata/$metadata地址,可以看到所有可用模型的元数据。
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0"> <edmx:DataServices> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Default"> <EntityType Name="Book"> <Key> <PropertyRef Name="Id"/> </Key> <Property Name="Id" Type="Edm.Int32" Nullable="false"/> <Property Name="ISBN" Type="Edm.String"/> <Property Name="Title" Type="Edm.String"/> <Property Name="Author" Type="Edm.String"/> <Property Name="Price" Type="Edm.Decimal" Nullable="false"/> <Property Name="Address" Type="Default.Address"/> <NavigationProperty Name="Press" Type="Default.Press"/> </EntityType> <EntityType Name="Press"> <Key> <PropertyRef Name="Id"/> </Key> <Property Name="Id" Type="Edm.Int32" Nullable="false"/> <Property Name="Name" Type="Edm.String"/> <Property Name="Email" Type="Edm.String"/> <Property Name="Category" Type="Default.Category" Nullable="false"/> </EntityType> <ComplexType Name="Address"> <Property Name="City" Type="Edm.String"/> <Property Name="Street" Type="Edm.String"/> </ComplexType> <EnumType Name="Category"> <Member Name="Book" Value="0"/> <Member Name="Magazine" Value="1"/> <Member Name="EBook" Value="2"/> </EnumType> <EntityContainer Name="Container"> <EntitySet Name="Books" EntityType="Default.Book"> <NavigationPropertyBinding Path="Press" Target="Presses"/> </EntitySet> <EntitySet Name="Presses" EntityType="Default.Press"/> </EntityContainer> </Schema> </edmx:DataServices> </edmx:Edmx>
创建Controller
本文实例中不考虑数据库的操作,故而使用hard code方式构建必要的模型对象。
public class BooksController : ODataController { private static IList<Book> Books {get; set;} public BooksController() { Books = new List<Book> { new Book { Id = 1, ISBN = "111-0-321-56789-1", Title = "Calculus", Price = 66.6m, Address = new Address { City = "Shanghai", Street = "Beijin Xi Road" }, Press = new Press { Id = 1, Name = "Shanghai Tongji", Category = Category.Book } }, new Book { Id = 2, ISBN = "222-2-654-00000-2", Title = "Linear Algebra", Price = 53.2m, Address = new Address { City = "Shanghai", Street = "Beijin Dong Road" }, Press = new Press { Id = 2, Name = "Shanghai Fudan", Category = Category.EBook } } }; } [EnableQuery] public IActionResult Get() { return Ok(Books); } [EnableQuery] public IActionResult Get(int key) { return Ok(Books.FirstOrDefault(b => b.Id == key)); } }
EnableQuery特性在需要高级查询的场景时必须添加。
查询
加入Controller之后,访问https://localhost:5001/odata/Books地址,可得到所有Book数据。
{ "@odata.context": "https://localhost:5001/odata/$metadata#Books", "value": [ { "Id": 1, "ISBN": "111-0-321-56789-1", "Title": "Calculus", "Author": null, "Price": 66.6, "Address": { "City": "Shanghai", "Street": "Beijin Xi Road" } }, { "Id": 2, "ISBN": "222-2-654-00000-2", "Title": "Linear Algebra", "Author": null, "Price": 53.2, "Address": { "City": "Shanghai", "Street": "Beijin Dong Road" } } ] }
访问https://localhost:5001/odata/Books(1)地址,可得到key值为1的Book数据。
{ "@odata.context": "https://localhost:5001/odata/$metadata#Books/$entity", "Id": 1, "ISBN": "111-0-321-56789-1", "Title": "Calculus", "Author": null, "Price": 66.6, "Address": { "City": "Shanghai", "Street": "Beijin Xi Road" } }
高级查询
如果想要使用OData查询的高级功能,可以在注册终结点时额外加上相应的配置。
app.UseMvc(b => { b.Select().Expand().Filter().OrderBy().MaxTop(100).Count(); b.MapODataServiceRoute("odata", "odata", GetEdmModel()); });
访问网址时加上所需的查询内容:
https://localhost:5001/odata/Books?$select=Id,Title
{ "@odata.context": "https://localhost:5001/odata/$metadata#Books(Id,Title)", "value": [ { "Id": 1, "Title": "Calculus" }, { "Id": 2, "Title": "Linear Algebra" } ] }
如果想要按特定条件过滤数据内容的话也很容易:
https://localhost:5001/odata/Books?$filter=Price%20le%2060
{ "@odata.context": "https://localhost:5001/odata/$metadata#Books", "value": [ { "Id": 2, "ISBN": "222-2-654-00000-2", "Title": "Linear Algebra", "Author": null, "Price": 53.2, "Address": { "City": "Shanghai", "Street": "Beijin Dong Road" } } ] }
总结
不难看出,OData的真正魅力在于其对那些高级查询功能的支持,所以在创建RESTful API时,不妨考虑使用OData,这样应该能减少许多不必要的代码工作。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对猪先飞的支持。
相关文章
- 这篇文章主要介绍了.NET Core下使用Kafka的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
- 这篇文章主要介绍了详解.NET Core 3.0 里新的JSON API,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
ASP.NET Core根据环境变量支持多个 appsettings.json配置文件
这篇文章主要介绍了ASP.NET Core根据环境变量支持多个 appsettings.json配置文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22- 这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
详解ASP.NET Core 中基于工厂的中间件激活的实现方法
这篇文章主要介绍了ASP.NET Core 中基于工厂的中间件激活的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22- Underscore 是一个 JavaScript 工具库,它提供了一整套函数式编程的实用功能,但是没有扩展任何 JavaScript 内置对象。这篇文章主要介绍了underscore源码分析相关知识,感兴趣的朋友一起学习吧...2016-01-02
详解.NET Core 使用HttpClient SSL请求出错的解决办法
这篇文章主要介绍了.NET Core 使用HttpClient SSL请求出错的解决办法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-09-22.net EF Core专题:EF Core 读取数据时发生了什么?
这篇文章主要介绍了EF Core 读取数据的的相关知识,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2021-09-22- 这篇文章主要介绍了详解ASP.NET Core Token认证,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2021-09-22
- .net core是最近讨论频率很高的话题,下面这篇文章主要给大家介绍了关于利用.NET Core如何获取操作系统中各种信息的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧...2021-09-22
- 这篇文章主要介绍了asp.net core MVC之实现基于token的认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-07
- 这篇文章主要介绍了ASP.NET Core如何注入多个服务实现类的相关资料,需要的朋友可以参考下面文章的具体内容...2021-09-22
ASP.NET core Web中使用appsettings.json配置文件的方法
这篇文章主要给大家介绍了在ASP.NET core Web中使用appsettings.json配置文件的方法,文中给出了详细的示例代码,需要的朋友可以参考学习,下面来一起看看吧。...2021-09-22- 这篇文章主要介绍了ASP.NET Core使用JWT认证授权的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
- 这篇文章主要介绍了详解EFCore中的导航属性的相关资料,帮助大家更好的理解和学习使用ASP.NET CORE,感兴趣的朋友可以了解下...2021-09-22
ASP.NET Core MVC如何实现运行时动态定义Controller类型
这篇文章主要介绍了ASP.NET Core MVC如何实现运行时动态定义Controller类型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22- 这篇文章主要介绍了dotnet core链接mongodb代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-25
详解ASP.NET Core部署项目到Ubuntu Server
这篇文章主要介绍了详解ASP.NET Core部署项目到Ubuntu Server ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22- 这篇文章主要给大家介绍了关于利用.net core实现反向代理中间件的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用.net core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2021-09-22
ASP.NET Core使用SkiaSharp实现验证码的示例代码
本篇文章主要介绍了ASP.NET Core使用SkiaSharp实现验证码的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-09-22