locked
CRM 2013: SOAP no longer works, and I am having a hard time understanding the SDK RRS feed

  • Question

  • Hi there,

    I used to have a JScript in CRM 2011 which used to change the text inside a lookup to show another field of the related entity in question.

    For example, suppose I have a lookup for a contact in a given entity. Normally the lookup would show the contact's full name. With this script, I could show the contact's nickname in the lookup instead.

    The objective of such script is to be able to localise records based on the language pack the user is running. I used to use this script to localise country names, from a country entity.

    I CRM 2011 I used to do this with a SOAP call, which used to work without any issues. However, in CRM 2013 this no longer seems to work as expected. I understand from reading the JScript that SOAP as we used to do in CRM 2011 is no longer supported, so we must update it. Thing is, I can't relate to the SDK examples as I find them overly complex when comparing to my simple script, which is as follows:

    function submitCountryName(fieldName) {Xrm.Page.getAttribute(fieldName).setSubmitMode("always");}
    
    function fetchCountryName(fieldName) {
    
        Xrm.Page.getAttribute(fieldName).setSubmitMode("never");
        var currentUserLcid = Xrm.Page.context.getUserLcid();
        var entityName="pmdci_country";
        var lookupObject = Xrm.Page.getAttribute(fieldName);
        var lookupid;
        var localisedName;
    	
        if (lookupObject != null) {
            var lookUpObjectValue = lookupObject.getValue();
            if ((lookUpObjectValue != null)) {
                lookupid = lookUpObjectValue[0].id;
    
    var authenticationHeader = GenerateAuthenticationHeader();
    // Prepare the SOAP message.
    var xml = "<?xml version='1.0' encoding='utf-8'?>"+ 
    "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'"+
    " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'"+
    " xmlns:xsd='http://www.w3.org/2001/XMLSchema'>"+ 
    authenticationHeader+ 
    "<soap:Body>"+ 
    "<Retrieve xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+ 
    "<entityName>pmdci_country</entityName>"+ 
    "<id>"+lookupid +"</id>"+ 
    "<columnSet xmlns:q1='http://schemas.microsoft.com/crm/2006/Query' xsi:type='q1:ColumnSet'>"+ 
    "<q1:Attributes>"+ 
    "<q1:Attribute>pmdci_name_"+currentUserLcid+"</q1:Attribute>"+ 
    "</q1:Attributes>"+ 
    "</columnSet>"+ 
    "</Retrieve>"+ 
    "</soap:Body>"+ 
    "</soap:Envelope>";
    // Prepare the xmlHttpObject and send the request.
    var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
    xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
    xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Retrieve");
    xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    xHReq.setRequestHeader("Content-Length", xml.length);
    xHReq.send(xml);
    // Capture the result.
    var resultXml = xHReq.responseXML;
    
    // Check for errors.
    var errorCount = resultXml.selectNodes('//error').length;
    if (errorCount != 0)
    {
     var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
     alert(msg);
    }
    // Display the retrieved value.
    else {
    var errorCount = resultXml.selectNodes("//q1:pmdci_name_"+currentUserLcid).length;
    if (errorCount != 0) {
    localizedName = resultXml.selectSingleNode("//q1:pmdci_name_"+currentUserLcid).nodeTypedValue;
    var newLookupValue = new Array();
    newLookupValue[0] = new Object();
    newLookupValue[0].id = lookupid;
    newLookupValue[0].name = localizedName;
    newLookupValue[0].entityType = "pmdci_country";
    Xrm.Page.getAttribute(fieldName).setValue(newLookupValue);
    }}
    
            }
        }
    
    }

    Could someone please advise? Is that something I can do similarly to this? Perhaps an update to soap:Envelope xmlns:soap, Retrieve and SetRequestHeader?

    Thanks in advance for the help.

    Regards,
    P.

    Tuesday, November 5, 2013 11:17 PM

