2019-05-18 更新 :

目前遇到的问题

odata 团队非常的不给力,虽然我都用了好多年了,但是越用越少. 它的维护实在太差了。

很多好的功能都是因为 bug 而用不上.

1. https://github.com/OData/WebApi/issues/194

/api/orders?$filter=stringList/any(v:v eq 'a')

stringList 是一个 json 来的, 使用 any 可以进行 filter, 虽然它不是在 sql 层面上做 filter 但也很不错了。

可是呢,如果 stringList 是 empty array 那样就会报错了.

而 /$count gt 0 有 bug 不能用.

应对方式,  json 就不要做 filter

update: 2019-10-28

https://docs.microsoft.com/en-us/odata/changelog/webapi-7x

7.2 版本后,这个 bug 没有了

但还是要记住哦,这个 filter 不是在 sql 层面做的,它会先把所有资料调出来在 c# 过滤.

所以有用 odata 还是少用 List<string> 这种 conversion 呗.

2.https://github.com/OData/WebApi/issues/196

complex type $select 不能用. bug !

应对 : 不要用 complex type 改用 1-1

这个被解决了 update 2020-01-10

3. https://github.com/OData/WebApi/issues/1687

继承 + $expand

应对 : 不要用继承

从前用 odata 做 restful GET POST DELETE PUT,用久了最后剩下 GET, 其余的全部用 web api

虽然 odata 很多问题, dto 也支持到很差基本不用.

但是任然比 graphql 好用. 希望有天这 2 个工具都越来越好呗.

4. https://github.com/OData/odata.net/issues/1491

ODataUriParser not working correct when have filter contains and operation or with parentheses

这个比较底层的功能...filter + contains + or + parentheses 会parse or formatter 坏掉

5. https://github.com/OData/odata.net/issues/1393

enum 不能 filter, 这个 fixed 了 update 2020-01-10

2018-12-10 更新 :

从前我都是把 entity 直接用于 odata 曝露 api 给程序用.

如果这个程序是我们自己写的前端,这样的方式非常好,因为就好比前端可以直接对数据库每一个表做操作。

但是呢,如果这个程序是外部的,那么就可能不应该直接把 entity 曝露出去了。

这时就会有个 dto 的概念来了.

上层点看,就是对于这些外人,他们依然可以使用 odata 访问数据,也可以 restful ,但是呢,他们看到的 entity 和我们数据来真正的 entity 是不同的。

这个概念和数据库做 view 表是一样的.

这时比较大的问题就是映射了. 因为用户操作的表可能并不存在,或者是多表联合而成.

如果用过 automapper 的可以尝试   useAsDataSource

 return Ok(Db.Categories.UseAsDataSource().For<CategoryDto>());

automapper 会帮我们对应好, 不过目前测试 expand 是会报错的... 我目前是没有这个需要. 希望要用到的时候一切正常..

虽然我没有需要在 get 的情况下使用 Dto 概念.

但是在 post put delete 时却是需要的,我个人的感觉是如果是内部用的 api 就不要使用 restful, 提供给外部的 api 就用. 类似 facebook 的 graphapi 那样就不错.

那 post put 的时候就得使用 odata action 了

action 遇到最大的问题是, parameters 每次要定义. 如果我们使用 dto 基本上可以用 [FormBody] 无需定义, 有一个前提是 postdata 不可以有继承 @odata.type 这种东西, 也不可以是 entity (必须是 dto)

那么如果真的遇到要继承,那就只能写 parameters 了。

builder.EntitySet<User>("Users");
var a = builder.EntityType<User>().Collection.Action("CreateUser");
a.Parameter<UserDto>("user");
a.Namespace = "Rpc"; // Namespace 是必须的,而且不要定义在全局哦. 不然你 get data 的时候, 派生类会变成 @odata.type = "#Namespace.", 这是不对的,应该是 @odata.type = "#YourEntityNamespace." 才对. [HttpPost]
public IActionResult CreateUser(ODataActionParameters parameters)
{
// Model.State.IsValid // valid parametes only
var user = (UserDto)parameters["user"];
var v = TryValidateModel(user); //valid real post data
var error = ModelState; //get error
return Ok();
} // post data
{
user : {
"Id": ,
"password": "",
"characters": [
{
"@odata.type": "#odata.Models.AdminDto",
"Id": ,
"name": "",
"userId": ,
"age":
}
]
} }

和 asp.net odata 区别不大. 用法依旧.

定义 EdmModel

