Friday, December 30, 2011

Step by step tutorial to add an entity URL to an email in a workflow

Rollup 5 introduced some new features in CRM2011. One of them is to add  an entity URL to an email in workflow. Before rollup 5, it used to be a  complicated process.We don't need to create custom workflow assemblies to this any more.. Still, there are a lot of people asking the same question “How to add entity URLs to emails in workflows” in CRM Forums.
Here is the step by step tutorial to add an entity URL to an email in a workflow.
1.    Start a new workflow.
2.    To send an email. Click on “Add Step” and choose “Send Email”. It will open up a following screen.pic 
3.    Add the information as required and to add the hyperlink, click on hyperlink icon shown in red circle in the above screen shot. It will open up a following screen.
pic2
4.    In “Text to display”. Enter the text to you would want to display. I am displaying the full name of the contact. It can be any string.
5.    Select the “URL” text box . When you look through the available fields. You can see a new option “Record URL (Dynamic)”. Click on that and press Ok.  The email will look like following screen.pic3  6.    Press save and close. Publish the workflow and you are good to go.

Monday, December 26, 2011

CRM2011 Subgrids and JavaScript

I have been thinking of bloging about this topic from last 6 months. I wanted to get an aggregate of numeric/money field in the grid. It is very easy to do, if subgrid contains only one page. But How would you get the aggregate if subgrid has more than 1 pages.

I posted this question on the forums and I never get an answer. I still don't have a solution for this problem.
Anyway....

The following sample code displaying the message box with the aggregate of “Estimated Revenue” field  of the opportunity.ce
function subGridOnload() 
{ 
 //debugger;
 var grid = Xrm.Page.ui.controls.get('Opps')._control;
 var sum =0.00;
 //if  (grid.readyState!="complete") 
 //{ 
 // delay one second and try again. 
 //setTimeout(subGridOnload, 1000); 
 //return; 
 //} 

 if  (grid.get_innerControl()==null)
 { 
  setTimeout(subGridOnload, 1000); 
  return; 
 } 
 else if (grid.get_innerControl()._element.innerText.search("Loading")!= -1)
 {
  setTimeout(subGridOnload, 1000); 
  return;
 }

 var ids = grid.get_innerControl().get_allRecordIds(); 
 var cellValue;
 for(i = 0; i < ids.length; i++) 
 { 
     if (grid.get_innerControl().getCellValue('estimatedvalue', ids[i]) !="")
     { 
       cellValue = grid.get_innerControl().getCellValue('estimatedvalue', ids[i]); 
       cellValue = cellValue.substring(2); 
       cellValue = parseFloat(cellValue);  
       sum = sum + cellValue;
     }
 
 }//end for   
 alert(sum);
}
I also noticed that  grid.readyState!="complete" does not work all the time.  It happens when the control is already loaded but the grid is still retrieving the data. So I changed the code to check if the records are already loaded.
See you guys……

Monday, December 19, 2011

Updating custom fields on synced outlook contacts in crm2011

CRM2011 does not support synching custom fields between CRM2011 and synced Outlook Contacts.
You can’t even select the fields to sync between CRM and Outlook. The add-in will update the custom fields between synced Outlook contacts with CRM2011.

Software Requirements:

This solution is tested on windows 7 and outlook 2010 only.

Solution components:

The solution consists of 2 components.
  • UpdateContactAddin_1_0_managed.zip (CRM2011 Managed solution)
  • OutlookAddin.zip (Outlook Addin)

1. UpdateContactAddin_1_0_managed.zip :

Download the file and import the solution. The solution creates a custom entity called “syncmapping”. The entity contains two main fields “CRM Field” and “Outlook Field”. The entity will map the fields needed to be updated between CRM2011 Contacts and Outlook Contacts. Before you add any data into the entity, go to the default solution and customize the entity to display in workplace or settings area.

For e.g. In above screen “accountrolecode” (Display Name Role) field in contact entity will update the User1 field or “User Field 1” in Outlook. clip_image004
You can choose multiple fields to update/synced Outlook Contacts as shown in the screen shot below

