Peterworks
Peterworks

Reputation: 505

Invalid format for continuation token on Cosmos db

Currently I try to get next result of my query at Cosmos db this is my code.

public async Task<KeyValuePair<string, IEnumerable<Peterworks>>> GetMultipleAsyncPaging(string queryString, string continuesToken,
        int pageSize)
{
    var results = new List<Peterworks>();
    QueryRequestOptions queryRequestOptions = new QueryRequestOptions();
    queryRequestOptions.MaxItemCount = pageSize;

    var query = _container.GetItemQueryIterator<Peterworks>(new QueryDefinition(queryString), continuesToken, queryRequestOptions);

    FeedResponse<Peterworks> feedResponse = await query.ReadNextAsync();
    foreach (Peterworks peterworks in feedResponse)
    {
        results.Add(peterworks);
    }
    return new KeyValuePair<string, IEnumerable<Peterworks>>(feedResponse.ContinuationToken, results);
}

Using this code with Asp.net core web api

API

        public async Task<IActionResult> GetPageResult(string appkey, string postbackType, long startDate, long endDate, int pagesize, string continuetoken)
    {
        KeyValuePair<string, IEnumerable<Peterworks>> returnValue;
        int pageNumber = 0;
        var query =
            $"SELECT * FROM peter_db p where p.appkey = '{appkey}'AND p.postback_type = '{postbackType}' AND p.event_time >= {startDate} AND p.event_time <= {endDate} ORDER BY p.event_time";

        if (continuetoken == "null")
        {
            string continueNullToken = null;

            returnValue =
                await _cosmosDbService.GetMultipleAsyncPaging(query, continueNullToken, pagesize);

        }
        else
        {
            string continueTokenDecode = HttpUtility.UrlDecode(continuetoken);
            var jsonContiueToken = JsonConvert.SerializeObject(continueTokenDecode);

            returnValue =
                await _cosmosDbService.GetMultipleAsyncPaging(query, jsonContiueToken, pagesize);
        }

        return Ok(returnValue);

    }

When token is null I get this result

{  "key": "[{\"token\":\"+RID:~6XYNAPAaNywkAQAAAAAAAA==#RT:1#TRC:2#RTD:EOhlC3LmlrnZoy5QrRcNBMHZH43PLA==#ISV:2#IEO:65567#QCF:7#FPC:AgEAAAAyAK8A4Hf99T7xxMAf+QH8/AF/APwPeEB/nWZk+H8A8H8ACMAA8P//A5Dw///f/v////8B\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]",

Using this token value I try to get next result, but this error came in.

Microsoft.Azure.Cosmos.Query.Core.Exceptions.MalformedContinuationTokenException: Invalid format for continuation token "[{\\\"token\\\":\\\" RID:~6XYNAPAaNywkAQAAAAAAAA==#RT:1#TRC:2#RTD:EOhlC3LmlrnZoy5QrRcNBMHZH43PLA==#ISV:2#IEO:65567#QCF:7#FPC:AgEAAAAyAK8A4Hf99T7xxMAf QH8/AF/APwPeEB/nWZk H8A8H8ACMAA8P//A5Dw///f/v////8B\\\",\\\"range\\\":{\\\"min\\\":\\\"\\\",\\\"max\\\":\\\"FF\\\"}}]" for ParallelCrossPartitionQueryPipelineStage

Without jsonConvert, this error came out.

Microsoft.Azure.Cosmos.CosmosException : Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: f1a36b17-58de-44f9-9d73-ba699c38bb16; Reason: (Encountered an unexpected JSON token.ActivityId: f1a36b17-58de-44f9-9d73-ba699c38bb16, Darwin/10.16 cosmos-netstandard-sdk/3.19.3);

What am I missing?

Upvotes: 0

Views: 1942

Answers (2)

Peterworks
Peterworks

Reputation: 505

Thanks for all the answers. I found what was the problem.

The problem was a continuation token return on JSON.

{  "key": "[{\"token\":\"+RID:~6XYNAPAaNywkAQAAAAAAAA==#RT:1#TRC:2#RTD:EOhlC3LmlrnZoy5QrRcNBMHZH43PLA==#ISV:2#IEO:65567#QCF:7#FPC:AgEAAAAyAK8A4Hf99T7xxMAf+QH8/AF/APwPeEB/nWZk+H8A8H8ACMAA8P//A5Dw///f/v////8B\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]",

When continuation token return to json, token has "\" compaier to original contiuation token. So I remove all "\" and try again it works.

Upvotes: 0

Noah Stahl
Noah Stahl

Reputation: 7553

In ASP.NET Core, an approach I've used to make the continuation token safe for round-tripping as a URL parameter is to leverage Base64UrlEncode.

To encode before returning to client:

using Microsoft.AspNetCore.WebUtilities;
...

string continuationToken = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(cosmosToken));

To decode when provided by client:

// Decode continuation token if provided
string? currentContinuationToken = !string.IsNullOrEmpty(continuationToken) 
    ? Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(continuationToken)) 
    : null;

Upvotes: 3

Related Questions