public static class ODataConfig
{
public static IEdmModel GetEdmModel(IServiceProvider servicePrivider)
{
var builder = new ODataConventionModelBuilder(servicePrivider); /*
对应 route :
GET : /odata/products
GET : /odata/products(key)
POST : /odata/products
PUT : /odata/products(key)
DELETE : /odata/products(key)
*/
builder.EntitySet<Product>("Products"); // POST /odata/products/changeSort
var productChangeSort = builder.EntityType<Product>().Collection.Action("changeSort");
productChangeSort.Returns<string>(); // POST /odata/products(key)/doSomething
var sample1 = builder.EntityType<Product>().Action("doSomething");
sample1.Returns<string>();

// GET /odata/products/getSomething
          var sample2 = builder.EntityType<Product>().Collection.Function("getSomething");
          sample2.ReturnsCollectionFromEntitySet<Product>("Products");

return builder.GetEdmModel();
}
}

普通的 get,post,put,delete 和 RPC get 和 post

然后在 UseMvc 添加上 routing

app.UseMvc(builder =>
{
builder.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"); builder.Select().Expand().Filter().OrderBy().MaxTop(null).Count();
builder.MapODataServiceRoute("odata", "odata", ODataConfig.GetEdmModel(app.ApplicationServices));
});

odata 有 default routing 匹配的概念,就好像第一个 code 图的 path 就是 default 的对应.

因为使用的是 default routing 所以不需要添加 [ODataRoute] 标签, 同时也无法使用 [ApiController], 因为 apicontroller 依赖 route 标签...

所以我们必须使用 [FromQuery] [FromBody] binding data.

builder.EntitySet<Product>("Products"); 里头的 "Products" 对应了 "ProductsController"

get,put,post,delete 是通过方法名字的前面几个字来匹配的.

builder.EntityType<Product>().Collection.Action("changeSort") 的 "changeSort" 对应的是 "changeSort" 方法名

如果你使用 ODataRoute 的话,那么就不看方法名字,转而看 ODataRoute 来对应. 同时需要写上 httpmethod 标签来做匹配.

建议使用自动匹配, 方法名字 unique 就行了, 还有 url 是不区分大小写的. action 也不一定要写上 namespace, 不写也是可以 ok 的哦.

如果是手动调用的话,还是区分大小写和使用 namespace 比较好,看来 odata 在处理 request 的时候帮我们做了些事儿,所以才那么方便.

var request = new ODataUriParser(Request.GetModel(), "http://192.168.1.152:61547/api", "http://192.168.1.152:61547/api/Users/RPC.Me?$expand=characters") 
{ Resolver = new ODataUriResolver { EnableCaseInsensitive = true } }.ParseUri();
var uri = request.BuildUri(ODataUrlKeyDelimiter.Parentheses);

还有 build uri 和之前有点不同了.

    public class ChangeSortData
{
public int aSort { get; set; }
public int bSort { get; set; }
} public class ProductsController : ODataController
{
private DB Db { get; set; }
public ProductsController(DB db)
{
Db = db;
} [EnableQuery(AllowedQueryOptions = AllowedQueryOptions.Count | AllowedQueryOptions.Expand, MaxExpansionDepth = )]
public IActionResult Get(ODataQueryOptions<Product> queryOptions)
{
return Ok(Db.Products);
} public IActionResult Post([FromBody] Product resource)
{
return Ok("ok");
} public IActionResult Put(int key, [FromBody] Product resource)
{
return Ok("ok");
} public IActionResult Delete(int key)
{
return Ok("ok");
} public IActionResult ChangeSort([FromBody] ChangeSortData data)
{
return Ok("ok");
} public IActionResult DoSomething(int key)
{
return Ok("ok");
} [HttpGet] //由于没有自动匹配了,所以我们需要表达式 get 请求,这样才匹配的到
[ODataRoute("products/getsomething")]
public IActionResult WhatEver()
{
return Ok("ok");
}
}