Note: The display name in both in Outlook and CRM2011 are different than the names used in the code. We need the “Name” field of the CRM2011. To get the proper name of the Outlook field please follow this link http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.contactitem_properties.aspx
For e.g. The name of “User Field 1” field is User1. “User Field 1” is just a display name. If the field does not exist in Outlook, the solution will create a new user defined field in Outlook.

2. OutlookAddin.zip

Extract the OutlookAddin.zip file and run the SetupUpdateContact exe. It will add a custom tab to the ribbon as shown in the following screen shot.


When the user clicks on “Update Contact”, it will display a following dialog. Enter all the values and press Update.

The above screen shot displays the values for CRM Online.

The above screen shot displays the values for on-premise CRM Deployment.
At the end of the process, the system will display a following message

Facts:
This solution updates text fields in outlook only. If you pick an optionset from CRM2011, the solution will get the text value of the field and update the field in Outlook.
The solution uses the update method to update the individual contacts. The solution does not have any automatic or scheduled syncing mechanism.
This solution is smart enough to update the contacts for the selected organization. If you are synced contacts from different organization. The system will update the contacts of the organization selected in a addin dialog.

Tips:

  • Setup the sync fields in syncmapping entity before pressing the update button
  • Please sync your outlook contacts before trying this solution.
Download this solution.

Sunday, November 13, 2011

CRM2011 Setup/Upgrade Errors and Resolutions

This is the second part of my last blog Installing CRM2011 with Precreated AD Groups.
The following are some of the errors and their resolutions encountered during installation/upgrade

Error 1

SQLSERVERAGENT (SQLSERVERAGENT) service is not running on the server ......

clip_image002


Resolution:

· Check if SQLSERVERAGENT service is running
· Open the port 445 for SQL Server.



Error 2

During the import of the organizations the following warning was received.
"Fragmented indexes were detected in the Microsoft Dynamics CRM database",

Resolution:


Re-index the organisation databases
USE MyDatabase
GO
EXEC sp_MSforeachtable @command1="print '?' DBCC DBREINDEX ('?', ' ', 80)"
GO
EXEC sp_updatestats
GO
Updating statistics ensures that queries compile with up-to-date statistics

Error 3

The following error message was received when testing the email router:
Type 'System.ServiceModel.Channels.ReceivedFault' in Assembly 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable

Resolution:


Add the account running the email router services to PrivUserGroup security group.

Error 4

The following error message was received when accessing the reports from any of the organizations:
Microsoft.Crm.Web.Reporting.SrsReportViewer.SetExecutionCredentials(ServerReport reportObj) Cannot create a connection to data source 'MSCRM'. (rsErrorOpeningConnection)
The reason was SSRS connector(reporting extensions) was installed using user other than deployment account. The SSRS service account was missing in privreportinggroup group.

Resolution:


  • · Add SSRS service account to privreporting group.
  • · Reinstall the reporting extension again using deployment account.
The process to resolve was as follows:
  1. 1. Uninstall the Reporting Extensions.
  2. 2. Go to the CONFIG DB (MSCRM_CONFIG) of CRM and update your organization's row in the Organization table to set the AreReportsPublished boolean field to FALSE.
  3. 3. Re-install the Reporting Extensions and they should publish the reports again.
Note: You will see the message about installation is republishing the reports again

FIXES FOR THE UPGRADED ORGANISATIONS

The section contains information on the issues encountered that required fixing for the upgraded organisations.

Issue 1

Unknown labels in settings group as shown in the screen shot below. This had happened to all four organisations.
image clip_image006
             Before                              After



Resolution:

Follow the Microsoft article for resolution: http://support.microsoft.com/kb/2530358.


Issue 2

The main tab is closed by default as shown in the screen shot below:
image
It is noted that this happened on multiple different locations throughout all the organisations.


Resolution:

  • Open the form in customisation mode.
  • Expand the tab, save the changes and then publish the changes.
There were few other things that did not work after upgrade. One of them was, the client has custom button to “Create Phone Cal” on contact and account form. The button was using builtin javascript function “locAddActTo(4210)”. I need to change the ribbon and javascript to fix that that function does not exist in CRM 2011.

