Sunday, 27 February 2011

How to place a custom button on the main page (Application Ribbon) of MS Dynamics CRM 2011

This post explains how to place a custom button on the main page of  MS Dynamics CRM 2011.
Lets place a simple button Google and when we click it we should get a popup window with Google.com page.

Firstly lets create a new solution. Let's name it as Ribbon.


After the creation go to the solution and navigate to components. And then choose Add Existing option and click on Application Ribbons. The purpose of this action is to obtain the standard tags in our customization file.
Application Ribbon has been added to the Solution as shown below.



As you all know the next action is Publish the solution.

Lets export the customizations of this solution.




You could choose Unmanaged or Managed according to the requirement.
For the time being lets opt Unmanaged.


Save the customization file to the local folder

When we extract this zipped file, we could see the customizations.xml

Open the Customizations.xml preferably with a Visual Studio editor or with any good xml editor. Readability is a key factor while editing xml files.

As shown above we need to place some code for the custom actions and also command definitions.

Our target is to place a button on the main page next to Start Dialog button. In the above screen shot Accounts is a tab. This tab will change according to entity. Currently its showing Accounts because we chose Accounts. Our button will be displayed on the main page for all entities.

Here is the key word for this scenario
Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab 
Tab displays the plural entity display name in the label.

A few other tabs could be identified as 

Mscrm.HomepageGrid.{!EntityLogicalName}.View 
Tab has the label View.

Mscrm.HomepageGrid.{!EntityLogicalName}.Related 
Tab has the label Add.

Mscrm.HomepageGrid.{!EntityLogicalName}.Developer 
Tab has the label Customize.

Each Tab is divided into Groups and then Controls

Tab----> Group1,Group2,Group3....etc
Group-->Control1,Control2,etc


The above sample XML could be found in SDK. Its helpful if we refer this to identify clearly where we are going to place the button. Also we can see the attribute values.



Location="Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab.Workflow.Controls._children"
Location is a key attribute which determines the location of the new button.
Also Command="Sample.all.MainTab.MyURL.Command" determines the action to be taken by referring to the Command definitions as shown above.

Following is our new Customization file.

<ImportExportXml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Entities></Entities>
  <Roles></Roles>
  <Workflows></Workflows>
  <FieldSecurityProfiles></FieldSecurityProfiles>
  <Templates />
  <RibbonDiffXml>
    <CustomActions>
      <CustomAction Id ="Sample.{!EntityLogicalName}.MainTab.MyURL.CustomAction" Sequence="41"
                    Location="Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab.Workflow.Controls._children">
        <CommandUIDefinition>
          <Button Id="Sample.{!EntityLogicalName}.MainTab.MyURL.Button"
                    Command="Sample.all.MainTab.MyURL.Command"
                    LabelText="Google" ToolTipTitle="Google"
                    ToolTipDescription="Google" TemplateAlias="o1" />

        </CommandUIDefinition>
      </CustomAction>
    </CustomActions>
    <Templates>
      <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
    </Templates>
    <CommandDefinitions>
      <CommandDefinition Id="Sample.all.MainTab.MyURL.Command">
        <EnableRules />
        <DisplayRules />
        <Actions>
          <Url Address="http://www.google.com" />
        </Actions>
      </CommandDefinition>
    </CommandDefinitions >
    <RuleDefinitions>
      <TabDisplayRules />
      <DisplayRules />
      <EnableRules />
    </RuleDefinitions>
    <LocLabels />
  </RibbonDiffXml>
  <EntityMaps />
  <EntityRelationships />
  <OrganizationSettings>
    <customization>
      <isappmode>False</isappmode>
    </customization>
  </OrganizationSettings>
  <optionsets />
  <Languages>
    <Language>1033</Language>
  </Languages>
</ImportExportXml>



After this we could compress and export the customizations back to the MS Dynamics CRM 2011.