Asp.net core 学习笔记 ( OData )的更多相关文章

  1. Asp.Net Core学习笔记:入门篇

    Asp.Net Core 学习 基于.Net Core 2.2版本的学习笔记. 常识 像Django那样自动检查代码更新,自动重载服务器(太方便了) dotnet watch run 托管设置 设置项 ...

  2. ASP.NET Core 学习笔记 第一篇 ASP.NET Core初探

    前言 因为工作原因博客断断续续更新,其实在很早以前就有想法做一套关于ASP.NET CORE整体学习度路线,整体来说国内的环境的.NET生态环境还是相对比较严峻的,但是干一行爱一行,还是希望更多人加入 ...

  3. Asp.net core 学习笔记 ( Web Api )

    asp.net core 把之前的 webapi 和 mvc 做了结合. mvc 既是 api. 但是后呢,又发现, api 确实有独到之处,所以又开了一些补助的方法. namespace Proje ...

  4. Asp.net Core学习笔记

    之前记在github上的,现在搬运过来 变化还是很大的,感觉和Nodejs有点类似,比如中间件的使用 ,努力学习ing... 优点 不依赖IIS 开源和跨平台 中间件支持 性能优化 无所不在的依赖注入 ...

  5. ASP.NET Core 学习笔记 第三篇 依赖注入框架的使用

    前言 首先感谢小可爱门的支持,写了这个系列的第二篇后,得到了好多人的鼓励,也更加坚定我把这个系列写完的决心,也能更好的督促自己的学习,分享自己的学习成果.还记得上篇文章中最后提及到,假如服务越来越多怎 ...

  6. ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置

    前言 说道配置文件,基本大多数软件为了扩展性.灵活性都会涉及到配置文件,比如之前常见的app.config和web.config.然后再说.NET Core,很多都发生了变化.总体的来说技术在进步,新 ...

  7. ASP.NET Core 学习笔记 第五篇 ASP.NET Core 中的选项

    前言 还记得上一篇文章中所说的配置吗?本篇文章算是上一篇的延续吧.在 .NET Core 中读取配置文件大多数会为配置选项绑定一个POCO(Plain Old CLR Object)对象,并通过依赖注 ...

  8. Asp.net core 学习笔记 ( Data protection )

    参考 : http://www.cnblogs.com/xishuai/p/aspnet-5-identity-part-one.html http://cnblogs.com/xishuai/p/a ...

  9. Asp.net core 学习笔记 SignalR

    refer : https://kimsereyblog.blogspot.com/2018/07/signalr-with-asp-net-core.html https://github.com/ ...

随机推荐

  1. NATS—协议详解(nats-protocol)

    NATS的协议是一个简单的.基于文本的发布/订阅风格的协议.客户端连接到 gnatsd(NATS服务器),并与 gnatsd 进行通信,通信基于普通的 TCP/IP 套接字,并定义了很小的操作集,换行 ...

  2. Differences Between Enterprise, Standard and Standard One Editions on Oracle 11.2 (Doc ID 1084132.1)

    标准版不允许并行.分区.闪回.各种缓存等大数据量必须特性,如此限制,oracle摆明了只卖企业版,买标准版不如mysql(如果不熟悉postgresql的话). Oracle企业版1 CPU 20w起 ...

  3. 写给大忙人的ELK最新版6.2.4学习笔记-Logstash和Filebeat解析(java异常堆栈下多行日志配置支持)

    接前一篇CentOS 7下最新版(6.2.4)ELK+Filebeat+Log4j日志集成环境搭建完整指南,继续对ELK. logstash官方最新文档https://www.elastic.co/g ...

  4. 【专家坐堂Q&A】在 petalinux-config 中选择外部来源时,可将符号链路添加内核来源目录树

    问题描述 作为 petalinux-config 菜单的一部分,现在可以将 Linux 内核指定为外部来源. 如果选择了该选项,可为内核来源目录树添加两个符号链路. 这会带来两个问题: 1. 符号链路 ...

  5. hdu 1811 Rank of Tetris - 拓扑排序 - 并查集

    自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他将制作一个全球Tetris高手排行榜, ...

  6. 关于python hashlib模块的使用

    hashlib hashlib主要提供字符加密功能,将md5和sha模块整合到了一起,支持md5,sha1, sha224, sha256, sha384, sha512等算法 #!/usr/bin/ ...

  7. Bootstrap3基础 img-thumbnail 给图片加一个圆角的边框

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  8. 2-sat相关复习

    2-sat相关复习 noi曾经考过,谁能说得准呢 sat问题 通俗的sat问题表述一般是这样的:有很多个集合,每个集合里面有若干元素,现给出一些取元素的规则,要你判断是否可行,可行则给出一个可行方案. ...

  9. 洛谷P1803 凌乱的yyy dp

    我要日更嘤嘤嘤>_< 原题戳>>https://www.luogu.org/problem/show?pid=1803<<(其实是戳不动的,复制粘贴吧) 题目背景 ...

  10. vue.js精讲02

    2017-09-17 笔记及源码地址 : https://github.com/wll8/vue_note vue 中的事件深入. 事件: @click/mouseover…事件简写: @ 如 @cl ...