locked
count contacts RRS feed

  • Question

  • Hi,

    On the Account form I have field that counts contacts. So, if I choose Account 'Account X' in the lookup field on the Contact form I should have +1 in Count Contact field.

    However if I open the contact after that, and change the Account to 'Account Y', I need to have -1 in the Count Contact field in Account 'Account X' and +1 in the current account ('Account Y').

    How can I achieve this?

    Sunday, February 27, 2011 2:57 PM

Answers

  • Hi,

    I would vote for the plug-in approach as Jamie initially suggested as this is the most robust way to ensure the count value is correct and doesn't rely on the contact form being opened, amended & saved. Bulk edit, adding contacts to the account from within the context of the account, and record updates via a portal are just a few scenarios that spring to mind where this approach would be flawed.

    Rob


    Microsoft Certified Technology Specialist (CRM) GAP Consulting Ltd.
    Sunday, February 27, 2011 9:54 PM
    Answerer
  • I definitely agree.  The logic would be the same though.  You would use .NET and do the retrievemultiple, talley the results, and then update the account on create, update or delete of a contact record.
    Jamie Miley
    Sunday, February 27, 2011 10:19 PM
    Moderator

All replies

  • There are a couple different methods.
    1. You could register a plugin to do this on the create, update, delete of a contact to do the math and update the account.
    2. You could use soap envelopes in jscript on save to also do the same thing.

    A BIG NOTE: I would not simply do increment and decrement as this might get a bit dicey. My logic (for either method) would be to do
     a retrievemultiple request for contacts with that accountid set and then count the results that come back and set the count accordingly with an update command. Below I have slapped together a very quick example of a retrievemultiple request and below
     it an example of a update request in jscript. Not all the syntax is good practice (like iterating until you hit 1000 and have it break when you run out of records with a catch block is bad practice), but it is to give you a quick idea on how to do this sort
     of operation.

    //**** FIRST THE RETRIEVEMULTIPLE REQUEST EXAMPLE
    
    try
    {
    
    
    //create SOAP envelope 
    var xmlSoapHeader= "" + 
    "<?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\">";
    
    var xmlAuthHeader = GenerateAuthenticationHeader();
    
    var xmlSoapBody = "<soap:Body>" + 
    "<RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\"> " +
    "  <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryByAttribute\" xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" + 
    "   <q1:EntityName>contact</q1:EntityName>" + 
    "   <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" + 
    "    <q1:Attributes>" + 
    "     <q1:Attribute>contactid</q1:Attribute>" + 
    "      <q1:Attribute>attribute1</q1:Attribute>" + 
    "      <q1:Attribute>attribute2</q1:Attribute>" +
    
    "    </q1:Attributes>" + 
    "   </q1:ColumnSet>" +
    " <q1:Attributes>" + 
    " <q1:Attribute>parentcustomerid</q1:Attribute>" + 
    " </q1:Attributes>" + 
    " <q1:Values>"+ 
    " <q1:Value xsi:type=\"xsd:string\">" + crmForm.ObjectId.toString() + "</q1:Value>" + 
    " </q1:Values>" + 
    "  </query>" + 
    " </RetrieveMultiple>" +
    " </soap:Body>" + 
    "</soap:Envelope>" + 
    ""; 
    
    
    
    var xmlt = xmlSoapHeader + xmlAuthHeader + xmlSoapBody; 
    var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP"); 
    xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false); 
    xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple"); 
    xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); 
    xmlHttpRequest.setRequestHeader("Content-Length", xmlt.length); 
    xmlHttpRequest.send(xmlt); 
    var resultXml = xmlHttpRequest.responseXML.xml;
    
    
    xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async="false";
    xmlDoc.loadXML(resultXml);
    
    
      var i = 0;
    //step through entities
      do
      {
     
       
       //count your entities returned here  
         
      
      
     
      i=i+1;
     
      }
      while (i<=1000);
    }
    catch(err)
    {
     
        // do nothing means we are done updating contacts (don't end your iteration this way in real life)
     
    }
    
    
    //***********UPDATE REQUEST EXAMPLE
    //create SOAP envelope
    xmlSoapHeader= "" + 
    "<?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\">";
    
    xmlAuthHeader = GenerateAuthenticationHeader();
    //<?xml version="1.0" encoding="utf-16"?>
    xmlSoapBody = " <soap:Body>" + 
    "<Update xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\"> " +
    "  <entity xsi:type=\"new_entityname\" xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" + 
    "   <new_streetaddy>34 Market St.</new_streetaddy>" + 
    "   <new_id>c28b8aa2-f571-dc11-967c-0013722e2165</new_id>" + 
    "  </entity>" + 
    "</Update> " +
    " </soap:Body>" + 
    "</soap:Envelope>" + 
    "";
    
    xmlt = xmlSoapHeader + xmlAuthHeader + xmlSoapBody; 
    xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP"); 
    xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false); 
    xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Update"); 
    xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8"); 
    xmlHttpRequest.setRequestHeader("Content-Length", xmlt.length); 
    xmlHttpRequest.send(xmlt); 
    
    Sunday, February 27, 2011 7:17 PM
    Moderator
  • Hi Jamie,

    Thanx for the effort.. :) 

    What you suggest is, if I understood good, is to make a retrieveMultiple call on OnLoad and OnSave on the Account form (retrieving number of associated contacts) and than do an Update.

    One question though.. This means that I wont be able to see the count in Account view, unless I open and/or save the Account form? Or maybe I'm wrong?

    Sunday, February 27, 2011 8:28 PM
  •  I didn't really form up the calls for what you want, they were generic examples that I pulled from my library.   I am actually suggesting you put your scripts and calls on the onload and onsave of the CONTACT form.  Then it will change the value for the account whenever you load or save a contact, since that is when the changes happen you shouldn't have a problem and the values should be there when you open the account records.

    So you need to update the account record from the onload and onsave of the contact form using properly formed up calls.

    I hope this helps.


    Jamie Miley
    Sunday, February 27, 2011 9:17 PM
    Moderator
  • Not quite, do the calls to get the number of contacts and update the coresponding account entity using calls on the onload and onsave of the CONTACT form.  This is where the changes truely take place.  Then you don't have to worry about whether or not the information will be there prior to opening the account form.  So you are updating the account entity at the time of saving or loading a CONTACT.

    One other note.  The calls are in no way formatted for you, they are pretty generic call statements.  They obviously need to be redone for your specific case.  So don't take any stock in the entity types and such that are specified in those calls.  I pulled this from my library as it was as a generic retrievemultiple call and an update call.

    I hope this clarifies and is helpful.


    Jamie Miley
    Sunday, February 27, 2011 9:40 PM
    Moderator
  • Hi,

    I would vote for the plug-in approach as Jamie initially suggested as this is the most robust way to ensure the count value is correct and doesn't rely on the contact form being opened, amended & saved. Bulk edit, adding contacts to the account from within the context of the account, and record updates via a portal are just a few scenarios that spring to mind where this approach would be flawed.

    Rob


    Microsoft Certified Technology Specialist (CRM) GAP Consulting Ltd.
    Sunday, February 27, 2011 9:54 PM
    Answerer
  • I definitely agree.  The logic would be the same though.  You would use .NET and do the retrievemultiple, talley the results, and then update the account on create, update or delete of a contact record.
    Jamie Miley
    Sunday, February 27, 2011 10:19 PM
    Moderator