为什么odata Trippinservice只返回8页



当我给odata服务url时,https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TipPinServiceRW/浏览器中的人,我只得到8条记录。当People实体中总共有20条记录时,为什么我只得到8条记录?Trippinservice中是否设置了PageSize?有人能帮我理解吗?

是的,此服务实现服务器端分页。

首先,我们通过响应中@odata.nextLink属性的存在来确定服务器端分页是有效的,这是响应的根:

{
"@odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"@odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skiptoken=8",
"value": [
... 8 records ... 
]
}

我们只能通过计算响应中的记录数或查阅给定服务的文档来确认页面大小为8。在这种情况下,下一个链接中有一个$skiptoken查询参数,在这种情况中,它的值恰好为8,这与记录的数量相对应,但只是巧合
注意:%24是经过url编码的美元符号$

~/TripPinServiceRW/People?%24skiptoken=8

在OData Basic Tutorial中记录的TripPin服务的情况下,$skiptoken值表示跳过的记录数,是常见的实现,但它不是标准

文档中没有具体提到People提要的服务器页面大小,也没有在$metatdata中记录$skiptoken逻辑的标准方法。阅读如何以及为什么ASP.NET WebAPI实现skiptoken:使用$skiptoken进行服务器驱动的分页

我们可以通过导航下一个nextLink或更改$orderby:来演示这一点

获取:~/TipPinServiceRW/人员$skiptoken=8

{
"@odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"@odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skiptoken=16",
"value": [
... 8 more records ...
]
}

$skiptoken现在是新nextLink:~/TripPinServiceRW/People?%24skiptoken=16中的16。在许多实现中,$skiptoken将表示发送的最后一条记录的密钥值,但TripPin不使用此约定,我们可以通过更改顺序来验证:

这两个响应都将在nextLink中具有$skiptoken=8

GET:~/TipPinServiceRW/人员$orderby=用户名

{
"@odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"@odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24orderby=UserName&%24skiptoken=8",
"value": [
... 8 records ...
]
}

获取:~/TipPinServiceRW/人员$orderby=用户名描述

{
"@odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"@odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24orderby=UserName+desc&%24skiptoken=8",
"value": [
... 8 records ...
]
}

根据规范,$skiptoken是一个任意令牌,服务可以使用它从之前准备的集合中检索下一个页的数据。$skiptoken的值对服务器本身具有特殊意义,它可以是指向缓存结果集中页面的任意令牌或引用。

11.2.5.7服务器驱动分页
仅包括请求URL标识的部分项目集的响应必须包含一个允许检索下一部分项目的链接。此链接称为下一个链接;它的表示是特定于格式的。项目的最终部分集合不得包含下一个链接。

OData客户端必须将下一个链接的URL视为不透明,并且不得将系统查询选项附加到下一个链路的URL。服务可能不允许在请求使用下一个链接的后续页面时更改格式。因此,客户端应该使用兼容的Accept标头在后续页面请求中请求相同的格式。OData服务可以在构建下一个链路时使用保留的系统查询选项CCD_ 20。它的内容是不透明的、特定于服务的,并且只能遵循URL查询部分的规则。

值得在规范中强调这个非常具体的注释:

OData客户端在构造请求时不得使用系统查询选项$skiptoken。

$skiptoken是一个服务器端实现,在许多情况下,你甚至猜不到正确的值。TripPin服务是一个非常简单的演示API,它使用8的页面大小来说明服务器端分页的行为,考虑到整个数据集(20)的小尺寸,这是一个很好的任意数字,将导致多个页面的最后一页仅部分满。这足以测试服务器端支持数据接口的基本合规性。

服务器端分页旨在鼓励搜索驱动的界面,在该界面中,用户制定更精确的搜索标准,而不是按1浏览页面。虚拟滚动是一种利用服务器端分页的常见用户界面范例。不同的语言和运行时有不同的实现,但基本上用户可以滚动数据列表或网格;加载更多";记录(在后台,这将从nextLink加载响应)。有时,当用户接近或到达列表末尾时,此链接不会显示,数据会自动加载。

您仍然可以使用$top$skip查询参数使用传统的客户端分页,但是服务器端页面的某些服务实现仍然会将结果限制在该服务器内部逻辑定义的固定行数。如果您正在实现客户端分页,那么您可能仍然需要使用nextLink来检索每个客户机端结果页面的所有结果。

让我们通过首先获取客户端页面大小为5:的第2页进行比较

获取:~/TipPinServiceRW/人员$skip=5&顶部=5

{
"@odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"value": [
... 5 records ...
]
}

请注意,响应中没有@odata.nextLink属性,这是因为请求的项数没有超过服务器页面大小逻辑。所以让我们试试9的页面大小。这一次,要检索页面的所有记录,我们需要进行多次查询。

这里的一般指导是为响应中的每个nextLinkurl递归调用服务,如果它们包含NEXLink

GET:~/TipPinServiceRW/人员$skip=9&顶部=9

{
"@odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"@odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skip=9&%24top=9&%24skiptoken=8",
"value": [
... 8 records ...
]
}

获取:~/TipPinServiceRW/人员?%24跳过=9&%24顶部=9&%24skiptoken=8

{
"@odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"value": [
... 1 record ...
]
}

当您实现自己的符合OData-v4的API时,重要的是要理解怪癖,并在API文档中具体记录您在服务器端分页方面的策略或约定,以及在哪些集合上启用它

在我自己的实现中,如果请求包含客户端分页令牌$top(并且$top的值为<=200)但

客户端实现如果您在响应中看到nextLink属性,并且没有收到预期的记录数,那么如果您无法实现启用虚拟滚动的用户体验,则应查询后续服务器页面以满足您的请求。


注意:通常,当我们讨论OData v4服务中的分页时,示例包括使用$count查询选项

[11.2.9请求集合中的项目数]:成功时,在应用任何$filter$search系统查询选项后,响应体必须包含与请求匹配的项目的确切计数

返回的计数不得受$top$skip$orderby$expand的影响

TripPin服务不符合规范中的这个特定(和许多其他)子句,所以我在本解释中没有使用该查询选项

最新更新