CRM 2011 – Bulk Removal of Child Entity records from Parent Entity Form.

In CRM 2011, in a 1:N (One-to-Many) entity relationship one entity has a lookup attribute that allows an entity object to store a reference to another entity object for a particular entity.

For 1:N entity relationship Parent Entity will have Left Navigation link to see all the Children Entity records associated with it. User can add new child records from Parent form itself.

However if User have to remove the children records from Parent Entity, they have to open each child record form and set the Lookup up value as null or blank. This is some times lengthy processes especially if the number of records are high.

To address this problem I created CRM solution which will allow User to remove child records from Parent Entity form and they need not go to individual child record form.

CRM Solutions are available on CodePlex

This solution adds a Custom Ribbon button to the “Records” Group of Sub-Grid Ribbon (List Tools). 

 

Screenshot 1: “Remove” button is added to Sub-Grid Ribbon.

image

 

Screenshot 2: “Remove” button is enabled only when there is at least one selected record in Sub-Grid

image

 

Custom “Remove” Ribbon button is displayed only when following conditions are satisfied

1. Entity relationship is 1:n, Remove button is not enabled for n:n (many – to –many ) relationships

2. User has “Basic” privilege on “Write” access on Selected Sub-Grid entity.

3. User has “Basic” privilege on “Append” access on Selected Sub-Grid entity.

4. User has “Basic” privilege on “AppendTo” access on Primary Entity in Form.

 

Screenshot 3: Confirm Removal dialog box is shown which includes count of selected records by User in Sub-Grid

image

 

Screenshot 4: Process in Progress Message

image

 

Screenshot 5: Error message

image

 

If all records are successfully removed, then Conform dialog box will automatically close and refresh sub-grid.

 

For those who wanted to alter Ribbon customizations to make it available only for selected entities can alter Application Ribbon XML.

New Display Rules can be added.

Following is Ribbon Customization done in Application Ribbon

<RibbonDiffXml>

    <CustomActions>

      <CustomAction Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.CustomAction" Location="Mscrm.SubGrid.{!EntityLogicalName}.MainTab.Management.Controls._children" Sequence="41">

        <CommandUIDefinition>

          <Button Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren" Command="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command" Sequence="130" ToolTipTitle="$LocLabels:makeer.SubGrid.EntityLogicalName.MainTab.Management.RemoveChildren.LabelText" LabelText="$LocLabels:makeer.SubGrid.EntityLogicalName.MainTab.Management.RemoveChildren.LabelText" ToolTipDescription="$LocLabels:makeer.SubGrid.EntityLogicalName.MainTab.Management.RemoveChildren.Description" TemplateAlias="isv" Image16by16="$webresource:makeer_/IMG/PNG/Remove_16x16.png" Image32by32="$webresource:makeer_/IMG/PNG/Remove_32x32.png" />

        </CommandUIDefinition>

      </CustomAction>

    </CustomActions>

    <Templates>

      <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>

    </Templates>

    <CommandDefinitions>

      <CommandDefinition Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command">

        <EnableRules>

          <EnableRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.EnableRule.SelectionCountRule" />

        </EnableRules>

        <DisplayRules>

          <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.RelationshipTypeRule" />

          <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.EntityPrivilegeRule" />

          <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.EntityPrivilegeRule2" />

          <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.EntityPrivilegeRule3" />

        </DisplayRules>

        <Actions>

          <JavaScriptFunction FunctionName="RemoveChildren" Library="$webresource:makeer_/Scripts/RemoveChildren.js">

            <CrmParameter Value="PrimaryEntityTypeName" />

            <CrmParameter Value="SelectedEntityTypeName" />

            <CrmParameter Value="SelectedControlSelectedItemIds" />

            <CrmParameter Value="SelectedControl" />

          </JavaScriptFunction>

        </Actions>

      </CommandDefinition>

    </CommandDefinitions>

    <RuleDefinitions>

      <TabDisplayRules />

      <DisplayRules>

        <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.RelationshipTypeRule">

          <RelationshipTypeRule RelationshipType="OneToMany" AppliesTo="SelectedEntity" />

        </DisplayRule>

        <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.EntityPrivilegeRule">

          <EntityPrivilegeRule AppliesTo="PrimaryEntity" PrivilegeDepth="Basic" PrivilegeType="AppendTo" />

        </DisplayRule>

        <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.EntityPrivilegeRule2">

          <EntityPrivilegeRule AppliesTo="SelectedEntity" PrivilegeDepth="Basic" PrivilegeType="Write" />

        </DisplayRule>

        <DisplayRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.DisplayRule.EntityPrivilegeRule3">

          <EntityPrivilegeRule AppliesTo="SelectedEntity" PrivilegeDepth="Basic" PrivilegeType="Append" />

        </DisplayRule>

      </DisplayRules>

      <EnableRules>

        <EnableRule Id="makeer.SubGrid.{!EntityLogicalName}.MainTab.Management.RemoveChildren.Command.EnableRule.SelectionCountRule">

          <SelectionCountRule AppliesTo="SelectedEntity" Minimum="1" Default="false" />

        </EnableRule>

      </EnableRules>

    </RuleDefinitions>

    <LocLabels>

      <LocLabel Id="makeer.SubGrid.EntityLogicalName.MainTab.Management.RemoveChildren.LabelText">

        <Titles>

          <Title languagecode="1033" description="Remove" />

        </Titles>

      </LocLabel>

      <LocLabel Id="makeer.SubGrid.EntityLogicalName.MainTab.Management.RemoveChildren.Description">

        <Titles>

          <Title languagecode="1033" description="Remove selected records. When you remove a record it still exists in the system." />

        </Titles>

      </LocLabel>

    </LocLabels>

  </RibbonDiffXml>

 

