am planning to implement paging using cosmos db continuation token. My api will return results and continuation token to client. My question here is which is the best place to store continuation token? Also the token will be changing per each subsequent request? How to maintain the previous continousTokens?
Here it shows where we get the value from and not where to store it How to pass\user azure continue token via webAPI Pagination in Cosmos DB using Page Size and Page Number
controller.cs
[Route("myApps")]
[HttpGet]
public async Task<IActionResult> GetAllAppsAsync(string continuationToken, CancellationToken cancellationToken)
{
var user = this.GetUser();
var results = await this.appRepository.GetAppsForUserAsync(user, continuationToken, cancellationToken).ConfigureAwait(false);
var result = this.mapper.Map<AppHeader[]>(results.Value);
return this.Ok(new KeyValuePair<string, AppDefinitionHeader[]>(results.Key, result));
}
Repository.cs
public async Task<KeyValuePair<string, IEnumerable<App>>> GetAppForUserAsync(User user, string continuationToken, CancellationToken cancellationToken)
{
try
{
FeedOptions queryOptions = new FeedOptions
{
MaxItemCount = 2,
RequestContinuation = continuationToken
};
string token = string.Empty;
var query = this.factory.GetClient()
.CreateDocumentQuery<AppDefinitionResource>(
UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName),
queryOptions)
.AsDocumentQuery();
List<AppDefinition> results = new List<AppDefinition>();
while (query.HasMoreResults && results.Count <= 2)
{
cancellationToken.ThrowIfCancellationRequested();
var response = await query.ExecuteNextAsync<App>(cancellationToken).ConfigureAwait(false);
var apps = this.mapper.Map<App[]>(response);
results.AddRange(apps);
token = response.ResponseContinuation;
}
return new KeyValuePair<string, IEnumerable<App>>(token, results);
}
}
Update :
How to maintain the previous continousTokens?
Ex : If there are 100 records and pageSize=10 and pageNumbers are 1,2,3,4,5,6,7,8,9,10 and if user clicks randomly on any page. In that case how to fetch required records? or just if I place "Previous" button in the below screenshot and want to traverse back in the list.
Yes, the token changes for each request, so that you can retrieve previous pages with previous tokens.
If you pass the token on to the client to keep the backend stateless, you should not send the token within the URL or a URL query, since the token can get quite large. Within the client you can just keep the token in memory. In most cases it's not necessary to persist the token, since a token should be short-lived. It should be short-lived since paginated results reflects all the changes that happen between each page request.
Since the token may be large, it has to be passed in the body of the request, which also means it shouldn't be a GET request.
An alternative solution would be to store the token in a cache with a smaller key (e.g. a GUID) in the backend (with some limited TTL) and just pass the key between backend and client. That way you can pass the key in the URL or in a URL query. But that requires the backend to hold state.
Hey Mo, Just updated the question, Am passing continuationToken and results to client and in the subsequent request how to bind continuationToken in controller which is passed from client? I cannot use [FromUri] because token is quite huge and neither I can use body because of Get request. what's the best practice here?
@DeepakKothari I extended the answer. Does that answer your question?
I implemented this using "POST" request and here my doubt is how to maintain previous continuosTokens? How to maintain the previous continousTokens? Ex : If there are 100 records and pageSize=10 and pageNumbers are 1,2,3,4,5,6,7,8,9,10 and if user clicks randomly on any page. In that case how to fetch required records? or just if I place "Previous" button in the below screenshot and want to traverse back in the list. i.stack.imgur.com/BMwI2.gif
Not sure what you mean precisely, but in any case this should be asked in a separate question.
Hey @Mo, I want to page backward. I think I need to do this stackoverflow.com/questions/52357925/… or let me know if you have any ideas.