Monday, 15 August 2016

Retrieve data from configuration records in Dynamics CRM using JavaScript

In most of my projects, we have a configuration record in Dynamics CRM from where we retrieve configuration values. Here is a code snippet that will retrieve the configuration data based on the name supplied.

var common = common || {};

/*
Purpose : Get the configuration record value whose name has been provided
*/
common.getValueFromConfigurationRecordBasedOnName = function(configurationRecordName, isAsync) {
    if (configurationRecordName) {
        console.log("The configuration record name is: " + configurationRecordName);
        var oDataSet = "contoso_configuration";
        var options = "$select=contoso_Value&$filter=contoso_name eq '" + configurationRecordName + "'";
        var configurationDataRecordValue;
        if (isAsync == null) {
            isAsync = false;
        }
        SDK.REST.retrieveMultipleRecords(oDataSet, options, function (response) {
            configurationDataRecordValue = common.getValueFromConfigurationRecordBasedOnNameHelper(response);
        }, SDK.REST.errorCallback, function () {
            console.log("Retrieve multiple call for retrieving configuration record data completed");
        }, isAsync);
        return configurationDataRecordValue;
    } else {
        console.log("The configuration record name has not been provided.");
        return null;
    }
}

/*
Purpose : Helper function to process the response to get the configuration record value whose name has been provided
*/
common.getValueFromConfigurationRecordBasedOnNameHelper = function(response) {
    if (response) {
        console.log("The number of responses retrieved is: " + response.length);
        if (response.length > 0) {
            return response[0].contoso_Value;
        } else {
            console.log("There is no configuration data record with the given name");
        }
    } else {
        console.log("There is null response retrieved as part of the ODATA call.");
    }

    return null;
}

Here I have used the SDK.REST JavaScript library (a JS file) (find it here: https://msdn.microsoft.com/en-us/library/gg334427(v=crm.7).aspx#BKMK_SDKREST ) which also comes with the SDK. This helps avoid writing code to trigger the AJAX request while making the ODATA query. I have added an additional parameter called "isAsync" that mentions whether the request needs to be asynchronous or not by modifying the method in the SDK.REST file itself. This is required as in some cases we need to retrieve the data in a synchronous manner to drive the correct behavior.

This is the updated method declaration:

retrieveMultipleRecords: function (type, options, successCallback, errorCallback, OnComplete, isAsync) {
        ///<summary>
        /// Sends an asynchronous request to retrieve records.
        ///</summary>
        ///<param name="type" type="String">
        /// The Schema Name of the Entity type record to retrieve.
        /// For an Account record, use "Account"
        ///</param>
        ///<param name="options" type="String">
        /// A String representing the OData System Query Options to control the data returned
        ///</param>
        ///<param name="successCallback" type="Function">
        /// The function that will be passed through and be called for each page of records returned.
        /// Each page is 50 records. If you expect that more than one page of records will be returned,
        /// this function should loop through the results and push the records into an array outside of the function.
        /// Use the OnComplete event handler to know when all the records have been processed.
        /// </param>
        ///<param name="errorCallback" type="Function">
        /// The function that will be passed through and be called by a failed response.
        /// This function must accept an Error object as a parameter.
        /// </param>
        ///<param name="OnComplete" type="Function">
        /// The function that will be called when all the requested records have been returned.
        /// No parameters are passed to this function.
        /// </param>
        ///<param name="isAsync" type="Boolean">
        /// Whether the operation should be asynchronously performed or not
        /// </param>
        this._stringParameterCheck(type, "SDK.REST.retrieveMultipleRecords requires the type parameter is a string.");
        if (options != null)
            this._stringParameterCheck(options, "SDK.REST.retrieveMultipleRecords requires the options parameter is a string.");
        this._callbackParameterCheck(successCallback, "SDK.REST.retrieveMultipleRecords requires the successCallback parameter is a function.");
        this._callbackParameterCheck(errorCallback, "SDK.REST.retrieveMultipleRecords requires the errorCallback parameter is a function.");
        this._callbackParameterCheck(OnComplete, "SDK.REST.retrieveMultipleRecords requires the OnComplete parameter is a function.");

        var optionsString;
        if (options != null) {
            if (options.charAt(0) != "?") {
                optionsString = "?" + options;
            }
            else { optionsString = options; }
        }
        var req = new XMLHttpRequest();
        req.open("GET", this._ODataPath() + type + "Set" + optionsString, isAsync);
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.onreadystatechange = function () {
            if (this.readyState == 4 /* complete */) {
                req.onreadystatechange = null;
                if (this.status == 200) {
                    var returned = JSON.parse(this.responseText, SDK.REST._dateReviver).d;
                    successCallback(returned.results);
                    if (returned.__next != null) {
                        var queryOptions = returned.__next.substring((SDK.REST._ODataPath() + type + "Set").length);
                        SDK.REST.retrieveMultipleRecords(type, queryOptions, successCallback, errorCallback, OnComplete);
                    }
                    else { OnComplete(); }
                }
                else {
                    errorCallback(SDK.REST._errorHandler(this));
                }
            }
        };
        req.send();
    }

I have highlighted the changes made to the original retrieve multiple method above wherever the isAsync parameter is used.

Here is how to call the original retrieve configuration method:

var incrementValue = common.getValueFromConfigurationRecordBasedOnName("increment", false);



Additionally, there is also this method that will convert the configuration data value into an array (comma character in the configuration data value acts as the delimiter in the array)

/*
Purpose     : Retrieve configuration data and convert coma seprated string into an array after trimming the white spaces at the begining and end.
*/
common.getConfigurationDataConvertedToArray = function (configName) {
    var configRecord = common.getValueFromConfigurationRecordBasedOnName(configName, false);
    var configRecordArray = [];
    if (configRecord) {
        console.log("getConfigurationDataConvertedToArray() : Value of configuration record is " + configRecord);
        configRecordArray = configRecord.split(",");
        console.log("The number of items in the record: " + configRecordArray.length);
        for (var i = 0; i < configRecordArray.length; i++) {
            if (configRecordArray[i]) {
                configRecordArray[i] = configRecordArray[i].trim();
            }
        }
    } else {
        console.log("getConfigurationDataConvertedToArray() : configuration data is null.");
    }
    return configRecordArray;
}


Let me know if the above code snippets help you. Happy Dynamics CRMing!!!

No comments:

Post a Comment