After the publish process, refresh the CRM URL and navigate to Workplace and click Accounts on the left navigation. You could see a button called "Google" on the application ribbon. If you click on it, you could see a popup with Google.com in it.

If you choose Contacts then you could see the same button on the same place.











How to use Sub-Grid in MS Dynamics CRM 2011

MS Dynamics CRM 2011 provides Sub-Grid feature to add an associated view to the form. This is a very helpful feature since it is even possible to filter the records.
For instance, consider  that we would like to associate a customized Contacts view to the Account form.
Let's see how quickly it could be done with this nice feature.
Navigate to Settings->Solutions->Entity->Account Entity->Account Form->Insert



You could see a Sub-Grid option. First place your cursor on the form where you want to insert the Sub-Grid. Its always a good practice to add it in a new section. And then click the Sub-Grid button.

We prefer to show only related contacts records of the Account entity. There is an option to edit the existing view or we could define a new view. Click on Edit button.


You could add or remove columns as per your preference. Once this is done click save and close. 
Note: Sometimes you may need to Publish the contact entity separately in order to see the modified view on the Account form. Its because this view is of another entity and there is no publish option on this navigation.


As shown above, the Sub-Grid displays the Contacts on the Account form. This provides a quick view of the related contacts of the corresponding Account to the End-User. As mentioned before this grid could be customized according to the requirements.

Editing Form Left Navigation items-Drag n Drop-MS Dynamics CRM 2011

In MS Dynamics CRM 2011 its possible to edit the form left navigation items just by a drag and drop. Even its possible to remove items or to reorder the items and sections in the left navigation.
Here is a scenario. Navigate to Solutions->Entity->Form . Here we are considering an Account form.
By default the "Body" Button on the ribbon would be enabled. But we would like to edit left navigation items. So click on the Navigation button which is on ribbon as shown below.


Please note the left navigation items are enabled for edit. "Common" is the first section and "Sales" is the second one.




Reordered left navigation items and section could be seen in the following screen shot. The section "Sales" in the left navigation was dragged and dropped to the top in Left Navigation items.


Its also possible to remove left navigation items by selecting the required one and then click the "Remove" button on the ribbon.

Saturday, 26 February 2011

A few good books for MS Dynamics CRM 2011

A few good books for MS Dynamics CRM 2011


       












 

     

Wednesday, 23 February 2011

How to refer a Web Resource file from Customizations file or Site map in MS Dynamics CRM 2011

Consider a scenario in MS Dynamics CRM 2011 where  you would like to change the icon of Workplace icon on the left navigation pane. In CRM 2011 its possible to upload the new icon file as a resource file into web resources and refer it from the sitemap. A sample is given below. In this code snippet, customIcon is a file which was uploaded to the webresources folder of MS Dynamics CRM 2011 and we are refering it using the simple code $webresource:customIcon 

The key advantage of this approach is that the uploaded webresource is used without depending on a particular server or physical location. As we all know its also possible to refer an icon file from either from a physical location or from a hosted URL. But just imagine what would happen if we move the Solution to another server. Hence the webresource reference approach becomes a valuable one. All supported webresource files could be used in the same way. Syntax is very simple too $webresource:webresourcefilename

Code snippet from Sitemap:


<Area Id="Workplace" ResourceId="Area_Workplace" ShowGroups="true" Icon="$webresource:customIcon" DescriptionResourceId="Workplace_Description">
</Area>


Code snippet from a Customizations.xml:

<CommandDefinitions>
<CommandDefinition Id="Org.CustomEntity.Form.CommandDefinition.TestButton">
<EnableRules>

<EnableRule Id="Org.contact.WebClient.EnableRule" />
</EnableRules>
<DisplayRules>
<DisplayRule Id="Org.contact.WebClient.DisplayRule" />
</DisplayRules>
<Actions>
<JavaScriptFunction Library="$webresource:yourjavascriptfile.js" FunctionName="Display">
</JavaScriptFunction>
</Actions>
</CommandDefinition>
</CommandDefinitions>

