In my sample project, I set the entity page size to 20. Then I have an entity set with result count which is divisible to the page size. For example, the Categories set which has 100 items. When I go to:
http://localhost/Sample.svc/Categories?$skiptoken=80
I got 81st to 100th categories and the page has the “next” link
http://localhost/Sample.svc/Categories?$skiptoken=100
I tried to go to that page and it returns nothing.
What’s the explanation for that?
The paging simply takes the next PageSize items. If it finds less than that, then it’s clear there are no more items to return so you don’t get the next link. If the query returns the requested number of items, the runtime doesn’t try to figure out if this is the last page or not, it simply returns a next link. It might happen that such a link will return no results.
In fact the next link is not bound to return any results, but as long as the response constains another next link, there are potentially more results. The standard built in paging will return pages of the predefined size (except for the last one), but services are free to use any other kind of paging which might return different sizes for each page (including empty pages).
To directly answer your question “Why is the last page empty?”:
The runtime doesn’t “look ahead” so it can’t tell if a given page is the last one except for when it gets less than the expected number of results. Looking ahead would be both costly (asking for more than necessary) and potentially wrong (what if the extra result causes an error…).