Advertisements

Conditional Hiding of Process Group in Ribbon on CRM 2011

On CRM 2011, there is Process Group in Ribbon. This Process groups contains 2 Ribbon Buttons namely “Run Workflow” and “Start Dialog”.

image

 

By configuring Security Roles we can disable these buttons from certain Users.

In Security Role, Entity Process should be configured to revoke read permissions

image

 

However in some cases we wanted to completely hide these buttons along with its Group. CRM does not hide the buttons even if we revoke Read permissions from Process entity. At the most it disables the button in Ribbon.

We can completely hide the Process group globally by using HideCustomAction, but then its is hidden from every user, even System Administrator cannot see it. So we have to do Ribbon customization to conditionally hide the Process group from certain User.

In following blog I have explain how I achieved it using entity based Ribbon customization.

Steps

1. Create a CRM Solution with number of entities on which Process Group in Ribbon needs to be hidden and Export this solution.

2. From exported .zip file extract customization.xml file and open it in suitable editor, my favorite is Visual Studio.

3. Under <CustomActions> which is under<RibbonDiffXml> paste following XML code

<!–********************************************–>

<CustomAction Id="Mscrm.HomepageGrid.XXXXX.MainTab.Workflow_CustomAction" Location="Mscrm.HomepageGrid.XXXXX.MainTab.Workflow" Sequence="40">

  <CommandUIDefinition>

    <Group Id="Mscrm.HomepageGrid.XXXXX.MainTab.Workflow" Command="Mscrm.XXXXX.Workflow.Command" Sequence="40" Title="$Resources:Ribbon.HomepageGrid.Data.Workflow" Image32by32Popup="/_imgs/ribbon/runworkflow32.png" Template="Mscrm.Templates.Flexible">

      <Controls Id="Mscrm.HomepageGrid.XXXXX.MainTab.Workflow.Controls">

        <Button Id="Mscrm.HomepageGrid.XXXXX.RunWorkflow" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunWorkflow" Command="Mscrm.RunWorkflowSelected" Sequence="40" LabelText="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" Alt="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" Image16by16="/_imgs/ribbon/StartWorkflow_16.png" Image32by32="/_imgs/ribbon/runworkflow32.png" TemplateAlias="o1" />

        <Button Id="Mscrm.HomepageGrid.XXXXX.RunScript" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunScript" Command="Mscrm.RunInteractiveWorkflowSelected" Sequence="50" LabelText="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Alt="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Image16by16="/_imgs/ribbon/startdialog_16.png" Image32by32="/_imgs/ribbon/startdialog_32.png" TemplateAlias="o1" />

      </Controls>

    </Group>

  </CommandUIDefinition>

</CustomAction>

 

