Monday, August 29, 2011

CRM2011 User Settings Utility

Hi Guys, I have created this CRM2011 utility tool that will help administrators to update personal settings of multiple users with  just few clicks. This is also my first codeplex project. Here is the link http://crm2011usersettings.codeplex.com.
Please leave feedback and suggestions.
Utility



Thanks

Tuesday, August 2, 2011

Enable/Disable Out of Box buttons (Sub Grid) based on a custom rule in crm 2011

You may have read millions of blogs on this topic. Here is my attempt.

Scenario:

We have an entity with “Many to One relationship” to multiple entities. We want to disable “Add Existing” button on subgrids of some of those entities.
In this example, I am disabling a “Add Existing Contact” button for all the entities except account. I am modifying the ribbon of contact entity.

Steps: There are 3 major steps to accomplish this solution

  1. JavaScript web resource
  2. Button id and command definition of the button we want to disabale/enable.
  3. Modify the ribbon definition of the entity ribbon.
Here are steps the steps in detail

Step 1: Javascript WebResource

  • Create a new javascript webresource with name new_CustomRule.js and add the following lines in it.
function HideExisting( PrimaryEntityTypeCode)
 {
  if (PrimaryEntityTypeCode ==1)
        {
        return true;
         }
         else
         {
          return false;
          }
 }
  • Save the webresource and publish it.
The HideExisting function is checking value of PrimaryEntityTypeCode parameter passed to it. If the PrimaryEntityTypeCode is 1(account) the function will return true otherwise it will return false.The function will enable the “Add Existing Contact” if it is on account form but disable the button on any other entity form.

Step 2: Getting the button id/s and command definitions of the button/s


  • If you don’t have CRM2011 SDK, download one. Go to location sdk\samplecode\cs\client\ribbon\exportribbonxml in SDK.

  • If you are using system entity and it’s ribbon has not been modified before, click on exportedribbonxml folder and open up the ribbon of your entity.

  • If you are working with a custom entity or with the system entity whose ribbon has been modified, open the exportribbonxml solution in Visual studio. If you are using a custom entity enter your entity name in ExportRibbonXml.cs in the following section.

image



  • Run the program and it will generate the ribbon definitions for the all the entities mentioned in the program.
  • Open the entity ribbon from exportedribbonxml folder and search for the button you are interested in. We are looking for “AddExisting” buttons in this case scenario. we need the whole <Buttons>tags for this solution

image

AddExistingStandard button is used when we embed a grid on the form and AddExistingAssoc is used when we click on native left navigation link. Look at “Command” name in the button tags above. We need the command definitions for these commands.

Step 3: Modify the Ribbon definition of Contact entity

  • Create a new solution in CRM, add contact entity to the solution and export the solution.

  • Open the customization file from the exported solution and look for <RibbonDiffXML> . It will look like following. We are making changes to 3 areas of the definition highlighted in red.
<RibbonDiffXml>
        <CustomActions />         
        <Templates>
               <RibbonTemplates Id=“Mscrm.Templates“></RibbonTemplates>
        </Templates>
        <CommandDefinitions />
        <RuleDefinitions>
       <TabDisplayRules />
       <DisplayRules />
       <EnableRules />
       </RuleDefinitions>
       <LocLabels />
</RibbonDiffXml>
  • Repalce the <CustomActions /> with
 <CustomActions>
            <CustomAction Id="AddExistingCustomAction"  Location="Mscrm.SubGrid.contact.AddExistingAssoc"  Sequence="40">
              <CommandUIDefinition>
                <Button Id="Mscrm.SubGrid.contact.AddExistingAssoc"  Command="Mscrm.AddExistingRecordFromSubGridAssociated"  Sequence="40" LabelText="$Resources(EntityDisplayName):Ribbon.SubGrid.AddExisting" Alt="$Resources(EntityDisplayName):Ribbon.SubGrid.AddExisting" Image16by16="/_imgs/ribbon/AddExistingStandard_16.png" Image32by32="/_imgs/ribbon/AddExistingStandard_32.png" TemplateAlias="o1" ToolTipTitle="$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingAssoc_ToolTipTitle" ToolTipDescription="$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingAssoc_ToolTipDescription" />
              </CommandUIDefinition>
            </CustomAction>
            <CustomAction Id="AddExistingCustomAction2"  Location="Mscrm.SubGrid.contact.AddExistingStandard"  Sequence="40">
              <CommandUIDefinition>
                <Button Id="Mscrm.SubGrid.contact.AddExistingStandard" Command="Mscrm.AddExistingRecordFromSubGridStandard" Sequence="30" LabelText="$Resources(EntityDisplayName):Ribbon.SubGrid.AddExisting" Alt="$Resources(EntityDisplayName):Ribbon.SubGrid.AddExisting" Image16by16="/_imgs/ribbon/AddExistingStandard_16.png" Image32by32="/_imgs/ribbon/AddExistingStandard_32.png" TemplateAlias="o1" ToolTipTitle="$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingStandard_ToolTipTitle" ToolTipDescription="$Resources(EntityDisplayName):Mscrm_SubGrid_EntityLogicalName_MainTab_Management_AddExistingStandard_ToolTipDescription" />
              </CommandUIDefinition>
            </CustomAction>
 </CustomActions>