clip_image002[9]
That’s all from me.

Saturday, November 5, 2011

Installing CRM2011 with precreated AD Groups

Last few weeks, I was working on CRM4.0 to CRM2011 upgrade.  I am doing few blogs to share my experience.  My upgrade involved moving the CRM sever and SQL server to a new severs. SSRS server was installed on the same as new SQL Server.  
I am not doing a step by step installation in this blog. I will be discussing the useful tips and solutions to some of the errors/problems I encounter.  Here are the main steps
1.    Install the CRM2011
2.    Install reporting extension(SSRS Connector) and Report Authoring Extension(Bids extensions)
3.    Backup 4.0 organization databases and restore them on  new SQL Server
4.    Import the organizations into CRM2011 using deployment manager
5.    Install/configure Email router
6.    Testing and fixing the issues.

The installation involved deploying the CRM Server on procreated AD groups.

Install the CRM2011

Installation Account Permissions

The user who is installing Microsoft Dynamics CRM should be a part of Local Administrator group on Microsoft Dynamics CRM server and on SQL Server. For more detail have a look at http://support.microsoft.com/kb/946677
Important
The deployment user should also have sysadmin permission on the SQL Server Instance to import the organization (otherwise you will get error message)

Create the AD Groups

Create the following security groups in Active Directory:
•    PrivUserGroup
•    PrivReportingGroup
•    ReportingGroup
•    SQLAccessGroup

Important•    You don’t need to create UserGroup for CRM2011.
•    Use naming conventions for creating the groups for e.g.  OrgEnvironmentNameOfTheGroup (ABCDevPrivUserGroup).
•    Need to know more about permissions on these group, click here http://support.microsoft.com/kb/946677

Create configuration xml file for precreated groups

Here is sample of the config file

<CRMSetup>
   <Server>
        <Groups AutoGroupManagementOff="true">
               <PrivUserGroup>CN=PrivUserGroup,OU=Company Name,OU=Company Name,DC=<domain>,DC=<domain_extension></PrivUserGroup>
             <SQLAccessGroup>CN=SQLAccessGroup,OU=Company Name,OU=Company Name, DC=<domain>,DC=<domain_extension></SQLAccessGroup>
                    <ReportingGroup>CN=ReportingGroup,OU=Company Name,OU=Company Name, DC=<domain>,DC=<domain_extension></ReportingGroup>
    <PrivReportingGroup>CN=PrivReportingGroup,OU=Company Name,OU=Company Name, DC=<domain>,DC=<domain_extension></PrivReportingGroup>
     </Groups>
    </Server>
</CRMSetup>

Now you need to change highlighted parts of the file to suit your system. If you like to know more about the structure chek the Microsoft article mentioned above in the post.

The easiest way to get the proper CN,OUs,DCs without making any mistakes use the dsquery command. Open the command prompt and Run
            dsquery group -name adgroupprefix* Change adgroupprefix with starting characters of your group
For e.g dsquery group -name ABCDev*

image

It will display all the information you need to fill the config file.
Just copy that and replace highlighted area in the config file above.
Save the file as config.xml.

Run CRM2011 Install

  • Open the cmd prompt and navigate the crm media  to folder containing ServerSetup.exe.
  • Run ServerSetup.exe /config C:\config.xml
  • Follow the installation wizard instructions.

Install reporting extension (SSRS Connector) and Report Authoring Extension (Bids extensions)


Reporting extension (SSRS Connector)

The deployment needs local administrator permissions to install reporting extension (SSRS Connector). The installation adds the Microsoft SQL Server Reporting Services “service account” for the associated instance of SQL Server to the PrivReportingGroup security group.
Important Reporting extensions must be installed to publish the reports and to import the organization.

Report Authoring Extension

(Bids extensions) is required to write fetchxml based reports.

Second part is coming soon........

Sunday, October 16, 2011

How to trigger "onchange" event for the fields in locked section