<CustomAction Id="Mscrm.Form.XXXXX.MainTab.Workflow_CustomAction" Location="Mscrm.Form.XXXXX.MainTab.Workflow">

  <CommandUIDefinition>

    <Group Id="Mscrm.Form.XXXXX.MainTab.Workflow" Command="Mscrm.XXXXX.Workflow.Command" Sequence="45" Title="$Resources:Ribbon.HomepageGrid.Data.Workflow" Image32by32Popup="/_imgs/ribbon/runworkflow32.png" Template="Mscrm.Templates.Flexible">

      <Controls Id="Mscrm.Form.XXXXX.MainTab.Workflow.Controls">

        <Button Id="Mscrm.Form.XXXXX.RunWorkflow" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunWorkflow" Command="Mscrm.RunWorkflowPrimary" Sequence="20" LabelText="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" Alt="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" Image16by16="/_imgs/ribbon/StartWorkflow_16.png" Image32by32="/_imgs/ribbon/runworkflow32.png" TemplateAlias="o1" />

        <Button Id="Mscrm.Form.XXXXX.RunScript" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunScript" Command="Mscrm.RunInteractiveWorkflowPrimary" Sequence="25" LabelText="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Alt="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Image16by16="/_imgs/ribbon/startdialog_16.png" Image32by32="/_imgs/ribbon/startdialog_32.png" TemplateAlias="o1" />

      </Controls>

    </Group>

  </CommandUIDefinition>

</CustomAction>

 

<CustomAction Id="Mscrm.SubGrid.XXXXX.MainTab.Workflow_CustomAction" Location="Mscrm.SubGrid.XXXXX.MainTab.Workflow">

  <CommandUIDefinition>

    <Group Id="Mscrm.SubGrid.XXXXX.MainTab.Workflow" Command="Mscrm.XXXXX.Workflow.Command" Sequence="70" Title="$Resources:Ribbon.HomepageGrid.Data.Workflow" Image32by32Popup="/_imgs/ribbon/runworkflow32.png" Template="Mscrm.Templates.Flexible">

      <Controls Id="Mscrm.SubGrid.XXXXX.MainTab.Workflow.Controls">

        <Button Id="Mscrm.SubGrid.XXXXX.RunWorkflow" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunWorkflow" Command="Mscrm.RunWorkflowSelected" Sequence="30" LabelText="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" Alt="$Resources:Ribbon.HomepageGrid.Data.Workflow.RunWorkflow" Image16by16="/_imgs/ribbon/RunWorkflow_16.png" Image32by32="/_imgs/ribbon/runworkflow32.png" TemplateAlias="o1" />

        <Button Id="Mscrm.SubGrid.XXXXX.RunScript" ToolTipTitle="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" ToolTipDescription="$Resources(EntityDisplayName):Ribbon.Tooltip.RunScript" Command="Mscrm.RunInteractiveWorkflowSelected" Sequence="40" LabelText="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Alt="$Resources:Ribbon.HomepageGrid.Data.InteractiveWorkflow.RunScript" Image16by16="/_imgs/ribbon/StartDialog_16.png" Image32by32="/_imgs/ribbon/StartDialog_32.png" TemplateAlias="o1" />

      </Controls>

    </Group>

  </CommandUIDefinition>

</CustomAction>

 

4. Replace XXXXX with entity logical name

5.Under <CommandDefinitions> paste following XML colde.

<!–********************************************–>

<CommandDefinition Id="Mscrm.XXXXX.Workflow.Command">

  <EnableRules>

    <EnableRule Id="Mscrm.Enabled" />

  </EnableRules>

  <DisplayRules>

    <DisplayRule Id="Mscrm.XXXXX.Workflow.DisplayRule"/>

  </DisplayRules>

  <Actions />

</CommandDefinition>

<!–********************************************–>

6. Replace XXXXX with entity logical name

7. Under <DisplayRules> under <RuleDefinitions> paste following XML code.

This rule basically checks whether User has Workflow Execution Permissions at Organization level. It will hide Process Group from all users who do not have Workflow Execution permissions.

<!–********************************************–>

<DisplayRule Id="Mscrm.XXXXX.Workflow.DisplayRule">

  <MiscellaneousPrivilegeRule PrivilegeName="WorkflowExecution" PrivilegeDepth="Global"/>

</DisplayRule>

<!–********************************************—>

8. Replace XXXXX with entity logical name

9. Save all these changes, Zip it back and Import the solution.

