WebAPI: Calculating NextPageLink for ODataResult<>

Fall update of Web API introduced ODataResult<> which is used to implement OData features like Server Driven Paging and $inlinecount. I blogged about it here 

If you look at the definition of ODataResult<>, it has following properties,

1. Items Collection
2. NextPageLink property
3. Count

Essentially calculating Items and Count are no brainer once you have access to IQueryable however NextPageLink can be interesting as there is no default implementation.

In this post, I’m going to describe how to calculate NextPageLink property. Feel free to modify the code as per your requirement, it is merely one way of achieving the goal.

Basics:

If you think about Paging support, you are thinking of two possible parameters, Batch Size & Page Number.

Usually queries are done like pageNumber=1 & batchSize=2 for first page, pageNumber=2 & batchSize=2 for the next page and so on, resulting in request made for page from 1..N but your batchSize does not change.

Here is the complete code sample which shows you how to calculate the NextPageLink.

 public static Uri CalculateNextPageLink(
            HttpRequestMessage request,
            int resultLimit)
        {
            if (resultLimit <= 0)
            {
                return null;
            }

            int topValue;
            int skipValue;

            var topValueRaw = request.GetQueryNameValuePairs()
                                     .FirstOrDefault(x => x.Key == "$top");
            if (!Int32.TryParse(
                topValueRaw.Value,
                out topValue))
            {
                return null;
            }

            var skipValueRaw = request.GetQueryNameValuePairs()
                                      .FirstOrDefault(x => x.Key == "$skip");

            if (!Int32.TryParse(
                skipValueRaw.Value,
                out skipValue))
            {
                return null;
            }

            if ((topValue > resultLimit) || (topValue <= 0 || skipValue < 0))
            {
                //return the same url
                return null;
            }

            //logic
            //skip=pageIndex*pageSize
            //top=pageSize
            var stringBuilder = new StringBuilder();
            var bothSkipAndTopSupplied = (topValue != -1 && skipValue != -1);
            var lastPageIndex = skipValue/topValue;
            //int lastPageNumber = lastPageIndex+1;

            foreach (var keyValue in request.GetQueryNameValuePairs())
            {
                switch (keyValue.Key)
                {
                    case "$top":
                        stringBuilder.AppendFormat("$top={0}",(bothSkipAndTopSupplied)? topValueRaw.Value: keyValue.Value);
                        break;
                    case "$skip":
                        if ((bothSkipAndTopSupplied))
                        {
                            stringBuilder.AppendFormat("$skip={0}",((lastPageIndex + 1)*topValue));
                        }
                        else
                        {
                            stringBuilder.AppendFormat("$skip={0}",keyValue.Value);
                        }
                        break;
                    default:
                        stringBuilder.Append(Uri.EscapeUriString(keyValue.Key));
                        stringBuilder.Append("=");
                        stringBuilder.Append(Uri.EscapeDataString((keyValue.Value)));
                        break;
                }

                stringBuilder.Append("&");
            }

            stringBuilder.Remove(
                stringBuilder.Length - 1,
                1);

            return new UriBuilder(request.RequestUri)
            {
                Query = stringBuilder.ToString()
            }.Uri;
        }
Advertisements

3 thoughts on “WebAPI: Calculating NextPageLink for ODataResult<>

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s