Using JScript to Link Records in an N:N Relationship

January 19, 2012 – I get lots of Dynamics CRM questions in my inbox, but rarely as well-articulated as one I received today. A question does not have to be polished to deserve an answer, but if you want it to turn, unedited, into an article, it helps. Forthwith, January’s Dynamics CRM Trick Bag “Stump the Experts” question. Calling it “Stump the Experts” makes me feel better, since I couldn’t answer it. But I’m betting that more than a few of you can, so please weigh in, in the form of comments on this post, with advice on how to programmatically link records in an N:N relationship.

Here’s the note I received:

Hi Richard,

I heard you speak at Extreme last year. I have been stumped on something and was wondering if you had time to help a noob with a weird problem. Maybe make a blog post out of it? I apologize if this is not the right way to beg for help.

We have a custom entity called a Project, from which multiple Marketing Lists hang off of it. Using javascript triggered from the Project, we want to be able to create marketing lists and associate the new marketing list with the Project. I can’t seem to figure out how to associate it with the Project. I can make the Marketing List, fill in the all the correct information, but am failing at the association with the project.

I tried using some code from here:

http://stackoverflow.com/questions/7358482/how-to-link-two-records-with-javascript-and-a-nm-relationship

to use this call:

AssociateEntities(data.ListId, “ListSet”, Xrm.Page.data.entity.getId(), “ags_projectSet”);

Am I passing the IDs incorrectly? Not sure. Is this code sensitive to there being curly brackets around the IDs? For the xml, how do you know which object to put first? Is this the wrong piece of code since I am trying to fill in a 1:N relationship instead of N:M? Any help you can give me would be awesome. Thanks.

on this function:

function AssociateEntities(id1, entityType1, id2, entityType2, relationshipName) {

    var xml;

    var resultXml;

    xml = “<Execute xmlns=’http://schemas.microsoft.com/crm/2007/WebServices’>”;

    xml += “<Request xsi:type=’AssociateEntitiesRequest’>”;

    xml += “<Moniker1><Id xmlns=’http://schemas.microsoft.com/crm/2006/CoreTypes’>” + id1 + “</Id>”;

    xml += “<Name xmlns=’http://schemas.microsoft.com/crm/2006/CoreTypes’>” + entityType1 + “</Name></Moniker1>”;

    xml += “<Moniker2><Id xmlns=’http://schemas.microsoft.com/crm/2006/CoreTypes’>” + id2 + “</Id>”;

    xml += “<Name xmlns=’http://schemas.microsoft.com/crm/2006/CoreTypes’>” + entityType2 + “</Name></Moniker2>”;

    xml += “<RelationshipName>” + relationshipName + “</RelationshipName>”;

    xml += “</Request></Execute>”;

    var xHReq = new ActiveXObject(”Msxml2.XMLHTTP”);

    xHReq.Open(”POST”, “/mscrmservices/2007/CrmService.asmx”, false);

    xHReq.setRequestHeader(”SOAPAction”,”http://schemas.microsoft.com/crm/2007/WebServices/Execute“);

    xHReq.setRequestHeader(”Content-Type”, “text/xml; charset=utf-8″);

    xHReq.setRequestHeader(”Content-Length”, xml.length);

    xHReq.send(xml);

    resultXml = xHReq.responseXML;

    if (resultXml) {

        return “success”;

    }

    else {

        return null;

    }

}

5 Comments »

  1. Jonas Rapp Said,

    January 20, 2012 @ 1:36 am

    Hi

    I guess this should do the trick.
    http://msdn.microsoft.com/en-us/library/gg309638.aspx#BKMK_AssociatingAndDisassociating

    Unfortunately, I have not entirely been able to decrypt the SDK to actually know how to write the correct syntax.
    Perhaps someone else can continue from here?

    /Jonas

  2. Richard Riddle Said,

    January 20, 2012 @ 7:12 am

    I assume because the words ListSet and ags_projectSet are used that this is CRM 2011, even though the CRM 4.0 end point is being used. Also, you have a function with 5 arguments but you only pass in 4; there’s no way it was ever going to work

    Review the associateRecord function here: http://msdn.microsoft.com/en-us/library/hh372956.aspx. It uses the updated REST interface, but works very well. The first four arguments you have are correct, and the fifth will require some digging. In CRM open Customizations and go to your Marketing List entity. In the N:N Relationship grid, you should see your Project entity. The fifth argument for the associateRecord function is what appears under the Schema Name column in that grid.

    Ensure you include the jquery and json libraries on your form as well, listed above the library which includes this code, so they are loaded first.

  3. David Berry Said,

    January 20, 2012 @ 10:08 am

    AssociateEntities is *only* appropriate for N:N relationships, and will not work for 1:N relationships. There’s another caveat to its use, however: like it’s counterpart, DisassociateEntities, you must only use it when you’re certain the records involved are not currently associated/disassociated (respectively). Any attempt to process these messages on a pair of records that already exist in the desired state will cause Web Exceptions–this doesn’t matter so much from a JS standpoint, but it can break your day from a Plugin.

    A while back, I wrote up some utility code for these messages on my blog (http://crmentropy.blogspot.com/2010/09/nn-relationship-utility-code-javascript.html) and the code validates the necessity for the desired message before making an attempt. That said, the code itself is identical in operation to the implementation your inquirer provided, so I’ll answer the last remaining question:

    No, it doesn’t matter if your GUID has braces or not. Any string that could be passed to “new Guid(str)” suffices.

    That said, if they’re still having a hard time getting the code call to work, the biggest area of problem with this message is often in getting the relationship schema name correct. The problem may not be with the code he’s using, but with the fact that his “Relationship Name” and “Relationship Entity Name” are not identical. (http://social.microsoft.com/Forums/en-US/crmdevelopment/thread/7fce1fd9-d51f-4e7e-b881-bbe1a6e1465c/) It’s a weird bug, but it probably trips more people up than we really know.

  4. Richard Knudson Said,

    January 20, 2012 @ 6:10 pm

    Jonas, Richard, David — thanks so much for the quick and authoritative responses! You’ll see from the note I received today from Mr. X that he figured it out also: once again, it was the old mixing up of the 1:Ns and N:Ns problem.

    Cheers — Richard

    Email:

    Richard-

    You know what, I think I figured it out. 1:N is different than N:M. All I had to do is fill in the lookup field on the N-side (our MarketingList) and it works fine. The N:M has an intermediary table which makes it a little harder, for the 1:N case, it’s just filling in the lookup field. Different from examples that I found on the web, which threw me off for a day, but I used the IE debugger and found the right format. Examples on the web put the lookup object as the first item in an array. I had to take out the array to make it work.

    Silly me. But thank you for being a sounding board for me. I appreciate you being kind to a stranger. Cheers!

    var newMktgList = new Object();
    <>
    newMktgList.ags_MilestoneListId = new Object();
    newMktgList.ags_MilestoneListId.Id = Xrm.Page.data.entity.getId();
    newMktgList.ags_MilestoneListId.Name = Xrm.Page.getAttribute(”ags_name”).getValue();
    newMktgList.ags_MilestoneListId.LogicalName = “ags_project”;
    createRecord(newMktgList, “ListSet”, createMktgListCompleted, createMktgListNotCompleted)

  5. CRM Software Blog Said,

    January 23, 2012 @ 7:48 pm

    CRM MVPs Reveal Best Practices: What works in CRM and Marketing Automation…

    For all the talk about aligning sales and marketing business processes with Dynamics CRM, executing on…

Leave a Comment