10. Open Security Role go to Customization tab and remove Execute Workflow Job access.

image

 

11. Now user will not see the Process tab

image

 

One of the advantage of this approach is Ribbon buttons are hidden based on Security Role settings. Based on requirements Display conditions can be further modified.

CRM 2011–Hiding Ribbon Tab using FormEntityContextRule

CRM 2011 does offer <HideCustomAction> to hide Ribbon Elements including Ribbon tabs. However in some cases we might have to selectively hide Tabs based on several conditions.

In such cases <HideCustomAction> is of less helpful as it globally hides the Ribbon element.

In this Walkthrough I am trying to demonstrate on of such scenario.

Scenario: A CRM Entity form has has Many-To-One relationship with multiple entities. Each of these entities are having Sub-Grid to show CRM entity in List form. Now we wanted to hide Contextual (List) tab for Sub-Grid entity from Main form of some of the entities.

Step 1:

Create a CRM 2011 Solution with entity for which Ribbon in Contextual Tab needs to be hidden. In this case entity name is new_cpvertical

Step 2:

Open ExportRibbonXml for the entity new_cpvertical. You can find this xml at SDK folder samplecodecsclientribbonexportribbonxmlbinDebugExportedRibbonXml. If RibbonXml for your entity is not available you can execute the solution exportribbonxml.sln and create one.

 

Step 3:

In RibbonXml, locate Tab element with Id as “Mscrm.SubGrid.new_cpvertical.MainTab” and copy entire Tab element with all its decendants.

Step 4:

Open customization.xml file from Solution you exported in Step1, and add Tab element copied in Step 3 under

image

Note that Location value for CustomAction is same as MainTab id.

Step 5:

Copy Command="Mscrm.SubGrid.new_cpvertical.MainTab" and all the Rules that has been referenced in Command.

Step 6:

Copy <TabDisplayRules> element under <RuleDefinitions> as shown below

image

Note: TabCommand should be same as CommandDefinition Id used under CommandDefinition

Step 7:

Create a new DisplayRule as shown below

image

Note: EntityName value is name of the PrimaryEntity where Sub-Grid is placed. Depending upon how many such entities need to be configured you can add Or to it.

Step 8:

Call this DisplayRule in Command ="Mscrm.SubGrid.new_cpvertical.MainTab"

image

Step 8:

Save the Customization, zip it back to Solution file and Import solution in CRM and Publish the Customization.

Here is how it looks with Contextual Ribbon hidden

With Contextual Ribbon (Note there is a List Tools Ribbon tab)

image

After hiding Contextual Ribbon (Note there is NO List Tools Ribbon tab)

image

Hope this helps

Walkthrough of Asynchronous call from <CustomRule> (RibbonDiff)

Walkthrough of Asynchronous call from <CustomRule>(RibbonDiff)

In following walkthrough I am demonstrating how to use EnableRule in Ribbon to call JavaScript function which will do Asynchronous call to CRM using REST and how to set Enable and Disable Ribbon Button

Assuming that Ribbon Customization is done and CustomRule is calling JavaScript function on EnableRule.

Following is how JavaScript. Here I am checking if logged in User is associated with current Entity record using Connections.

///<reference path=”XrmPage-vsdoc.js”/>
//Global Parameter
var isPartnerTeamMember = false;
var PageUI; 

function GetServerUrl() {

    var customServerURL = document.location.protocol + “//” + document.location.host + “/” + Xrm.Page.context.getOrgUniqueName();

    return customServerURL;

}

 

function CheckUserAccessOnPartner(PrimaryEntityTypeName, partnerObjectTypeCode, SelectedEntityTypeName, partnerId) {

    if (isPartnerTeamMember) {

        return true;

    }

    else {

        PageUI = window.top.opener.parent.Xrm.Page.ui;

        var context = Xrm.Page.context;

        var serverUrl = GetServerUrl();

        var userId = context.getUserId();

        var ODataPath = serverUrl + “/XRMServices/2011/OrganizationData.svc”;

        var retrieveReq = new XMLHttpRequest();

        retrieveReq.open(“GET”, ODataPath + “/ConnectionSet?$select=ConnectionId,Record1Id,Record1ObjectTypeCode,Record2Id,Record2ObjectTypeCode&$filter=Record1ObjectTypeCode/Value eq ” + partnerObjectTypeCode + ” and Record2ObjectTypeCode/Value eq 8 and Record1Id/Id eq guid'” + partnerId + “‘”, true);

        retrieveReq.setRequestHeader(“Accept”, “application/json”);

        retrieveReq.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);

        retrieveReq.onreadystatechange = function () {

            retrievePartnerConnectionsCallBack(this);

        };
        retrieveReq.send();
        return false;
    }
}