Answers

  • Hi pmdci,
    I think this will work:

    var countryLocalizedName = retrievedCountry['pmdci_name_'+ currentUserLcid];

    It's saturday night and I don't have a CRM environment to try the code, hope this works :)
    and please mark as answered if works :)


    My blog: www.crmanswers.net - Rockstar 365 Profile


    • Edited by Guido PreiteMVP Saturday, November 9, 2013 10:01 PM
    • Proposed as answer by Guido PreiteMVP Saturday, November 9, 2013 10:13 PM
    • Marked as answer by pmdci Saturday, November 9, 2013 10:13 PM
    Saturday, November 9, 2013 10:00 PM

All replies

  • Hi,
    you can use the REST endpoint, will be cross-browser compatible and will work for CRM 2011 and 2013.

    You can adapt the example that I wrote in my blog:

    http://www.crmanswers.net/2013/07/set-accounts-primary-contact-as.html

    or this

    http://www.crmanswers.net/2013/04/get-current-users-full-name-with.html


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Wednesday, November 6, 2013 12:01 AM
  • Hi,

    Thank you for the help. However I am looking at your examples and I noticed that in the following line:

     accountRequest.open("GET", ODataPath + "/AccountSet(guid'" + accountId + "')", false);

    The keyword AccountSet points to the entity in question. My question is around the Set bit so I was wondering that in the case of my custom entity if it would be called pmdci_countrySet or simply pmdci_country.

    Regards,

    P.

    Saturday, November 9, 2013 7:20 PM
  • Hi,
    it's always entity schema name + Set, so in your case pmdci_countrySet

    My blog: www.crmanswers.net - Rockstar 365 Profile

    Saturday, November 9, 2013 7:23 PM
  • Hi Guido,

    I tried this code as per your guidance, but unfortunately I am getting a JScript error:

    Field:window
    Event:onload
    Error:undefined

    The line that has the error is the following:

    countryRequest.open("GET", ODataPath + "/pmdci_countrySet(guid'" + pmdci_countryId  + "')", false); 

    Any ideas what I am doing wrong?

    Regards,
    P.

    Saturday, November 9, 2013 8:41 PM
  • did you define the variable pmdci_countryId before? it must be the same value as lookupid variable in your original code.

    If still have problems please post the full code.


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Saturday, November 9, 2013 8:47 PM
  • Hi,

    pmdci_countryId is the primary key of the Country entity. In fact I am using the CRM 2011 OData query designer for some tests, and the following query works:

    http://rythar:5555/DynamicsCRMSandbox/xrmservices/2011/OrganizationData.svc/pmdci_countrySet?$select=pmdci_countryId

    Saturday, November 9, 2013 8:49 PM
  • that piece of code doesn't consider the primary key name, it's only a variable name (for example you can write also goofy as name), please post your full code.

    My blog: www.crmanswers.net - Rockstar 365 Profile

    Saturday, November 9, 2013 8:51 PM
  • Ciao Guido,

    Here is the full code

    function testOdata() {
        var currentUserLcid = Xrm.Page.context.getUserLcid();
        var serverUrl;
        if (Xrm.Page.context.getClientUrl !== undefined) {
            serverUrl = Xrm.Page.context.getClientUrl();
        } else {
            serverUrl = Xrm.Page.context.getServerUrl();
        }
    
        var ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc"; 
        var countryRequest = new XMLHttpRequest();
    alert('debug alert #1');	
        countryRequest.open("GET", ODataPath + "/pmdci_countrySet(guid'" + pmdci_countryId  + "')", false); 
    alert('debug alert #2');
        countryRequest.setRequestHeader("Accept", "application/json"); 
    alert('debug alert #3');
        countryRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    alert('debug alert #4');
        countryRequest.send();
    alert('debug alert #5');
        if (countryRequest.status === 200) {
            var retrievedCountry = JSON.parse(countryRequest.responseText).d; 
            var countryLocalizedName = retrievedCountry.pmdci_name_ + currentUserLcid;
            // return countryLocalizedName;
            alert(countryName);
        }
        else {
            return "error";
        }
    }

    Regards,
    P.

    Saturday, November 9, 2013 8:53 PM
  • please test this code, read carefully the comments:

    function testOdata() {
    var fieldName = ""; // here you need to put the lookup name that contains the country
    var lookup = Xrm.Page.getAttribute(fieldName).getValue();
    if (lookup != null) {
       var pmdci_countryId = lookup[0].id; // now pmdci_countryId is defined
    
        var currentUserLcid = Xrm.Page.context.getUserLcid();
        var serverUrl;
        if (Xrm.Page.context.getClientUrl !== undefined) {
            serverUrl = Xrm.Page.context.getClientUrl();
        } else {
            serverUrl = Xrm.Page.context.getServerUrl();
        }
    
        var ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc"; 
        var countryRequest = new XMLHttpRequest();
        alert('debug alert #1');	
        countryRequest.open("GET", ODataPath + "/pmdci_countrySet(guid'" + pmdci_countryId  + "')", false); 
        alert('debug alert #2');
        countryRequest.setRequestHeader("Accept", "application/json"); 
        alert('debug alert #3');
        countryRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        alert('debug alert #4');
        countryRequest.send();
        alert('debug alert #5');
        if (countryRequest.status === 200) {
            var retrievedCountry = JSON.parse(countryRequest.responseText).d; 
            //var countryLocalizedName = retrievedCountry.pmdci_name_ + currentUserLcid;
    		// you can't create the field name in this way, please for now test with a userlcid you already know, for example 1033 or a lcid that exists
    		var countryLocalizedName = retrievedCountry.pmdci_name_1033;
            alert(countryLocalizedName);
        }
        else {
            return "error";
        }
    }
    }


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Saturday, November 9, 2013 9:06 PM
  • Guido,

    the code works perfectly. Now I must ensure that the countryLocalizedName that is based on the currentUserLcid variable. How do I do that?

    Regards,
    P.

    Saturday, November 9, 2013 9:13 PM
  • Now the only way that come up in my mind is to use a switch condition, something like:

    var countryLocalizedName = "";
    switch(currentUserLcid) {
       case 1033: countryLocalizedName = retrievedCountry.pmdci_name_1033; break;
       case 1040: countryLocalizedName = retrievedCountry.pmdci_name_1040; break;
       // other conditions here
    }

    is a bit ugly but works.


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Saturday, November 9, 2013 9:22 PM
  • OMG... This worse than ugly, to use a switch would be grotesque.

    There is NO REASON why the code I've proposed to append the currnetUserLcid shouldn't work within the JScript logic. Yet as you well said, it doesn't work (it returns NaN instead).

    No I will had to add over 30 lines of code because of this... If I had any doubts that CRM 2013 is bad for developers, I guess this sets it. 

    :(

    Saturday, November 9, 2013 9:28 PM
  • the reason is that you can't build dynamically variable names with javascript, in your original code you build a string with lcid, not calling a variable.
    Maybe a workaround is the following code, but I didn't test it, however if I find a more elegant way to do this, I will post here.

    var countryLocalizedName = window['retrievedCountry.pmdci_name_'+ currentUserLcid];


    My blog: www.crmanswers.net - Rockstar 365 Profile

    Saturday, November 9, 2013 9:47 PM
  • Hi Guido,

    Unfortunately it doesn't seem to work and the alert shows 'undefined'.

    Using a switch would be really bad as I have about 40 fields...

    there MUST be a way?! :(

    Saturday, November 9, 2013 9:52 PM
  • Hi pmdci,
    I think this will work:

    var countryLocalizedName = retrievedCountry['pmdci_name_'+ currentUserLcid];

    It's saturday night and I don't have a CRM environment to try the code, hope this works :)
    and please mark as answered if works :)


    My blog: www.crmanswers.net - Rockstar 365 Profile


    • Edited by Guido PreiteMVP Saturday, November 9, 2013 10:01 PM
    • Proposed as answer by Guido PreiteMVP Saturday, November 9, 2013 10:13 PM
    • Marked as answer by pmdci Saturday, November 9, 2013 10:13 PM
    Saturday, November 9, 2013 10:00 PM
  • It worked!!!

    thanks a Million Guido! you saved me!

    Grazie mille! Kudos to you.

    Regards,
    P.

    Saturday, November 9, 2013 10:05 PM