Revised SOAP.queryAll and SOAP.fetchMore to allow sort order (asc or desc) parameter to be passed

May 1, 2013 at 3:24 PM
Edited May 1, 2013 at 3:25 PM
I revised the SOAP.queryAll and SOAP.fetchMore methods to allow sort order (asc or desc) parameter to be passed. Below is the updated code for the queryAll method (the moreFetchXml var of the fetchMore method should mirror this as well):
var queryAll = function (queryOptions, callback) {
        ///<summary>
        /// Sends synchronous/asynchronous request to do a queryAll request. This is to return all records (>5k+).
        /// Consider Performance impact when using this method.
        ///</summary>
        ///<param name="queryOptions" type="Object">
        /// A JavaScript Object with properties corresponding to the queryByAttribute Criteria
        /// that are valid for queryByAttribute operations.
        /// queryOptions.entityName is a string represents the name of the entity
        /// queryOptions.attributes is a array represents the attributes of the entity to query
        /// queryOptions.values is a array represents the values of the attributes to query
        /// queryOptions.columnSet is a array represents the attributes of the entity to return
        /// queryOptions.orderBy is a array represents the order conditions of the results
        /// queryOptions.orderDescending is a boolean represents the sort order conditions of the results
        /// </param>
        ///<param name="callback" type="Function">
        /// A Function used for asynchronous request. If not defined, it sends a synchronous request.
        /// </param>
        var entityName = queryOptions.entityName;
        var attributes = queryOptions.attributes;
        var values = queryOptions.values;
        var columnSet = queryOptions.columnSet;
        var orderBy = queryOptions.orderBy || '';
        var orderDescending = queryOptions.orderDescending || '';

        attributes = isArray(attributes) ? attributes : [attributes];
        values = isArray(values) ? values : [values];
        orderBy = (!!orderBy && isArray(orderBy)) ? orderBy : [orderBy];
        orderDescending = (!!orderDescending && isArray(orderDescending)) ? orderDescending : [orderDescending];
        columnSet = (!!columnSet && isArray(columnSet)) ? columnSet : [columnSet];

        for (var i = 0; i < values.length; i++) {
            values[i] = encodeValue(values[i]);
        }

        var fetchXml =
                [
                    "<fetch mapping='logical'>",
                    "   <entity name='", entityName, "'>",
                           joinArray("<attribute name='", columnSet, "' />"),
                           joinArray("<order attribute='", orderBy, "'"),
                           joinArray(" descending='", orderDescending, "' />"),
                    "      <filter>",
                              joinConditionPair(attributes, values),
                    "      </filter>",
                    "   </entity>",
                    "</fetch>"
                ].join("");

        var msgBody = "<query i:type='a:FetchExpression' xmlns:a='http://schemas.microsoft.com/xrm/2011/Contracts'>" +
                            "<a:Query>" +
                                ((typeof window.CrmEncodeDecode != 'undefined') ? window.CrmEncodeDecode.CrmXmlEncode(fetchXml) : crmXmlEncode(fetchXml)) +
                            "</a:Query>" +
                        "</query>";
        var async = !!callback;

        return doRequest(msgBody, "RetrieveMultiple", !!callback, function (resultXml) {

            //Logic here is inspired by http://nishantrana.wordpress.com/2012/09/11/paging-cookie-is-required-when-trying-to-retrieve-a-set-of-records-on-any-high-pages-error-in-crm-2011/

            var fetchResult;
            var moreRecords;

            if ($(resultXml).find("a\\:Entities").length != 0) {
                fetchResult = $(resultXml).find("a\\:Entities").eq(0)[0];
            } else {
                fetchResult = $(resultXml).find("Entities").eq(0)[0]; //chrome
            }

            if ($(resultXml).find("a\\:MoreRecords").length != 0) {
                moreRecords = $(resultXml).find("a\\:MoreRecords").eq(0)[0].firstChild.text === "true";
            } else {
                moreRecords = $(resultXml).find("MoreRecords").eq(0)[0].firstChild.text === "true"; //chrome
            }

            var fetchResults = [];

            for (var ii = 0; ii < fetchResult.childNodes.length; ii++) {
                var entity = new businessEntity();

                entity.deserialize(fetchResult.childNodes[ii]);
                fetchResults.push(entity);
            }

            if (moreRecords) {
                var pageNumber = 2;
                var pageCookie;
                if ($(resultXml).find("a\\:PagingCookie").length != 0) {
                    pageCookie = $(resultXml).find("a\\:PagingCookie").eq(0)[0].firstChild.text.replace(/\"/g, '\'').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&quot;');
                } else {
                    pageCookie = $(resultXml).find("PagingCookie").eq(0)[0].firstChild.text.replace(/\"/g, '\'').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&quot;');
                }
                fetchMore(queryOptions, pageNumber, pageCookie, fetchResults);
            }

            if (!async)
                return fetchResults;
            else
                callback(fetchResults);
            // ReSharper disable NotAllPathsReturnValue
        });
    };
Coordinator
May 15, 2013 at 10:30 AM
Hi There.

Thanks for doing this. I will have a look at the code soon.

Regards,
Jaimie
May 27, 2013 at 2:22 PM
Codeplex is not very good for collaborating. Can you, please, transfer development to GitHub and use Codeplex for stable releases?