function retrievePartnerConnectionsCallBack(retrieveReq) {

    if (retrieveReq.readyState == 4 /* complete */) {

        if (retrieveReq.status == 200) {
            //Success
            var responseData = JSON.parse(retrieveReq.responseText).d;

            if (responseData != null && responseData.results != null && responseData.results.length > 0) {

                for (i = 0; i < responseData.results.length; i++) {

                    var record2Id = “{” + responseData.results[0].Record2Id.Id + “}”;

                    if (record2Id.toLowerCase() == Xrm.Page.context.getUserId().toLowerCase()) {

                        isPartnerTeamMember = true;

                        if (PageUI != null) {
                            PageUI.refreshRibbon();
                        }
                        break;
                    }
                }
            }
        }

        else {
            //errorHandler(retrieveReq);
        }
    }
}

 Key Point to note in above Script

  1. I am using Global variable to defined return value (isPartnerTeamMember) which is by default set to false.
  2. As first step I am checking isPartnerTeamMember and returning if it is true else calling REST query.
  3. In REST callback I am calling Xrm.Page.ui.refreshRibbon() method, which will reevaluate function and this time it will find isPartnerTeamMember as true and it will be returned from there.
  4. One of the important thing to note here is if you have having Ribbon button on SubGrid or associated view Xrm.Page.ui will be null for this you have to use window.top.opener.parent.Xrm.Page.ui (Thanks Daniel Cai !! for figuring out this)

Hope this Helps

Walkthrough – Adding CustomRule to OutofBox Ribbon Button

CRM 2011 has introduced Ribbon. Few weeks back I spent some time to customize Ribbon button and add CustomRule which Enables and Disables Ribbon Button based on JavaScript function return value.
I thought of sharing my experience so that others can take advantage of my learning.

Functionality Required:

I have Many-To-Many relationships between Contact and Account entity, on Account form there is Navigation Link for Contacts which enables user to Add Existing Contacts to Account. These Contacts can be seen by any user who has Read permission on Account and Contact, but we need to implement extra check to allow only certain Users to Add Existing Contacts based on certain logic driven on values of certain attributes of Account entity. So
when User opens Account Form and click on Contact Link either in left Navigation Pane or click on Contact Sub-Grid on Account for, CustomRule should get fired and depending upon output of Rule “Add Existing Contact” button in Ribbon should be enabled or disabled.

Following are steps which need to carry out

1. We first need to take Contact Ribbon XML.The definitions of the default ribbon definitions are included in the downloadable files in the Microsoft Dynamics CRM SDK. The SDK\SampleCode\CS\Client\Ribbon\ExportRibbonXml\ExportedRibbonXml folder includes the output files you would have for an organization with a ribbon that has not been customized. You don’t need to run the sample application to export this data. If you have a customized ribbon, you should run the sample application to refresh the files in this folder with any customizations previously applied for your organization. File name for Contact should be contactribbon.xml

2. Open contactribbon.xml in MS VS 2010. Since we have to apply rule for Contact Ribbon in Account form, locate
<ContextualGroupId=Mscrm.SubGrid.contact.ContextualTabsin contactribbon.xml,

It will list various Buttons, for our purpose we need following button which is shown in Associated View of Contact.

<ButtonId=Mscrm.SubGrid.contact.AddExistingAssocCommand=Mscrm.AddExistingRecordFromSubGridAssociatedSequence=40LabelText=$Resources(EntityDisplayName):Ribbon.SubGrid.AddExistingAlt=$Resources(EntityDisplayName):Ribbon.SubGrid.AddExistingImage16by16=/_imgs/ribbon/AddExistingStandard_16.pngImage32by32=/_imgs/ribbon/AddExistingStandard_32.pngTemplateAlias=o1ToolTipTitle=$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingAssoc_ToolTipTitleToolTipDescription=$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingAssoc_ToolTipDescription/>

