Tuesday, November 19, 2019

Paging FetchXml Queries in Dynamic CRM


When paging FetchXML queries, things are a little bit different in comparison to Rest API:
  • Item count per page is specified by setting the count attribute in the fetch node.
  • The page number is specified in the page attribute of the fetch node. To retrieve the next page, update the page number to the next page.
  • Need to evaluate @Microsoft.Dynamics.CRM.fetchxmlpagingcookie attribute when verifying if next set of records are available to be fetched



CODE EXAMPLE


var serverUrl = Xrm.Page.context.getClientUrl();

function getallRecords(OriginalQueryUrl)
{
// we return an object with a similar structure
var allRecords = new Object();
allRecords.results = new Array();

// we loop until we have an url to query
var queryUrl = OriginalQueryUrl;

// Initially defining the PageNumber
var pageNumber = 1;

while (queryUrl != null)
{
    // we build the request
    var httpRequest = new XMLHttpRequest();
    httpRequest.open("GET", queryUrl, false); // false = synchronous request
    httpRequest.setRequestHeader("Accept", "application/json");
    httpRequest.setRequestHeader("OData-MaxVersion", "4.0");
    httpRequest.setRequestHeader("OData-Version", "4.0");
    httpRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    httpRequest.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
    httpRequest.send();

    if (httpRequest.status === 200)
    {
        var parsedResults = JSON.parse(httpRequest.responseText);

        if (parsedResults != null && parsedResults.value != null)
        {
            // we add the results to our object
            for (var i = 0; i < parsedResults.value.length; i++) {
                allRecords.results.push(parsedResults.value[i]);
            }
               
            // check if there are more records and set the new url, otherwise we set to null the url
            if (parsedResults["@Microsoft.Dynamics.CRM.fetchxmlpagingcookie"] != null 
                && 
                parsedResults["@Microsoft.Dynamics.CRM.fetchxmlpagingcookie"] != 'undefined')
            {
             pageNumber++;
            // Updating Query with page number to fetch Next set of records.
queryUrl = queryUrl.replace("page='" + (pageNumber-1) +"'","page='"+ pageNumber.toString()+"'")                   
            }
            else
            {
                queryUrl = null;
            }
        }
    }
    else
    {
        // if the request has errors we stop and return a null result
        queryUrl = null;
        allRecords = null;
    }
}
return allRecords;
}



1 comment:

NoviceOfDynamics365PowerApps said...

Thanks Vipin. This was really useful. Had updated my code as per async promise pattern. The core logic remains the same. Thanks so much again. The WebApi seems to have stopped returning the @odata.nextLink for the fetchxml queries via crm webapi.
In addition, I had used "@Microsoft.Dynamics.CRM.morerecords" boolean value as well for the conditional check which is sent as true in case of more records.