There is  "Scheduling Information" section on  Appointment and Service Activity entity forms.
You can not  change the properties of the fields in this section. You cannot add javascript to "OnChange" events of these fields. If you double click on any of the field in this section, you will get a message "You can not modify the properties of this element because it is with in a locked section"
















So how can you add javascript to onchange event on these fields? It is simple and here is what I did to achieve this.
  • Add a new tab to the form.
  • In the visibility section of tab unctick the "Visible by default" checkbox .


























  • In the field explore window untick "Only shows unused fields". It will display all the available entity  fields in the list.
  • Add the fields to this newly created tab. ( Fields that are also present on the locked section)
  • Add the "On Change" event to one of the field.
  • Save the changes and publish the entity.
  • Now if you change the value of field in the locked section, it will trigger the event you defined in the newly created tab's field.

Wednesday, October 5, 2011

CRM2011 User Settings Utility 2.0

Here I am with User Settings Utility 2.0. I have added some more features to version 1.0.

Here is a complete list of new features.
  1. Ability to filter users based on  Business Unit names.
  2. Ability to set the email options
    • Allow other users to send emails on user's behalf
    • Track Email Messages
    • Create Records from tracked email
  3. Ability to add/remove Startup Pane
  4. Ability to open the advance find in simple or detailed mode
  5. Ability to set Error Notification Preference
Here is link to download the solution from codeplex.

Screen Shot


Good Luck.



Sunday, September 18, 2011

How to create an email activity using REST Endpoints in CRM2011


How tough it can be to create an activity using code? It sounds very easy but there are few issues, if you are using REST Endpoints.

REST Endpoints do not support all the CRM data types. One of those data type is PartyList. PartyList is very important to create most of the activity like emails, appointments, phone calls etc.

To set the value of the PartyList field you need an array of PartyLists as you can have more than value for those fields. For e.g you can have more than one recipient for an email or you can have more than resource for an appointment.

As I mentioned earlier, REST Endpoints do not support PartyList, So its is impossible to assign value to these fields. If you look at DataSet returned by the Rest Endpoints, It looks like they are treating PartyList fields like string fields.

image

These values does not even return the guid or name of the PartyList entity. if you look at sender field in the screen shot above, it does not have guid or the name of the system user who sent this email.
I tried the same using following code:

email.Sender="crm2011@emailops.com.au";
var partlistcollection = new Array(); //tried to create an array of PartyLists

partlistcollection[0] = {Id: "8384E684-7686-E011-8AF0-00155D32042E",LogicalName: "contact",Name: "Amreek Singh"};
email.ToRecipients=JSON.stringify(partlistcollection);

But it did not work, if you pass a string value to the PartyList fields, You won’t get any error message but you won’t see any value in those fields on a created entity. 

Now here is the solution. You need to create an activity (in this case it’s  an email) first and then create a PartyList entity and link it back to the created activity.

function CreateEmail() {
alert("CreateEmail Begin");

var email = new Object();
email.Subject = "Sample Email Using REST";
SDK.JScriptRESTDataOperations.Create(email, "Email", EmailCallBack, function (error) { alert(error.message); });
}

// Email Call Back function
function EmailCallBack(result)
{
var activityParty=new Object();
// Set the "party" of the ActivityParty // EntityReference of an entity this activityparty relatated to. 
activityParty.PartyId = {
  Id: "8384E684-7686-E011-8AF0-00155D32042E",//replace this with the contactid from your system.
  LogicalName: "contact"
};
// Set the "activity" of the ActivityParty
// EntityReference.
activityParty.ActivityId = {
  Id: result.ActivityId, 
  LogicalName: "email"
};
// Set the participation type (what role the party has on the activity).
activityParty.ParticipationTypeMask = { Value: 2 }; // 2 mean ToRecipients
SDK.JScriptRESTDataOperations.Create(activityParty, "ActivityParty",ActivityPartyCallBack , function (error) { alert(error.message); });
}

function ActivityPartyCallBack(reuslt)
{
alert("Process Completed");
}

activityParty.ParticipationTypeMask = { Value: 2 }; is very important as it will specify if this PartList is sender/recipient/resource etc  of the activity.