In this button there is Command property which gets called everytime button is loaded in UI, CRM has default Commands for Out Of Box Ribbon Buttons. In same contactribbon.xml locate CommandDefinition with Id as Mscrm.AddExistingRecordFromSubGridAssociated, it should look like

<CommandDefinitionId=Mscrm.AddExistingRecordFromSubGridAssociated>
<EnableRules>
<EnableRuleId=Mscrm.AppendToPrimary/> <EnableRuleId=Mscrm.EntityFormIsEnabled/> </EnableRules>
<DisplayRules><DisplayRuleId=Mscrm.AddExisting/>
<DisplayRuleId=Mscrm.ShowForManyToManyGrids/>
<DisplayRuleId=Mscrm.AppendToPrimary/>
<DisplayRuleId=Mscrm.AppendSelected/>
</DisplayRules>
<Actions>
<JavaScriptFunction FunctionName=Mscrm.GridRibbonActions.addExistingFromSubGridAssociated
Library=/_static/_common/scripts/RibbonActions.js>
<CrmParameterValue=SelectedEntityTypeCode/>
<CrmParameterValue=SelectedControl/></JavaScriptFunction>
</Actions>
</CommandDefinition>

Thats all information we need from contactribbon.xml file

2. Now create a new Solution and add Contact entity to it. Export the solution and open solution zip file and open customizations.xml in MS VS 2010.

3. In customizations.xml, there should be <RibbonDiffXml> in it, all the Ribbon Customization goes under this element. If there is no prior customization don on contact Ribbon it should look like

<RibbonDiffXml>
<
CustomActions>
</
CustomActions>
<
Templates>
<
RibbonTemplatesId=Mscrm.Templates></RibbonTemplates>
</
Templates>

<CommandDefinitions>
</
CommandDefinitions>

<RuleDefinitions>
<
TabDisplayRules />
<
DisplayRules />
<
EnableRules/>
</
RuleDefinitions>

<LocLabels/>
</RibbonDiffXml>

4. Copy the CommandDefinition we found in contactribbon.xml (with Id = Mscrm.AddExistingRecordFromSubGridAssociated) and paste it in Customizations.xml file under <CommandDefinitions> tag. Once copy give new Unique Id to CommandDefintion in customizations.xml

<CommandDefinition Id=”Mscrm.AddExistingRecordFromSubGridAssociated_CustomAction“>

5. Since we have to enable and disable Ribbon button we have add new <EnableRule>. Add this rule under <RuleDefinitions>. Again give new Unique Id to this rule. You can have Rule depending upon your requirement, in my case I have CustomRule which calls JavaScript function.

<EnableRule Id=”Mscrm.AddExistingRecordFromSubGridAssociated_CustomRule“>

<CustomRule FunctionName=”isUserPartnerTeamMember” Default=”false”

Library=”$webresource:mbs_/UserSettings.js”>

6. Once created Refer this EnableRule in Command Definition

<EnableRule Id=”Mscrm.EntityFormIsEnabled” />

7. Now we all set with CommandDefinition. We have to add Button element copied from contactribbon.xml under <CustomActions> tag in customization.xml. Important thing to note here is Location property of CustomAction should be exactly same as ButtonId and Command property of Button should now refer to new Id of CommandDefinition which we have created in above steps.

<CustomActions>
<CustomActionId=Mscrm.SubGrid.contact.AddExistingAssoc_CustomAction”  Location=Mscrm.SubGrid.contact.AddExistingAssoc”  Sequence=40>
<CommandUIDefinition>
<ButtonId=Mscrm.SubGrid.contact.AddExistingAssoc”  Command=Mscrm.AddExistingRecordFromSubGridAssociated_CustomAction”  Sequence=40LabelText=$Resources(EntityDisplayName):Ribbon.SubGrid.AddExistingAlt=$Resources(EntityDisplayName):Ribbon.SubGrid.AddExistingImage16by16=/_imgs/ribbon/AddExistingStandard_16.pngImage32by32=/_imgs/ribbon/AddExistingStandard_32.pngTemplateAlias=o1ToolTipTitle=$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingAssoc_ToolTipTitleToolTipDescription=$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingAssoc_ToolTipDescription/>
</CommandUIDefinition>
</CustomAction>
</CustomActions>

8. Finally import customization back in CRM and new CustomRules should be effective.

Hope this helps