Another scenario -Consider that we placed a Button on the ribbon XML of an entity form and we would like to execute a javascript file when the end-user clicks the button. As explained above firstly upload the javascript file into Webresources of the solution. And refer the js file using the same syntax as shown above. When you move Solution to another server, you don't need to move the js file separately because its already in webresource and certainly the webresources will be moved along with Solution.

Tuesday, 22 February 2011

Fetch XML in MS Dynamics CRM 2011

 MS Dynamics CRM 2011 Users could easily download fetch xml queries from the 'Advanced Find'  option. So Developers could make use of the fetch XML as a good user input. This post explains how it could be done. Consider the scenario of contacts.


We would like to build a query to list the contacts who lives in London.  So we navigated to Adavanced Find option, which is one of the best features of MS Dynamcis CRM.

Please note the option to download the fetchxml file


Once you click on the Download Fetch XML option, you could save the XML file to your local machine. The XML file contents is purely based on the query that the user made. For instance our query was based on the city field.


Another example could be if you want to retrieve all account records then the XML file contents would be
<fetch mapping='logical'> 
   <entity name='account'><all-attributes/></entity>
</fetch>

But anyway MS Dynamics CRM will create the XML file for you.

So it is possible to use this XML contents as a user input on any of the forms. Users could easily copy this XML contents and paste in the text box.

We have 2 classes in MS Dynamics CRM which are very useful to deal the Fetch XML contents as normal query expression.

FetchXmlToQueryExpressionRequest   ---- Request to the organization service
 FetchXmlToQueryExpressionResponse -- Response from the organization service

FetchXmlToQueryExpressionRequest req = new FetchXmlToQueryExpressionRequest();
req.FetchXml = "<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false"><entity name="contact"><attribute name="fullname" />attribute name="telephone1" /><attribute name="contactid" /><order attribute="fullname" descending="false" /><filter type="and"><condition attribute="address1_city" operator="eq" value="London" /></filter></entity></fetch>";


FetchXmlToQueryExpressionResponse resp = (FetchXmlToQueryExpressionResponse)service.Execute(req);

So the resp variable will have the results as per the query ( In this case query in the form of fetch XML)



OR


string fetchXML="<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false"><entity name="contact"><attribute name="fullname" />attribute name="telephone1" /><attribute name="contactid" /><order attribute="fullname" descending="false" /><filter type="and"><condition attribute="address1_city" operator="eq" value="London" /></filter></entity></fetch>";


EntityCollection resp = service.RetrieveMultiple(new FetchExpression(fetchXML));

Sunday, 20 February 2011

How to differentiate between Create and Update contexts of a Form in MS Dynamics CRM 2011 using Javascript

var  formType= Xrm.Page.ui.getFormType();
getFormType() function returns a number
If the return value is 1 –  Form context is Create
If the return value is 2 –  Form context is Update

How to set required level of a control in MS Dynamics CRM 2011 using Javascript

MANDATORY:
Xrm.Page.getAttribute(YourAttributeName).setRequiredLevel(“required”);

OR

SetFieldRequiredOrRecommended(crmForm.all[YourAttributeName+ "_c"], FIELD_REQUIRED, "");

RECOMMENDED:

Xrm.Page.getAttribute(YourAttributeName).setRequiredLevel(“recommended”);
OR
SetFieldRequiredOrRecommended(crmForm.all[YourAttributeName+ "_c"], FIELD_RECOMMENDED, "");

NONE:
Xrm.Page.getAttribute(YourAttributeName).setRequiredLevel(“none”);
OR
SetFieldRequiredOrRecommended(crmForm.all[YourAttributeName+ "_c"], FIELD_NOT_REQUIRED, "");

Reading XML file in MS Dynamics CRM 2011 using Javascript

