Tuesday, November 1, 2016

Use FetchXML to Retrieve Data from MS CRM 2016 using Web API

With Web API in MS CRM, we are retrieve data using FetchXML.
Easy way to construct FetchXML queries are using advanced find in CRM, you can create query in advanced find, add columns, define sorting and then download FetchXML.
Once your FetchXML is ready, you can use this FetchXML in web API to retrieve data from CRM.
Here is sample code for how to execute FetXML and get values from FetchXML result set

ExecuteFetchXML: function () {      
        var accountFetchXML = ['< fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">' +
            '< entity name="account">' +
            '< attribute name="name" />' +
            '< attribute name="accountid" />' +
            '< attribute name="numberofemployees" />' +
            '< attribute name="processid" />' +
            '< attribute name="donotpostalmail" />' +
            '< attribute name="statuscode" />' +
            '< attribute name="statecode" />' +
            '< attribute name="telephone1" />' +
            '< attribute name="ownerid" />' +
            '< attribute name="description" />' +
            '< attribute name="primarycontactid" />' +
            '< attribute name="address1_longitude" />' +
            '< attribute name="exchangerate" />' +
            '< attribute name="createdon" />' +
            '< attribute name="openrevenue" />' +
            '< attribute name="industrycode" />' +
            '< attribute name="shippingmethodcode" />' +
            '< order attribute="name" descending="false" />' +
            '< filter type="and">' +
               '< condition attribute="industrycode" operator="not-null" />' +
            '</ filter>' +
            '< link-entity name="contact" from="contactid" to="primarycontactid" visible="false" link-type="outer" alias="prmContact">' +
               '< attribute name="telephone3" />' +
               '< attribute name="spousesname" />' +
               '< attribute name="ownerid" />' +
               '< attribute name="gendercode" />' +
               '< attribute name="description" />' +
               '< attribute name="createdby" />' +
               '< attribute name="address1_latitude" />' +
               '< attribute name="exchangerate" />' +
               '< attribute name="createdon" />' +
               '< attribute name="annualincome" />' +
             '</ link-entity>' +
           '</ entity>' +
         '</ fetch>'].join('');

        var encodedFetchXML = encodeURIComponent(accountFetchXML);

        var req = new XMLHttpRequest();
        req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/accounts?fetchXml=" + encodedFetchXML, true);
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Prefer", "odata.include-annotations=\"OData.Community.Display.V1.FormattedValue\"");
        req.onreadystatechange = function () {
          if (this.readyState === 4) {
            req.onreadystatechange = null;
          if (this.status === 200) {

            var results = JSON.parse(this.response);
              for (var i = 0; i < results.value.length; i++) {                        
               var accountDetails = results.value[i];

               //Single Line Text
               var nameValue = accountDetails['name'];
               var telephone1Value = accountDetails['telephone1'];

               //UniqueIdentifier
               var accountidValue = accountDetails['accountid'];
               var processidValue = accountDetails['processid'];


               //Whole Number
               var numberofemployeesValue = accountDetails['numberofemployees'];

               //Two Option
               var donotpostalmailValue = accountDetails['donotpostalmail'];
               var donotpostalmailTextValue = accountDetails['donotpostalmail@OData.Community.Display.V1.FormattedValue'];

               //Status Reason
               var statuscodeValue = accountDetails['statuscode'];
               var statuscodeTextValue = accountDetails['statuscode@OData.Community.Display.V1.FormattedValue'];

               //Status
               var statecodeValue = accountDetails['statecode']; //Status
               var statecodeTextValue = accountDetails['statecode@OData.Community.Display.V1.FormattedValue'];

               //Owner
               var owneridValue = accountDetails['_ownerid_value'];
               var OwnerName = accountDetails["_ownerid_value@OData.Community.Display.V1.FormattedValue"]

               //Multiple Line
               var descriptionValue = accountDetails['description'];

               //Lookup
               var primarycontactidValue= accountDetails['_primarycontactid_value'];
               var primarycontactidName = accountDetails['_primarycontactid_value@OData.Community.Display.V1.FormattedValue'];

                  //Floating Point Number
                  var address1_longitudeValue= accountDetails['address1_longitude'];

                  //Decimal
                  var exchangerateValue = accountDetails['exchangerate'];

                  //Date Time
                  var createdonValue = accountDetails['createdon'];

                  //Currency
                  var openrevenueValue = accountDetails['openrevenue'];

                  //Option set
                  var industrycodeValue = accountDetails['industrycode'];
                  var industrycodeTextValue = accountDetails['industrycode@OData.Community.Display.V1.FormattedValue'];

                 //Contact - Linked entity data
                 //Single Line Text
                 var prmContact_telephone3Value = accountDetails['prmContact_x002e_telephone3'];
                 var prmContact_spousesnameValue = accountDetails['prmContact_x002e_spousesname'];

                 //Owner
                 var prmContact_owneridValue = accountDetails['prmContact_x002e_ownerid'];

                 //Option set
                 var prmContact_gendercodeValue = accountDetails['prmContact_x002e_gendercode'];
                 var prmContact_gendercodeTextValue = accountDetails['prmContact_x002e_gendercode@OData.Community.Display.V1.FormattedValue'];

                 //Multiple Line
                 var prmContact_descriptionValue = accountDetails['prmContact_x002e_description'];

                 //Lookup
                 var prmContact_createdbyValue = accountDetails['prmContact_x002e_createdby'];

                 //Floating Point Number
                 var prmContact_address1_latitudeValue = accountDetails['prmContact_x002e_address1_latitude'];

                 //Decimal
                 var prmContact_exchangerateValue = accountDetails['prmContact_x002e_exchangerate'];

                 //Date Time
                 var prmContact_createdonValue = accountDetails['prmContact_x002e_createdon'];

                 //Currency
                 var prmContact_annualincomeValue = accountDetails['prmContact_x002e_annualincome'];

                    }
                }
                else {
                    alert(this.statusText);
                }
            }
        };
        req.send();
    },