We need a <CustomAction> to change the behaviour of the button. Make sure location property of <CustomAction> tag is exactly the same as Id property of <Button> tag.
The <Button >tags has been copied from contactribbon file from exportedribbonxml folder mentioned in step 2.
  • Repalce the <CommandDefinitions /> with the command definition from contactribbon file from step 2.
<CommandDefinitions>
            <CommandDefinition Id="Mscrm.AddExistingRecordFromSubGridStandard">
              <EnableRules>
                <EnableRule Id="Mscrm.AppendToPrimary" />
                <EnableRule Id="Mscrm.EntityFormIsEnabled" />
                <EnableRule Id="Mscrm.AddExistingCustomRule" />
              </EnableRules>
              <DisplayRules>
                <DisplayRule Id="Mscrm.ShowForOneToManyGrids" />
                <DisplayRule Id="Mscrm.AppendToPrimary" />
                <DisplayRule Id="Mscrm.AppendSelected" />
                <DisplayRule Id="Mscrm.CanWriteSelected" />
              </DisplayRules>
              <Actions>
                <JavaScriptFunction FunctionName="Mscrm.GridRibbonActions.addExistingFromSubGridStandard" Library="/_static/_common/scripts/RibbonActions.js">
                  <CrmParameter Value="SelectedEntityTypeCode" />
                  <CrmParameter Value="SelectedControl" />
                </JavaScriptFunction>
              </Actions>
            </CommandDefinition>
            <CommandDefinition Id="Mscrm.AddExistingRecordFromSubGridAssociated">
              <EnableRules>
                <EnableRule Id="Mscrm.AppendPrimary" />
                <EnableRule Id="Mscrm.AppendToPrimary" />
                <EnableRule Id="Mscrm.EntityFormIsEnabled" />
                <EnableRule Id="Mscrm.AddExistingCustomRule" />
              </EnableRules>
              <DisplayRules>
                <DisplayRule Id="Mscrm.ShowForManyToManyGrids" />
                <DisplayRule Id="Mscrm.AppendPrimary" />
                <DisplayRule Id="Mscrm.AppendToPrimary" />
                <DisplayRule Id="Mscrm.AppendSelected" />
                <DisplayRule Id="Mscrm.AppendToSelected" />
                <DisplayRule Id="Mscrm.CanWriteSelected" />
              </DisplayRules>
              <Actions>
                <JavaScriptFunction FunctionName="Mscrm.GridRibbonActions.addExistingFromSubGridAssociated" Library="/_static/_common/scripts/RibbonActions.js">
                  <CrmParameter Value="SelectedEntityTypeCode" />
                  <CrmParameter Value="SelectedControl" />
                </JavaScriptFunction>
              </Actions>
            </CommandDefinition>
          </CommandDefinitions>

The only thing we changed in the commandefinition is the <EnableRule> highlighted in Blue.
<EnableRule Id="Mscrm.AddExistingCustomRule" />

  • Now I need to define this rule. Change the <EnableRules /> with
<EnableRules>
      <EnableRule Id="Mscrm.AddExistingCustomRule">
       <CustomRule FunctionName="HideExisting" Library="$webresource:new_CustomRule.js" Default="false" >
          <CrmParameter Value="PrimaryEntityTypeCode" />
        </CustomRule>
      </EnableRule>
 </EnableRules>
In the <CustumRole> I am calling a function HideExisting from webresource CustomRule.js mentioned in step 1. The default return value for this function false.The <CustomRule> is also passing PrimaryEntityTypeCode as parameter to HideExisting function If the function return true, the system will enable the “Add Existing Contact” button otherwise it will be disable the button.

  • Save the file and overwrite the Customization file in your exported solution zip file with this file.
  • Import the solution zip file and publish it. It’s done.
Note: If your solution is not working. The reason may be, when you click on left navigation or click on subgrid on the form the javascript starts loading. But it won’t call the function. But if you click on some other option and come back it will work the second time.This problem has been fixed in Rollup 2 . I spent 2 days to sort this out.
Install rollup 2 and you are good to go.