Friday, 20 April 2012

Programmatically change the customization for a system/custom entity in CRM 2011

Each and every entity of Dynamics CRM is having a “Formxml” that outlines the customization of the particular entity. In this blog I am going to explain you how to update the “Formxml” of any System/Custom entities.

To change customization we’ve to follow these steps.
· Retrieve formxml for that particular entity.
· Apply changes to that formxml.
· Publish updated formxml to CRM.

Here I’ve used custom entity “acm_airport” and applied changes on its formxml.
As shown in below screen shot there is a tab named as “Extra” having a section. I would like to add one more section with the same name (“Extra”) in this tab

image

Add following files in your class library project from this location “..\sdk\samplecode\cs\helpercode” once you have successfully downloaded Dynamics CRM SDK(5.0.7).
· crmservicehelpers.cs
· myorganizationcrmsdktypes.cs
· optionsets.cs

Use below code to get the fetchxml of acm_airport entity.
using System.Xml;
using System.Xml.XPath;
using Microsoft.Xrm.Sdk.Query;
 
string entityName = "acm_airport";
string tabName = "tab_Extra";
string sectionName = "section_Extra";
 
#region Retrieve Form XML
//Creates query expression to retrieve fromxml and form id for the specified object type code and form type='main'
QueryExpression myFormXml = new QueryExpression
{
EntityName = SystemForm.EntityLogicalName,
ColumnSet = new ColumnSet(new string[] { "formxml" }),
Criteria = new FilterExpression
{
Conditions = 
{
new ConditionExpression
{
//CRM represents EntityTypeName in ObjectTypeCode attribute
//Set 'Objecttypecode' as an Attribute name 
AttributeName = "objecttypecode",
Operator = ConditionOperator.Equal,
 
//set 'entityname' as value of an attribute
Values = { entityName }
},
new ConditionExpression
{
AttributeName = "type",
Operator = ConditionOperator.Equal,
Values = {"2"}
}
}
}
};
SystemForm systemForm = null;
EntityCollection entityCollection = organizationService.RetrieveMultiple(myFormXml);
 
#endregion
In continuation with above code, use below code to update the retrieved formxml with new section named as “Extra” and publish the customization changes.

if (entityCollection.Entities.Count > 0)
{
#region Validate Specified Tab,Section and Insert Control
systemForm = (SystemForm)entityCollection[0];
 
//Loads form xml to customization
XmlDocument customization = new XmlDocument();
customization.LoadXml(systemForm.FormXml);
 
//Creates XPathNavigator
XPathNavigator xNav = customization.CreateNavigator();
 
//Set path to insert new section on mainform.
string validateTab = "//tabs/tab[@name='" + tabName + "']";
string validateSection = validateTab + "/columns/column/sections" +
"/section[@name='" + sectionName + "']";
 
//Creates new row to place new web resource control with necessary parameters
string newDDList = "<section name='" + sectionName + "' showlabel='false' showbar='false'                 locklevel='0' id='{6851ca85-b2a6-9689-ead3-3813de16082e}'                         IsUserDefined='0' layout='varwidth' columns='11' labelwidth='115'                     celllabelalignment='Left' celllabelposition='Left'> "+
"   <labels> "+
"    <label description='Extra' languagecode='1033' />"+
"   </labels> "+
"   <rows> "+
"     <row> "+
"     </row> "+
"   </rows> "+
"</section>";
 
XPathNodeIterator xIterTab = xNav.Select(xNav.Compile(validateTab));
 
 
//Validate specified Tab exists or not 
if (xIterTab.Count == 0)
{
throw new InvalidPluginExecutionException("Invalid Tab Name, Please verify");
}
 
XPathNodeIterator xIterSection = xNav.Select(xNav.Compile(validateSection));
 
//Validate specified Section exist or not 
if (xIterSection.Count > 0)
throw new InvalidPluginExecutionException("The Section is already configured on a                                     form. You cannot specify the existing "
+ "Section Name");
 
if (xNav.CanEdit)
{
XPathExpression xExpression = xNav.Compile(validateTab +                                             "/columns/column/sections/section");
 
//Select node using specified path in expression.
XPathNodeIterator xIter = xNav.Select(xExpression);
if (xIter.Count > 0)
{
//Moves navigator to next node from current set node
while (xIter.MoveNext())
{
//Checks position of current node is last node or not.
if (xIter.CurrentPosition == xIter.Count)
 
//if currnt node is last node then insert new element    
xIter.Current.InsertAfter(newDDList);
}                            }
}
#endregion
 
#region Update Form xml
//Now we place the updated FormXml back into the systemform, and update                     it.
systemForm.FormXml = customization.InnerXml;
try
{
organizationService.Update(systemForm);
}
catch (Exception)
{
throw new InvalidPluginExecutionException("Failure: Updating the                     Formxml changes...");
}
#endregion
}
}

After implementing the above code in a plug-in you can verify the updated formxml either opening a record or Airport entity or by validating the same via form customization. You could see the new section with “Extra” in the tab “Extra” as shown below.

image

Similarly, you can apply other required customization changes programmatically.

I hope this will be useful.

2 comments:

  1. how can i problematically customize the entity specific RibbonDiffXml?

    ReplyDelete
  2. The following link may help you.
    http://blog.tallan.com/2011/06/24/microsoft-dynamics-crm-2011-adding-and-removing-buttons-from-the-ribbon/

    ReplyDelete