Remember when using fetchXML query in WEB API
1.      You need to URL encoded FetchXML
2.      With FetchXML you can apply paging by setting page and count attribute of the fetch element.


10 comments:

  1. Hi Mahadeo,

    I have similar kind of requirement where the sub-gird has to get data dynamically based on the selected done in the drop-down.

    For example if there are two drop downs country and state when user selects any country then corresponding states should be displayed and then on selecting the state then all the accounts from that region should populate in the sub-grid.

    Can you let me know how to achieve it with fetch-XML.

    ReplyDelete
    Replies
    1. Hi Ravi,
      To get states for selected country, if you have Picklist / Dropdowns then you can use dependentOption sets.

      You will find sample code for dependent option set

      https://msdn.microsoft.com/en-us/library/gg594433.aspx

      and to show account for selected state in sub-grid try

      https://mahadeomatre.blogspot.com/2015/02/dynamically-filter-form-sub-grid-to.html

      Delete
  2. Thanks a lot! Looked everywhere for this info..

    ReplyDelete
  3. HI Mahadeo,

    I am new in crm 2016 and fetch xml,
    please help me where to put this javascript and get the data.
    Please share step by step guide or sample code.

    Regards
    Surbhi

    ReplyDelete
    Replies
    1. Hi Surbhi, I believe the code above is C# in your case you would need to right a javascript request. Here is a sample request performed in JavaScript, you can pass whatever fetchXml you want as a string (make sure to format it like the above code).


      function executeXMLHttpRequestAsynchronously(theURL, callBack) {
      console.log(Xrm.Page.context.getClientUrl() + "/api/data/v8.2/" + encodeURI(theURL));
      var req = new XMLHttpRequest();
      req.open("GET", ( Xrm.Page.context.getClientUrl() + "/api/data/v8.2/" + encodeURI(theURL)), true);
      req.setRequestHeader("OData-MaxVersion", "4.0");
      req.setRequestHeader("OData-Version", "4.0");
      req.setRequestHeader("Accept", "application/json");
      req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
      req.setRequestHeader("Prefer", "odata.include-annotations=\"*\",odata.maxpagesize=5000");

      req.onreadystatechange = function () {
      if (this.readyState == 4) { //Request is ready
      req.onreadystatechange = null;
      if (this.status == 200) { //Request is good
      callBack(req);
      }
      else { //Request failed
      Xrm.Page.ui.setFormNotification("There was an error while creating the request, please contact your System Admin.", "ERROR", "REST_FAILED");
      }
      }
      };
      req.send(null);
      }

      Delete
  4. Hi Surbhi, I believe the code above is C# in your case you would need to right a javascript request. Here is a sample request performed in JavaScript, you can pass whatever fetchXml you want as a string (make sure to format it like the above code).


    function executeXMLHttpRequestAsynchronously(theMethod, theURL, callBack) {
    console.log(Xrm.Page.context.getClientUrl() + "/api/data/v8.2/" + encodeURI(theURL));
    var req = new XMLHttpRequest();
    req.open(theMethod, ( Xrm.Page.context.getClientUrl() + "/api/data/v8.2/" + encodeURI(theURL)), true);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\",odata.maxpagesize=5000");

    req.onreadystatechange = function () {
    if (this.readyState == 4) { //Request is ready
    req.onreadystatechange = null;
    if (this.status == 200) { //Request is good
    callBack(req);
    }
    else { //Request failed
    Xrm.Page.ui.setFormNotification("There was an error while creating the request, please contact your System Admin.", "ERROR", "REST_FAILED");
    }
    }
    };
    req.send(null);
    }

    ReplyDelete
  5. Hello Sir,

    I am new to Dynamics 365 and learning it. What I want to try is to use Web API to -
    1. Fetch schema of CRM Metadata.
    2. Perform CRUD operations using Web API and the data should replicate in CRM too.

    Can you please suggest some sample code with best possible approach to do this?

    Thank you in advance sir.

    ReplyDelete
  6. I found that using the above in a javascript API call, there is no need to use "_x002e_" (prmContact_x002e_exchangerate). You can use the normal period (prmContact.exchangerate).

    ReplyDelete
  7. Excellent and very exciting site. Love to watch. Keep Rocking. retrieve data from USB flash drive

    ReplyDelete