In MS Dynamics CRM 2011, we could maintain the XML files using web resource utility, which is a very good feature. It could be read using Javascript which is also maintained in the web resources.
You could make use of this feature when you want to populate some values dynamically. So that later amendments could be done in the XML file.
The path could be in the following format after uploading the xml file into the web resources of the solution.
var xmlPath = "../WebResources/ConfigureAttributes.xml";
Sample xml file –ConfigureAttributes.xml
<attributes>
    <attribute id="DateofBirth">sol_birthdate</attribute>
    <attribute id="Name">sol_name</attribute>
</attributes>

The contents of the xml file could be read using the following code.
var nodePath = "//attributes/attribute";
var doc = new ActiveXObject("Microsoft.XMLDOM");
doc.preserveWhiteSpace = true;
doc.async = false;
doc.load(xmlPath);
params = new Array();
var nodelist;
nodelist = doc.selectNodes(nodePath);
for (var i = 0; i < nodelist.length; i++)
{
params[i] = nodelist(i).attributes[0].value;
}

How to disable a control in MS Dynamics CRM 2011 using Javascript

Code snippet:

var control = Xrm.Page.ui.controls.get(YourAttributeName);
control.setDisabled(true);

How to hide a control in MS CRM 2011 using Javascript

code snippet:
var control = Xrm.Page.ui.controls.get(YourAttributeName);
control.setVisible(false);

“CRM cannot find the plugin assembly or one of its dependencies” OR How to use IL Merge? OR How to merge DLLs?

Have you ever faced this issue when you deployed plugins in MS Dynamics CRM?
“CRM cannot find the plugin assembly or one of its dependencies” 

Here is a free tool from Microsoft to resolve the dependency issues of Assemblies. In simple words, ILMerge will create a capsule dll with all the dependency dlls inside in it.

IL Merge could be downloaded from the following link:




ILMerge is a tool to merge .NET assemblies into one dll. For instance, if you have business layer, configuration layer etc then you could merge all the dlls into a single dll using IL Merge. This is very useful when you develop plugins. We may need to include functionalities of other layers to our plugin. So if you use ILMerge you could merge those dlls along with your plugins dll. This avoids dependency issues while using plugins in MS Dynamics CRM.
 
In ILMerge you could specify the dlls to be merged. It’s very simple to use ILMerge.
Please ensure that the following are in place prior to executing these commands.
1) ILMerge.exe exists in the path provided in the command. 2) The output directory exists in the path provided in the command and also the file paths are valid

IL Merge could be implemented in 2 ways
1) Create a batch file and include the ILMerge code and later execute the batch file.
Code snippet for the batch file:
"C:\Projects\MyProject\Library\ILMerge" /t:library /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /copyattrs /keyfile:"C:\Projects\MyProject\Library\mykey.snk"
/out:"C:\Projects\MyProject\Plugins\OutputPluginsLibrary\ PluginsLibrary.dll"  "C:\Projects\MyProject\Plugins\ bin\Debug\Entities.dll" "C:\Projects\MyProject\Plugins\ bin\Debug\Plugins.dll"

2)  Include the ILMerge code in the BUILD EVENTS of the Class Library Project.
Place the following code snippet in the build event as shown in the screen shot
  "$(SolutionDir)Library\ILMerge" /t:library /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /copyattrs /keyfile:"$(SolutionDir)Library\mykey.snk" /out:"$(SolutionDir)Plugins\OutputPluginsLibrary\ PluginsLibrary.dll" "$(SolutionDir)Plugins\$(OutDir)Entities.dll" "$(SolutionDir)Plugins\$(OutDir)Plugins.dll"


This code execution will be done on a successful build.
Macros used:
$(SolutionDir) - The directory of the solution.
$(OutDir) - Path to the output file directory, relative to the project directory.
On a successful scenario, you could see a combined dll in the corresponding output directory. This dll will not cause any dependency issues when it’s deployed in Dynamics CRM Environment.