Sunday, April 10, 2016

Key values in CRM Lookup fields

I have been working with CRM for nearly 9 years but I have never been aware of the “Key Values” available in the lookup control. Generally, when we retrieve the lookup control in JavaScript, we use code similar to the following :
 lookupFieldObject ='parentaccountid');   
 if (lookupFieldObject.getValue() != null) {   
 entityId = lookupFieldObject.getValue()[0].id;   
 entityName = lookupFieldObject.getValue()[0].entityType;   
 entityLabel = lookupFieldObject.getValue()[0].name;   
 What are the key values for lookup control?
If you select the lookup entity on a form, the lookup control also contains a collection of key values that have other fields from the lookup entity. The screenshot below displays the key values available for an account lookup, when I select a parent account from a contact form.
The screenshot displays the collection of other account attributes such as abn, address1state, address1_city, primarycontactid, telephone 1, etc. I did not know that these values were also available for a lookup control. Sometimes we need to retrieve the other attributes of the lookup entity and these key values can be used to retrieve them, instead of making an additional call.
Where are these values coming from?
After doing a bit of research, we have found that these attributes/values are coming from the lookup view of the entity.
Here is the lookup view of the account entity in my system.
These are the same fields as shown in the Key Values collection in the screen shot above.
Now to the bad news. These key values are not available all the time. These values are only available if you select the value manually from the form. These values won’t be available if the lookup value is set via code or a workflow. My colleague, Mr. Davey has an explanation, that these values get cached when we select the lookup control on the form. That sounds like a good explanation.

Tuesday, April 5, 2016

A bit more about SDK “Merge” message in CRM plugins

One of our clients is using auto numbering on contact records. A few days ago, they reported to have duplicates in the system. So I started the investigation, I could not believe that this could happen in our solution. But what I had found out was that those duplicates were generated as a part of the "Merge" functionality available in CRM. Every time users "Merge" the customer and choose the subordinate's customer number to come across, it will override the master record's customer number with the subordinate record's number.

So we decided to write a plugin that will stop the users from overriding the master record's customer number.
The  context.InputParameters  collection of the merge message contains 3 of the following objects
  1. Target ( entity reference of the master record)
  2. SubordinateId ( guid of the subordinate record)
  3. UpdateContent ( temporary entity that contains the attribute that will be passed to the master record).

The following example does not use the SubordinateId object. We are only using Target and UpdateContent entity. Like any other plugin entity, the "UpdateContent" entity only contains attributes that will be updated in the master record.
 protected void ExecutePreCustomerMerge(LocalPluginContext localContext)  
       if (localContext == null)  
         throw new ArgumentNullException("localContext");  
       IPluginExecutionContext context = localContext.PluginExecutionContext;  
       ITracingService trace = localContext.TracingService;  
       IOrganizationService service = localContext.OrganizationService;  
       // if the sdk message is merge  
       if (context.MessageName.Equals("merge", StringComparison.InvariantCultureIgnoreCase))  
         //get the merged entity  
         Entity updateContentData = context.InputParameters["UpdateContent"] as Entity;  
         //if the merged record is null then do nothing  
         if (updateContentData == null) { return; }  
           //get the customer number of merged record  
           string mergedCustNumber = updateContentData.GetAttributeValue<string>("custNumber");  
           if (mergedCustNumber == null) return;  
             // if the merged CustNumber is not null retrieve the CustNumber of the master record to display in the message  
             // get the master entity reference  
             EntityReference targetReference = (EntityReference)context.InputParameters["Target"];  
             //trace.Trace("entity reference " + targetReference.LogicalName.ToString());  
             //retrieve the CustNumber number of the master entity  
             Entity target = service.Retrieve(targetReference.LogicalName, targetReference.Id, new ColumnSet("custNumber"));  
             string masterCustNumber = target.GetAttributeValue<string>("custNumber");  
             throw new InvalidPluginExecutionException("You cannot update the CustNumber of the Master record. Master CustNumber :" + masterCustNumber + " and New CustNumber :" + mergedCustNumber);  

Some Other Observations
When I tested this plugin in CRM2013 roll up 2, I did not receive the message thrown using InvalidPuginExecutionException. Instead, I received the following message:
I think it is a bug in CRM2013, that is now fixed in CRM2013 SP1.

When I tested the same plugin on CRM2013 SP1 UR3, It displays the proper message, as thrown by the InvalidPuginExecutionException.