Here is the link to complete list of activityParty.ParticipationTypeMask click here.
For this sample, I have used the generic REST CRUD data operations library created by Jim Daly.
Add references to following Java Script  web resources to try the solution.
  • SDK.JScriptRESTDataOperations
  • JSON2
Here is the link to unmanaged solution RESTEmailSolution_1_0
  • I hope this helps.

Tuesday, September 6, 2011

How to change the maximum no. of controls on CRM2011 Dashboards

The maximum number of controls allowed on CRM2011 dashboards are 6. You cannot put the more than 6 graphs/charts/iframes/webresources etc. on the dashboard.
This setting is applied to the server not a organisation setting. So you cannot change this setting for CRM Online but you can change this for an on-premise installation.
There are two ways to do it.
  1. Using Deployment Web Service (http://myservername/xrmdeployment/2011/deployment.svc)
  2. Using Window Power Shell
Windows Power Shell Option is the easiest one.
  • Open the Windows Power Shell
  • Add the Microsoft Dynamics CRM PowerShell snap-in using
Add-PSSnapin Microsoft.Crm.PowerShell
you may get the message saying something like “Add-PSSnapin : Cannot add Windows PowerShell snap-in Microsoft.Crm.PowerShell because it is already added.” It is okay.
  • Run the following 3 command
$setting = Get-CrmSetting -SettingType DashboardSettings
$setting.MaximumControlsLimit = 7 (// you can change this number)
Set-CrmSetting -Setting $setting
Here is my screen shot with 7 charts.
    Charts

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.

Sunday, July 17, 2011

Step by Step - Hiding “Add Existing” button in CRM 2011

In MSCRM 4.0, hiding the “Add Existing” button was a very common request. This blog will show how to do this in CRM 2011. When we click on associated record link in left navigation of an entity form, we can see a "Add Existing" button on the ribbon. To hide this button we need to modify the ribbon of the associated entity.
The following screen shot is of an account entity. If we click on "Contacts" on left navigation, we can see the "Add Existing Contact" button on the ribbon. To hide this button we need to modify the ribbon of the contact entity.
image
Here are the steps
  • Create a new solution.
  • Add the contact entity to the solution. Do not include any required components or dependent components to the solution.
  • Export the solution and unzip the solution file.
  • Open the customizations file and look for “<RibbonDiffXml>” tag.
  • Replace the <CustomActions /> with
<CustomActions>
  <HideCustomAction Location="Mscrm.SubGrid.contact.AddExistingAssoc" HideActionId="Mscrm.SubGrid.contact.AddExistingAssoc.HideAction" />
  <HideCustomAction Location="Mscrm.SubGrid.contact.AddExistingStandard" HideActionId="Mscrm.SubGrid.contact.AddExistingStandard.HideAction" />
</CustomActions>
  • Save the file.
  • Replace the customizaions.xml file in your zip solution with this file.
  • Import the solution and publish the changes.
Note: Replace the highlighted "contact” text with your entity name. It can be “opportunity” or a custom entity like “new_entity” etc.

Good day…………..

Wednesday, June 29, 2011

CRM 2011 Postcode Lookup Solution Version 1.0

I have created this postcode lookup solution. You can download the managed solution from here. The name of the solution file is PostCodeSolution_1_0_managed. The solution consists of 4 files

  • new_Json2.js (Javascript webresource)
  • new_PostCodeScript(Javascript webresource)
  • new_postcode(custom entity to store postcode information)
  • new_SuburbOptions (HTML webresource)

How does it work:

  • User enters the postcode on postal code field and onchange event of the field, the solution will retrieve postcode records related to entered postcode.
  • If there is a record related to entered postcode, the solution will populate the state, suburb and country fields for you.
  • If there are more than one records related to entered postcode, solution will prompt you to select the appropriate entry.

In the following screen shot, I entered 2000 in postal code field and system prompt to pick the relevant city/suburb.

image

Pros:

  • Clean data entry: The solution will help to minimise data entry errors in address fields.
  • Don’t need to create custom picklist state/or country attributes.
  • Using built-in address fields means, don’t need to modified some of the built-in reports.

Cons:

  • The solution is working only address1_postalcode attribute of an entity. It can work on account , contact or any other entity that has built in address fields.
  • The solution is hard coded to fill built in adress1_city, address1_stateorprovince, address1_country fields only.

Version 2.0 :

I will release version 2.0 soon, which will not use hard coded attributes.

Installation Directions:

  1. Install the postcode solution.
  2. Open the account or contact entity form in customisation mode.
  3. Double click on Postal Code attribute.
  4. Add new_Json2.js and new_PostCodeScript to form libraries.
  5. Call loadPostCodeRequest function from new_PostCodeScript.Save the changes and publish them.

image





















6. Import the Postcodes.

image

  • Import the file into new_postcode entity.

    Note: You can download the US postal Codes from US ZIP CODES.

    You are good to go.

    Feedback please.

Thursday, June 16, 2011

Tips for using REST endpoints in CRM 2011(Rest endpoints browser)

Using REST endpoints with json2 are the simplest way to retrieve data in CRM 2011. The code is clean and simple. Here is a sample retrieve request

retrieveAccountsReq.open("GET", getRESTUrl() +

"/new_postcodeSet?$top=20&$select=new_name,new_Country,new_Suburb,new_State,new_postcodeId&$filter=new_name
eq ('"
+ postcode + "')", true);


The above request is used to retrieve the custom entity (new_postcode) dataset where new_name is equal to postcode.

The result will look like this
image
To get the fieldnames for an entity you can use http://servername:portnumber/organization name/XRMServices/2011/OrganizationData.svc/entitySet

The result will look like this

image

You can even paste the query in the browser and check the result of the query. The following query will display all the records with postcode 2010.

http://tcrm2010:5555/CRM/XRMServices/2011/OrganizationData.svc/new_postcodeSet?$select=new_name,new_Country,new_Suburb,new_State,new_postcodeId&$filter=new_name

The result will look like this

image

Conclusion

REST endpoints are the best way to retrieve data on client site. You can even see the result of the query in the browser.

Happy Programming……..

Wednesday, June 8, 2011

How to start a Dialog from Application Ribbon (CRM 2011)

To start the Dialog from the Application Ribbon, you need to 3 things
  1. Application Ribbon Button (and Button Images)
  2. JavaScript to call the Dialog
  3. Dialog
I have attached the unmanaged solution here. The solution contains the following components
image
  • “Application Ribbons” contains the definition of the button.
  • “new_custom16x16” and “new_custom32x32” are image files for the button.
  • “new_dialogjavascript” is a JavaScript web Resource. It contains the JavaScript code to open the dialog.
  • “Sales Call” is dialog script

Detail Explanation

Application Ribbon

   1:  <RibbonDiffXml>
   2:      <CustomActions>
   3:        <CustomAction Id="Sample.{!EntityLogicalName}.MainTab.MyURL.CustomAction" Sequence="41" Location="Mscrm.HomepageGrid.{!EntityLogicalName}.MainTab.Workflow.Controls._children">
   4:          <CommandUIDefinition>
   5:            <Button Id="Sample.{!EntityLogicalName}.MainTab.MyURL.Button" Command="javascript.Command" LabelText="Sales Call" ToolTipTitle="Sales Call" ToolTipDescription="Sales Call" TemplateAlias="o1" Image16by16="$webresource:new_custom16x16" Image32by32="$webresource:new_custom32x32" />
   6:          </CommandUIDefinition>
   7:        </CustomAction>
   8:      </CustomActions>
   9:      <Templates>
  10:        <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
  11:      </Templates>
  12:      <CommandDefinitions>
  13:        <CommandDefinition Id="javascript.Command">
  14:          <EnableRules>
  15:            <EnableRule Id="Mscrm.Enabled"/>
  16:          </EnableRules>
  17:          <DisplayRules />
  18:          <Actions>
  19:            <JavaScriptFunction
  20:                Library="$webresource:new_dialogjavascript"
  21:                FunctionName="callDialog">
  22:            </JavaScriptFunction>
  23:          </Actions>
  24:        </CommandDefinition>
  25:      </CommandDefinitions>
  26:      <RuleDefinitions>
  27:        <TabDisplayRules />
  28:        <DisplayRules />
  29:        <EnableRules />
  30:      </RuleDefinitions>
  31:      <LocLabels />
  32:    </RibbonDiffXml>
  • “CustomAction” tag define the location of the button ( which entity, which group, sequence etc).
  • “Button” tag defines the text, images, tooltip of the button. The most import attribute of “Button” tag is “Command”. In this solution Command = javascript.Command.
  • “CommandDefinition” tag defines the javascript.Command mentioned in “Button” tag.
  • <EnableRule Id="Mscrm.Enabled"/> this line makes the button enabled on the ribbon.
  • “Actions” tag defines which JavaScript webresource and which function in that webresource will be called on button click.
Note: If you already a custom app ribbon button in your solution and you import any other unmanaged solution with “Application Ribbon” file in it. it will over write your custom button. Take a backup of your solution before you import any unmanaged solution.
    function getOrg() {
        ///<summary>
        /// get organisation
        ///</summary>
      
        var Org = "";
        if (typeof GetGlobalContext == "function") {
            var context = GetGlobalContext();
            Org = context.getOrgUniqueName();
        }
        else {
            if (typeof Xrm.Page.context == "object") {
                Org = Xrm.Page.context.getOrgUniqueName();
            }
            else
            { throw new Error("Unable to access Organisation name"); }
        }
       
        return Org;
    }

    function getUser() {
        ///<summary>
        /// get logged in user
        ///</summary>
      
        var User = "";
        if (typeof GetGlobalContext == "function") {
            var context = GetGlobalContext();
            User = context.getUserId();
        }
        else {
            if (typeof Xrm.Page.context == "object") {
                User = Xrm.Page.context.getUserId();
            }
            else
            { throw new Error("Unable to access the UserId"); }
        }
      
        return User;
    }

    function callDialog() {
    
    var url="/" + getOrg() + "/cs/dialog/rundialog.aspx?DialogId=%7bB7D825D7-7EF6-4713-AC11-284546FEB260%7d&EntityName=systemuser&ObjectId=" + getUser();
    window.open(url, "", "status=no,scrollbars=no,toolbars=no,menubar=no,location=no");
    //window.open(url);

    }
The JavaScript Webresource has three function
  • getOrganisation() – to get context organisation
  • getUser()-to get the logged in user
  • callDialog()- will call the dialog. you can change the DialogId to call your own dialog.
This example is using a dialog attached to the user entity, so we don’t need to create any record to run the dialog. The code picks up the logged in user and run the process.
Sales Call Dialog

Sales Call dialog is very simple but meaningful dialog process. Steps are as follow.
  1. Ask for customers first name and last name
  2. Ask if customer exist in the system
    • Search for the customer
  3. Else ask for address information
  4. Ask for the product customer is interested in
  5. Ask if sales rep want to create relevant records. if sales rep select yes create the contact and/or opportunity records.

Note: This dialog does not add product to the opportunity.

Here are some screen shots

image


 
image

 
image

 
Bye…………...

Tuesday, May 17, 2011

How to set Date fields in MSCRM 2011 Dialogs

If you are capturing a date in a dialog, it is not possible to assign that value to the crm datetime field. It can be done by creating workflow assembly.

Create a workflow assembly, which takes a string as input parameter and return date as output parameter. Here is code..
using System;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
 
namespace DialogDate
{
public class DialogDate:CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
  
// Create the context
    //IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
    //IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
    //IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    string sdate = StringInput.Get<string>(executionContext);
    DateOutput.Set(executionContext, DateTime.Parse(sdate));
}
 
[Input("string")]
[Default("10/11/2010")]
public InArgument StringInput { get; set; }
 
[Output("Date")]
[Default("01/01/01")]
public OutArgument DateOutput { get; set; }
 
}
}
 
Register the assembly and use it in your dialog.

Call the assembly and pass the date string and use the return value to set the date field as shown in screen shots below.