Wednesday 13 December 2017

{Know-How} MSCRM JS - show or hide Navigation items using display name or Label



Code Snippet to show or hide a navigation using display name

Function to show or hide Navs
ToggleNavigationItem = function (navName,isVisible) {
    var navs = Xrm.Page.ui.navigation.items.get();
    for (var i in navs) {
        var nav = navs[i];
        if (nav.getLabel() === navName) {
            nav.setVisible(isVisible);
        }
    }
};

Usage
ToggleNavigationItem("Accounts",false); //Hide
ToggleNavigationItem("Accounts",true); //Show

Note: The labels are case sensitive

Thursday 2 November 2017

CRM 2016/15/13 to D365 - Data Migration - Issues with Business process flows and workarounds



Recently I have done few migration projects from CRM 2016 or older version to D365 v9.

Due to the Business process flow architectural update in v9, we have faced few hurdles. Suddenly the blogger inside me wanted to document the same 😈

Here is the Killer error message that occurs while create and update

"The traversed path should end with the new active stage"

What is the fix for the BPF while record create?

Issue anlysis:
Traversed path field is the culprit. This field contains the traversed stages in a business process flow. For some reason the process stages value in traversed path is not in sync with current business process stage hope this happens when we switch between process. This breaks the record create with error "The traversed path should end with the new active stage"

Fix:
Exclude/Unmap the field traversed path from migration and we should be good.

What is the fix for the BPF while record update?
Issue anlysis:
Once the record with BPF get into D365 V9, one more record will be created in related BPF entity for the processid in that record. After this, when we try to update the process via data integration it breaks with above error. This is due to the fact that a process change is not only related to stageid/processid fields and the same involves multiple related BPF entities.

Fix:
Before update clean-up the existing process in related BPF entities for the specific record and then update record.

Monday 23 October 2017

{Know-how}D365 Customer Engagement- Sub-grid create new record or lookup to existing



In a sub-grid on click of "+" sign, manage create of new record or lookup to existing one. This is applicable to 1:N/N:1 relationship.

Ex:
Entity1 is related to Entity2 in 1:N fashion. Entity1 will contain subgrid and Entity2 will contain Entity1 lookup


To enable create on click of "+" sign
  • Go to related lookup field in the related entity - Entity1 lookup field in Entity2
  • Customize the field and make it mandatory
  • If the field is mandatory, then automatically the "+" sign will point to create of new record

To enable add existing on click of "+" sign
  • Go to related lookup field in the related entity - Entity1 lookup field in Entity2
  • Customize the field and make it non-mandatory
  • If the field is mandatory, then automatically the "+" sign will point to existing record

Note: This behavior is not applicable to some of the OOB relationships.

Friday 15 September 2017

{know-how} D365 CRM - Get optionset label from Stringmap using FetchXML - c#,JS, SSRS



Hello All,

Good to be back with another know how post. Lets go through a simple way to retrieve a MSCRM optionset label using fetchxml that can be used with C#/JS/SSRS.

Usual way to retrieve an optionset value in c# or JS is by using RetrieveAttributeRequest and refer this blog for the same.

RetrieveAttributeRequest - Option set label retrieval

This time, wanted to stick with old school SQL approach by using stringmap table, so replicated the same logic into fetchxml query and below is the simple fetchxml. This will be handy in SSRS report development to retrieve optionset details.

What is stringmap?
Stringmap is a table in crm which contains all the optionset options and its related details. Will write a quick article soon around stringmap and its fields 😉

Coming back to the topic, below is the fetchxml to get optionset label, hope the fields are self explanatory.

FetchXML

<fetch>
    <entity name="stringmap" >
        <attribute name="value" />
        <filter type="and" >
            <condition attribute="objecttypecodename" operator="eq" value="account" />
            <condition attribute="attributename" operator="eq" value="customertypecode" />
            <condition attribute="attributevalue" operator="eq" value="2" /> 
        </filter>
    </entity>
</fetch>

Result


<result>
    <value>Consultant</value>
</result>

Thursday 7 September 2017

{know-how} MSCRM Actions - Newly created actions not available or missing in plugin registration tool



When we create a new action, sometimes the new action will not be visible in plugin registration tool, this could be due to metadata refresh. Try below options and it should be visible after this.
  1. Deactivate and activate action
  2. Refresh the plugin registration tool
  3. Close and Reopen the plugin registration tool - This option works most of the time

{know-how} MSCRM FetchXML SSRS - Improve performance with No-Lock - FetchXML Nolock



A quick tip around improving CRM data retrieval performance using fetchxml, this is applicable to both RetrieveMultiple  and SSRS performance.

What is no-lock?
Whenever we query CRM using fetchxml,a lock is issued against the table. when we use No-lock the process of issuing lock is skipped. This type of data retrieval is also called as dirty read because there is a chance that you might read the uncommitted data before rollback.

Advantage?

  • Improves SSRS report performance or RetrieveMultiple performance on high transaction oriented tables


Example:

<fetch mapping="logical" no-lock="true" >
    <entity name="account" />
</fetch> 

Sunday 20 August 2017

{Know-how} D365 - SSRS Report Prefiltering fetchxml/SQL


Hello All,

FetchXML and SQL querying are some of the best possible ways to retrieve data from MSCRM for BI or Data manipulation.


Previous articles around fetchxml querying are as follows, now lets jump into fetchxml/sql prefiltering


What is prefiltering and why should I use it?

 As the name suggests, before execution of the report we restrict the scope to work based on relevant records. This is improves performance and also enables advanced find filtering before report execution.


How to enable prefiltering for FetchXML datasets?
  • Under entity node, add an attribute enableprefiltering attribute and set its value to true

 <fetch distinct="false" mapping="logical">
   <entity name="account" enableprefiltering="1">
      <attribute name="accountid" />
      <attribute name="name" />      
   </entity>
 </fetch>


How to enable pre-filtering for SQL datasets?
  • Add an alias with prefix CRMAF_ to the filtered view name
SELECT accountid, name  
FROM FilteredAccount AS CRMAF_FilteredAccount

{Know-how} D365 CRM Javascript - Optionset related methods - get/set/add/remove/retrieve all/remove all


Hello all,

Optionsets are one of the key data capturing controls and manipulating options are essential to achieve an efficient UX experience in all systems including our MSCRM. Below are the quick reference to D365 CRM optionset related javascript methods, which helps in achieving the same.

Here we are going to use "Status Reason"(statuscode) field as our optionset. Lets not wait anymore, Js snippets are as follows😉


Get the selected option - returns the label/text and value

Xrm.Page.getAttribute("statuscode").getSelectedOption()
{"value":1,"text":"Active"}



Get the selected option's value

Xrm.Page.getAttribute("statuscode").getValue()
1



Get the selected option's text/label

Xrm.Page.getAttribute("statuscode").getText()
Active



Get all the options for the optionset - Returns an array of options

Xrm.Page.getAttribute("statuscode").getOptions()
[{"value":1,"text":"Active"},{"value":100000000,"text":"Test1"},"value":100000001,"text":"Test2"}]



Set the optionset value(selected option) - Set to Test1

Xrm.Page.getAttribute("statuscode").setValue(100000000)



Remove an option from optionset - Remove Test1

window.frames[0].Xrm.Page.getControl("statuscode").removeOption(100000000)



Add an option to optionset - Add Test1 Again


Xrm.Page.getControl("statuscode").addOption({value:100000000,text:"Test1"})



Remove all options from an optionset

Xrm.Page.getControl("statuscode").clearOptions()


Hope this helps!

Thursday 27 July 2017

{Know-how} Add a ribbon button using Ribbon WorkBench

Hello,

Though its an age old topic, would like to write down step-by-step approach to add an ribbon button for reference.

Prerequisite:
CRM instance with ribbon workbench solution  or Xrmtoolbox



Scenario:
Add a ribbon button on account and on click of the ribbon button show the URL of the record.

Steps:
  1. Open ribbon workbench
  2. Select the solution that contains account entity. 
  3. Add a new js command. Using command we can define JavaScript function or an URL action called on click of ribbon button.
  4. Lets add a Javascript action and call our Alert function which is available in existing Js webresource
  5. Now add the ribbon button and fill in the necessary details. Also link the command to the button and publish the changes
  6. Once done navigate to account and click the button to view the alert
Code snippet to alert URL:
 function alertURL() {  
 var url= "{0}/main.aspx?etn={1}&id={2}&pagetype=entityrecord"  
  Xrm.Utility.alertDialog( url.replace("{0}",Xrm.Page.context.getClientUrl()).replace("{1}", Xrm.Page.data.entity.getEntityName()).replace("{2}", encodeURIComponent(Xrm.Page.data.entity.getId())));  
 }  


HTH! Please leave your feedback on comments section!

Wednesday 26 July 2017

{Know-how} Dynamics 365 - SSRS pass prefiltering report parameter and open report using URL - JavaScript


Reporting is an essential part in any system. In Dynamics CRM, we have wide variety of reporting options that are flexible enough to meet most of the requirements and one such scenario is explained here. At times we may need to open a report via URL inside an IFrame or in a new window based on the requirement and in our scenario it is new window.


Scenario:
On click of a ribbon button in an account record, open account prefiltered report in a new window.

Code Explanation:
To form a report URL we need following
  1. Organization URL - Organization URL  and in my case https://contoso.crm.dynamics.com
  2. Report Id- unique identifier of the report
  3. Action - It can be either run or filter and for our scenario it should be run
  4. Context - It should be records
  5. ETC - Entity type code and in our case its for account
  6. Record Id - unique identifier of the current record
Note: The parameters 4,5 and 6 are specific to prefiltering. Skip the same if you want to run a report without preregistering


JavaScript code snippet:
             var orgUrl = Xrm.Page.context.getClientUrl();  
             var action = "run";  
             var context = "records";  
             var reportId = "report id goes here";
             var recordid = Xrm.Page.data.entity.getId().replace("{", "").replace("}", "");  
             var etc = Xrm.Page.context.getQueryStringParameters().etc;  
             var url = orgUrl +  
               "/crmreports/viewer/viewer.aspx?action=" + encodeURIComponent(action) +  
               "&context=" + encodeURIComponent(context) +  
               "&id=%7b" + encodeURIComponent(reportId) + "%7d" +  
               "&records=%7b" + encodeURIComponent(recordid) + "%7d" +  
               "&recordstype=" + encodeURIComponent(etc);  
             var customParameters = encodeURIComponent(url);  
             Xrm.Utility.openWebResource("reportcontainer.html", customParameters)  

HTH! Please leave your valuable feedback in comments!

SSRS shared dataset deployment error - The feature: "Shared dataset" is not supported in this edition of Reporting Services.



Today I was deploying reports using visual studio and faced a weird error while creating shared dataset. The error is as follows

The feature: "Shared dataset" is not supported in this edition of Reporting Services

After a bit of analysis found that issue is related to the edition of SQL Reporting server. Only certain editions of SQL server supports shared datasets and the rest doesn't.

Refer this Microsoft article for more information.

The following are the editions that should not support shared datasets
  • Web
  • Express with Advanced Services
  • Express with Tools
  • Express

and the below are the one's which should support the same
  • Enterprise
  • Standard
  • Developer

Wednesday 12 July 2017

{know-how}Dynamics CRM 365 - Query Hierarchical data - D365


Hierarchical querying, an interesting way of retrieving data for analysis, transforming and reporting. In latest version of CRM, we can use fetchxml to query and retrieve hierarchical data.

The hierarchical data retrieval in fetchxml can be achieved using following filter condition operators
  • above
  • eq-or-above
  • under
  • eq-or-under
  • not-under
  • eq-owneduseroruserhierarchy
  • eq-useroruserhierarchyandteams
Prerequisite:
Make sure the specific relationship is hierarchy enabled.
Sample Scenario:
Find all child account hierarchy for the parent account.

Fetchxml:
In the below fetchxml the highlighted operator called under will fetch all the accounts that are under the given accounts hierarchy.


<fetch>
    <entity name="account" >
        <all-attributes/>
        <filter type="and" >
            <condition attribute="accountid" operator="under" value="a9df53b3-e31c-e711-8108-5065f38af901" />
        </filter>
    </entity>
</fetch>

Try all the above filter operators and also refer below MSDN article for more info and do not forget to go through restrictions.

https://msdn.microsoft.com/en-in/library/dn817893.aspx

Happy learning!

Saturday 8 July 2017

Dynamics 365 CRM July 2017 update - List of depreciated functionalities in D365

Hello All,

With the new upcoming D365 CRM July 2017 Update, some of functionalities are depreciated and their usage will be supported by Microsoft until they are officially removed. This list is based on the D365 customer engagement announcement from Microsoft team and the same helps in new release readiness.

In general, whenever a feature is depreciated, its better to start using the alternative immediately as the depreciated functionality will be removed anytime sooner or later.

As an architect or developer, its important to know the latest list of depreciated functionalities and start replacing them in future developments and upgrades. 

Below are the list of depreciated functionalities apart from some of the client API's
  • Dynamics 365 for Outlook (Outlook client)
  • Dynamics 365 for Outlook (Outlook client) is deprecated
  • Service scheduling in Dynamics 365 for Customer Service is deprecated
  • Dialogs are deprecated
  • Usage of Parature knowledgebase as the Dynamics 365 knowledge management solution is deprecated
  • Project Service Finder app is deprecated
  • Contracts, Contract Line Items, and Contract Templates entities are deprecated
  • Standard SLAs in Dynamics 365 for Customer Service are deprecated
  • Relationship Roles are deprecated
  • Mail Merge is deprecated
  • Announcements are deprecated
  • Ready-to-use business processes available through Add Ready to Use Business Processes setting are deprecate
  • EntityMetadata.IsInteractionCentricEnabled property is deprecated
  • Silverlight (XAP) web resource is deprecated
Reference with full details on depreciated functionalities and their replacements: https://docs.microsoft.com/en-us/dynamics365/get-started/whats-new/customer-engagement/important-changes-coming

Disclaimer: This details are based on Microsoft D365 customer engagement announcements and the purpose of this blog post is to spread awareness.

From Microsoft docs regarding this topic:
The announcements and deprecations described in this topic apply to Dynamics 365 Customer Engagement as of the July 2017 Update. Administrators and IT professionals should use this information to prepare for future releases of Dynamics 365. Customer Engagement refers to the applications that make up the CRM portion of Dynamics 365, which includes the Sales, Customer Service, Field Service, and Project Service Automation applications.
“Deprecated” means we intend to remove the feature or capability from a future major release of Dynamics 365. The feature or capability will continue to work and is fully supported until it is officially removed. This deprecation notification can span a few years. After removal, the feature or capability will no longer work. We are notifying you now so you have sufficient time to plan and update your code before the feature or capability is removed.

Dynamics 365 CRM July 2017 update - List of depreciated JavaScript client API's in D365

Hello All,

With the new upcoming D365 CRM July 2017 Update, some of client API's are depreciated and their usage will be supported by Microsoft until they are officially removed. This list is based on the D365 customer engagement announcement from Microsoft team and the same helps in new release readiness.

In general, whenever a feature is depreciated, its better to start using the alternative immediately as the depreciated functionality will be removed anytime sooner or later.

As an architect or developer, its important to know the latest list of depreciated functionalities and start replacing them in future developments and upgrades. 

Apart from other depreciated functionalities, below are the list of client API's that are depreciated,

Xrm.Page
Xrm.Page.context
Xrm.Page.context.getQueryStringParameters
Xrm.Page.context.getTimeZoneOffsetMinutes
Xrm.Page.context.getUserId
Xrm.Page.context.getUserLcid
Xrm.Page.context.getUserName
Xrm.Page.context.getUserRoles
Xrm.Page.context.getIsAutoSaveEnabled
Xrm.Page.context.getOrgLcid
Xrm.Page.context.getOrgUniqueName
Xrm.Page.data.entity.save(string)
Xrm.Page.data.entity.getDataXml
GridRow.getData
GridRowData.getEntity
Xrm.Mobile.offline
parent.Xrm
addOnKeyPress
removeOnKeyPress
showAutoComplete
hideAutoComplete
Xrm.Utility.alertDialog
Xrm.Utility.confirmDialog
Xrm.Utility.isActivityType
Xrm.Utility.openEntityForm
Xrm.Utility.openQuickCreate
Xrm.Utility.openWebResource

Reference with full details on depreciated API and their replacements: https://docs.microsoft.com/en-us/dynamics365/get-started/whats-new/customer-engagement/important-changes-coming

Disclaimer: This details are based on Microsoft D365 customer engagement announcements and the purpose of this blog post is to spread awareness.

From Microsoft docs regarding this topic:
The announcements and deprecations described in this topic apply to Dynamics 365 Customer Engagement as of the July 2017 Update. Administrators and IT professionals should use this information to prepare for future releases of Dynamics 365. Customer Engagement refers to the applications that make up the CRM portion of Dynamics 365, which includes the Sales, Customer Service, Field Service, and Project Service Automation applications.
“Deprecated” means we intend to remove the feature or capability from a future major release of Dynamics 365. The feature or capability will continue to work and is fully supported until it is officially removed. This deprecation notification can span a few years. After removal, the feature or capability will no longer work. We are notifying you now so you have sufficient time to plan and update your code before the feature or capability is removed.

Wednesday 21 June 2017

{know-how} Or condition between linked entities or multiple entites in MSCRM Fetchxml

I have seen many struggling to achieve an OR condition between filters in parent entity and the linked entity. So today lets see how to overcome this issue and how to achieve an OR condition spanning between multiple entities.

Scenario:
I want to select an account with specific phone number or its primary contacts phone number is equal to the given number

Gap:
In this scenario we may not able to form an or condition for the filters as the filters are split between the parent(account) and the linked entity(contact) in advanced find editor. But the same can be achieved in fetchxml.

Solution:
Fetchxml supports conditions from other linked entities, the trick is to use an attribute called entityname in condition node to specify which entity it links to. The same is highlighted below.



<fetch version="1.0" output-format="xml-platform" mapping="logical" >
    <entity name="account" >
        <attribute name="accountid" />
        <filter type="or" >
            <condition attribute="telephone1" operator="eq" value="1234" />
            <condition entityname="contact" attribute="telephone1" operator="eq" value="1234" />
        </filter>
        <link-entity name="contact" alias="contact" from="contactid" to="primarycontactid" />
    </entity>
</fetch>

Hope this helps!

{know-how} Set a lookup value on create/update of a record using MSCRM WebApi - An undeclared property Error



Recently faced an error while creating and updating records in CRM using WebAPI. The issue was around setting a lookup value and following is the error message

An undeclared property new_primaryincident which only has property annotations in the payload but no property value was found in the payload. In OData, only declared navigation properties and declared named streams can be represented as properties without values.


Fix:
The issue is due to the fact that whenever we set a lookup value we need use schema name and not the logical name. In my case I had to use "new_PrimaryIncident" instead of  "new_primaryincident".

Code snippet:

// code with issue
"new_primaryincident@odata.bind":"/incidents(10000000-0000-0000-0000-000000000000)" 

// code after fix
"new_PrimaryIncident@odata.bind":"/incidents(10000000-0000-0000-0000-000000000000)"

Hope this helps!

Tuesday 20 June 2017

{know-how}MSCRM open external url using Xrm.Utility.openWebResource - D365



Hello All,

Good to be back with another know-how post, lets see how to open an external url using Xrm.Utility.OpenWebresource

Scenario:
On click of search ribbon button in account form of CRM, open an external url(bing search) using Xrm.Utility.openWebResource

Why to use Xrm.Utility.openWebResource
Window.open is not a supported method to open a webresource

How?
  1. Open a custom HTML webresource using openWebResource method and pass the encoded external URL as query string parameter
  2. In the webresource, redirect to the encoded URL in  parameter.

Steps and code explanation: 
  1. Create a custom HTML webresource(use the code below).
  2. Onload of page, call a js function named getParameters.
  3. The function will retrieve the encoded URL available in query string
  4. Then it will redirect to the encoded external URL(Bing search)

Code snippets

To open Webresource:
var customParameters = encodeURIComponent("<URL goes here>");
Xrm.Utility.openWebResource("ram_webContainer.html", customParameters)

HTML webresource named ram_webContainer.html:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <script type="text/javascript" src="ClientGlobalContext.js.aspx"></script>
    <script type="text/javascript">
        var CRMCustomParameters = [];
        var getParameters = function () {
            var Parameters = GetGlobalContext().getQueryStringParameters();
            if (Parameters && Parameters.Data) {
                location.href = Parameters.Data;
            }

        }
       
    </script>
</head>
<body onload="getParameters()">

</body>
</html>

Hope this helps!

Friday 16 June 2017

{know-how} Editablegrid disable fields conditionally using Javascript - Dynamics CRM D365 - D365_EditableGrid#1


Editable grid is an awesome way to manage related child records effectively and efficiently within few clicks and I personally love it for the same. For this kind of requirements, building a custom grid was the story for long time and now Editable grid is a real savior.

Before deep diving into code , below are the supported JavaScript events for editable grid. 

Scenario: In account form we have contact editable grid. Whenever the account name is DisableFields(felt lazy to find another field :P), disable all the fields in the editable grid row.

Event Registration:
  1. Open form editor and then open editable grid properties
  2. Navigate to Events tab and select Event named OnRecordSelect
  3. Add a function to the event.While adding function do not forget to enable "Pass execution context as first parameter"


Code Explanation:
To access the current row(entity record) we need the editable grid's formcontext which is a part of the context passed as first parameter. From there the rest of the code is similar to our traditional js implementations. 

function setFieldsDisabled(context) {
    var name = Xrm.Page.getAttribute("name").getValue();
    if (name == "DisableFields") {
        var contact = context.getFormContext().data.entity;
        contact.attributes.forEach(function(field, i) {
            field.controls.get(0).setDisabled(true);
        });
    }
}

Hope this helps! 

Friday 9 June 2017

Mobile compatible development - disable all fields using JS - Microsoft Dynamics CRM - MoCA_Tip#3


Hello All,

Lets go though a quick tip on best practice around disabling all fields using JavaScript in MoCA.

Issue:
In traditional CRM JS development, we tend to use  getDisabled function to identify whether a control is disabled or not and setDisabled to enable or disable a field.

But in MoCA there are some controls which do not expose the above functions which result in JS error(not defined or not found).

Fix:
Before calling the function validate whether the function exist or not  and then call the same. By this way we can avoid unnecessary chaos in our JS.

Code Snippet:

if (control && control.getDisabled && !control.getDisabled()) {
   control.setDisabled(true);
}


Refer this blog for MoCA compatible disable all fields script

Don't forget to go through previous tips if you have missed,
  1. Form Selector and its usage

Monday 29 May 2017

Mobile compatible development - formSelector - Microsoft Dynamics CRM - MoCA_Tip#2

After the MoCA wave with D365, we are rapidly evolving in mobile space. This evolution demands mobile compatible development and the same is our key to success.

I have planned to share my experience with MoCA as a series and the link for previous tips can be found at the end of this blog.

lets jump on to the tip now,

Its common to have Xrm.Page.ui.formSelector in our JavaScript development and the same is used to identify current form and for form navigation.

Xrm.Page.ui.formSelector is not supported in mobile!
In MoCA formselector is not available and usage of the same will result in form error. This is because mobile application doesn't have multiple forms. 

From MSDN Library:
Dynamics 365 for phones and tablets does not provide the capability to switch between forms. If you have more than one main form for an entity, the one displayed depends on the form order set and which security roles are assigned to the form.


Ways to overcome this issue,
  1. Preferred solution is to avoid using multiple forms 😉  - This may sound crazy, but its better to design the main form in a way that everything fits into it. This automatically streamlines all your form related development mobile compatible. 
  2. Another way is to conditionally avoid form selector piece of code by validating the client. If the client is mobile skip the specific portion of code, sample code snippet is as follows

if (Xrm.Page.context.client.getClient() != "Mobile")
{
    //Form selector code goes here

}


Don't forget to go through previous tips if you have missed,
  1. Document template Fix
  2. Hidden tabs and Mobile application organization settings

Happy learning!



Thursday 25 May 2017

MSCRM - Email Tracking token understanding and configuration

In this article we are going to understand the purpose, configuration and tracking of the Email tracking token.

What is tracking token and why we need it?

Whenever an email is sent via CRM, a tracking token is suffixed to subject line by default and it is used for email tracking and correlation purpose.

This helps in auto mapping/matching related conversations to the regarding object. If its turned off, then we may need to compare key words in subject, sender and receiver to find the best match and this results in reduced probability.

Example Tracking Token: CRM:00010001



Should we disable tracking token?

Sometimes tracking tokens may cause confusion around the subject of the mail and we may need to get rid of it . But disabling tracking token affects the accuracy of email tracking and its not recommended by Microsoft.

In such situations we can update the prefix to a more meaningful one, like

Examples:
  • TrakingToken:00010001
  • Tracking#00010001 
  • #00010001
Note from Microsoft website
Tracking tokens are the only supported correlation method that can be used when you use Dynamics 365 for Outlook connected to an SMTP server and send email to a non-Exchange recipient. In this situation, if tracking tokens are not enabled, then correlation events, such as the automatically creating records based on the regarding object, may not work.

The tracking token is configurable under Email tab in System Settings,

For more information refer below link - Old article but the content is perfect

Tuesday 23 May 2017

MSCRM - Retrieve more than 5000 records using FetchXML - Simplified



I was working on a piece of C# code to retrieve more than 5000 records using Fetchxml. This may get bit tricky, so tried to simply the same as much as possible in the below post.

By default an organization service can return only the first five thousand records and page details for the next set of records, if exists.

The result entity collection exposes a Boolean attribute called MoreRecords, it will be true if more records available else false.

If more records available then we need to use the combo of pagingcookie and page(pagenumber) to retrieve rest of the records.

**Do not forget to add {0} in fetchxml which is used to include page details in below code

Code Snippet:

        public List<Entity> RetrieveAllRecords(IOrganizationService service, string fetch)
        {
            var moreRecords = false;
            int page = 1;
            var cookie = string.Empty;
            List<Entity> Entities = new List<Entity>();
            do
            {
                var xml = string.Format(fetch, cookie);
                var collection = service.RetrieveMultiple(new FetchExpression(xml));

                if (collection.Entities.Count >= 0) Entities.AddRange(collection.Entities);

                moreRecords = collection.MoreRecords;
                if (moreRecords)
                {
                    page++;
                    cookie = string.Format("paging-cookie='{0}' page='{1}'", System.Security.SecurityElement.Escape(collection.PagingCookie), page);
                }
            } while (moreRecords);

            return Entities;
        }


Example:

            var fetch = "<fetch {0}>" +
                        "    <entity name='accounts' >" +
                        "        <attribute name='accountid' />" +
                        "        <attribute name='name' />" +
                        "    </entity>" +
                        "</fetch>";
            var accountCol = RetrieveAllRecords(service, fetch);



Friday 19 May 2017

C# - Null conditional operator - Null check with question mark to handle null reference exception

Hello All,

Its good to meet you with yet another exciting tip and this time its around C#. With C# 6.0 there are many handy features introduced when it comes to day to day development.

One such feature is  Null conditional operator. ?

Personally during c# development, I always felt that in C# we lack better null condition handlers and I had to develop my own extensions to handle the same. But the situation is upside down now and I am loving this new null conditional operator.

Lets go through a quick example with code snippet

Consider the following function where we are trying to replace a value in a string, here we handle null in a conventional way


        private string StringReplaceTest(string input)
        {
            if (input == null) return null;

            return input.Replace("1", "2"); 
        }

With the latest version, we got our handy way to handle the null's and below is the updated code,


        private string StringReplaceTest(string input)
        {
            return input?.Replace("1", "2"); 
        }

Hope this helps.

MSCRM - Retrieve optionset label - RetrieveAttributeRequest - optionsetmetada - C#


Hello All,

Below is a quick code snippet that can retrieve picklist label based on value,

private string GetOptionsSetTextOnValue(IOrganizationService service,string entityName, string attributeName, int option)  
     {  
       RetrieveAttributeRequest retrieveAttributeRequest = new RetrieveAttributeRequest  
       {  
         EntityLogicalName = entityName,  
         LogicalName = attributeName,  
         RetrieveAsIfPublished = true  
       };  
       RetrieveAttributeResponse retrieveAttributeResponse = (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);  
       PicklistAttributeMetadata attributeMetadata = (PicklistAttributeMetadata)retrieveAttributeResponse?.AttributeMetadata;  
       if (attributeMetadata == null) return string.Empty;  
       var currentOption = attributeMetadata?.OptionSet?.Options?.FirstOrDefault(x => x.Value == option);        
       return currentOption?.Label?.UserLocalizedLabel?.Label != null ? currentOption.Label.UserLocalizedLabel.Label : string.Empty;  
     }  

To know more on conditional operator  with question mark, please refer
http://exptechsolutions.blogspot.com/2017/05/c-null-conditional-operator-null-check.html

Null conditional operators are the question marks in the above c# code which is a cool functionality that helps to avoid clumsy if conditions.

Friday 12 May 2017

MSCRM - Microsoft Dynamics CRM BIDS Extension Setup has stopped working - Reporting authoring extension installer failure - windows 10



A quick tip to solve report authoring extension installation issue which results in installer crash. It was hard to find the root cause as error was not specific.

Tried multiple things such as compatibility mode, visual studio shell extension installation and many other workarounds and nothing worked. Finally found that the issue was with RunOnce registry key.

Note: The below solution should also fix "Setup cannot continue because there is a pending restart required. Restart the computer and then try running Setup again" error

Solution :
If we delete this registry key(back-up before delete),  the installer will work fine

Possible Registry Key Locations:
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
  • HKEY_CURRENT_USER\Software\Microsoft\Windwos\CurrentVersion\RunOnce
  • HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce
Refer:
https://support.microsoft.com/en-us/help/2004114/you-receive-the-following-error-when-you-install-microsoft-dynamics-crm-for-microsoft-office-outlook-installation-cannot-proceed

Friday 5 May 2017

MSCRM - Entity not available in post configuration

Hi All,

I have seen lot of queries around entity not available in post configuration(Activity feed configuration).

By default CRM doesn't refresh the post configuration entities, we need manually refresh to view the latest entities.

To manually refresh, hit the refresh ribbon button and it should solve the issue

MSCRM - FetchXML filter based on time and time zone


Recently came across a scenario where we had to query CRM and retrieve accounts based on UTC date. After a fair bit of research, came-up with a Fetch query that can retrieve records based on time and time zone filters.

The key part in querying is the ISO 8601 format to specify the date time with timezone.

In the below date, +00.00 stands for UTC Time Zone and we can use any timezone by modifying this part.
2017-05-05T22:03:19+00:00

Below is a sample fetchxml, which retrieve records with modifiedon greater than or equal to given UTC datetime.

Note: Use 'greater than or equal to' or 'lesser than or equal to' instead of 'on or before' or 'on or after'

 <fetch>  
   <entity name="account" >  
     <all-attributes/>  
     <filter type="and" >  
       <condition attribute="modifiedon" operator="ge" value="2017-05-05T22:03:19+00:00" />  
     </filter>  
   </entity>  
 </fetch>  

To filter time based on user's timezone remove the timezone part(+00:00) from the query and the sample will look like below,

 <fetch>  
   <entity name="account" >  
     <all-attributes/>  
     <filter type="and" >  
       <condition attribute="modifiedon" operator="ge" value="2017-05-05T22:03:19" />  
     </filter>  
   </entity>  
 </fetch>


Hope this helps!

Tuesday 2 May 2017

MS CRM - Xrm.Page.getAttribute("attribute").fireOnChange() - #JSTip4


Hello All,

In our Xrm clientside object we have an method called fireOnChange(),

Purpose and Usage:
Triggers onchange event of the specific attribute, which in turn triggers the JavaScript functions attached to it.

Scenarios
  • At times, based on business needs we may need to execute a JS logic pinned to field on demand, where this function comes handy.
  • Script updates to a field will not trigger onchange of that field. We can use this way to trigger onchange event of the field if needed. 
Example: 
In account form, we have address fields and on change of address fields there is a logic to populate shipping address. Now when we add a primary contact consider the address fields should be updated from contact address. In this scenario, using JS if we update address fields the shipping address functionality tied to address fields will not fire. This is where we need to use fireOnchange.

Code Snippet:
Xrm.Page.getAttribute("fieldname").fireOnChange()

MS CRM - A currency is required if a value exists in a money field. Select a currency and try again - #CRMTip



Hello All,

Good to be back with another quick tip regarding currency and money fields.

Many of us might have experienced issues with money and currency fields, In this post we are going to learn a best practice and fix for one of the money or currency issues

Error:
A currency is required if a value exists in a money field. Select a currency and try again

Steps to replicate:
Open an existing CRM record without currency value populated, now enter data into any of the money fields and you will experience the above error.

Root Cause:
Money fields are currency dependent and when the currency is empty, its obvious that money is invalid.

Quick fix:
Populate currency field and it will fix the issue.

Best practice:
Make sure that currency field is always populated during create/update via workflow/plugin. If any custom logic is used to select currency, default a currency if no match found.

Thursday 13 April 2017

MS CRM - Better way of Hiding or Disabling a field in Form - #JSTip3


Hello All,

Lets go through a quick development tip regarding hiding or disabling an attribute using JavaScript,

To hide or disable a field in CRM, its very common to use Xrm.Page.getControl. Though the method is very handy it has its own restrictions.

Xrm.Page.getControl - Not the best way
This function will return only the first occurrence of the specific attribute in the form.

Consider we have statecode attribute at multiple area's of a form, In this scenario getcontrol can handle only the first occurrence of this attribute, which affects the robustness of the solution.


Xrm.Page.getAttribute("AttributeName").controls
Instead of using getControl we can use getAttribute.controls to hide all the fields related to a particular attribute.

Here we select the attribute, then we loop through all the controls available for that attribute and we are hiding them.

Sample code snippets are as follows,

Usual Way:
Xrm.Page.getControl("statecode").setVisible(false);

Best way:
Xrm.Page.getAttribute("statecode").controls.forEach(
        function (control) {
            control.setVisible(false);
        });









Saturday 8 April 2017

MS CRM Plugin - IPluginExecutionContext InitiatingUserId and UserId - #PluginTip2


Hello All,

Glad to meet you with another tip, In plugin execution context we have two attributes which points to user record with which we can create organization service. Both the attributes are of type EntityReference and at the end of this post you will have good idea on what is the difference between them and when to use specific attribute.

Initiatinguserid:
This is the user who performs the operation that triggers the plugin. If USER-A creates a record and a plugin is triggered on record create then the Initiatinguserid is USER-A.
Userid:
This contains the "run in user's context" users id that is set as a part of plugin step creation. If the value is not set, then it equivalent to Initiatinguserid
In below code, we have created orgservice with both user entityreference's
Example code:
 IPluginExecutionContext context = (IPluginExecutionContext)  
         serviceProvider.GetService(typeof(IPluginExecutionContext));  
 IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));  
 IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);  
 IOrganizationService intiatingUserService = serviceFactory.CreateOrganizationService(context.InitiatingUserId);  

Example Scenario's
======================================================
======================================================
Scenario - 1
USER-A executes a plugin step without  "run in user's context".
Initiatinguserid/Userid  = USER-A
======================================================
Scenario - 2
USER-A  executes a plugin step with  "run in user's context" as USER-B
Initiatinguserid = USER-A
Userid = USER-B

Hope this helps!
Also check out my blog on plugin depth

Wednesday 5 April 2017

MS CRM - IPluginExecutionContext.Depth a detailed look - #PluginTip1


Today, we are going to have a detailed look on the depth property available in plugin or workflow context. By the end of this post, you will have enough knowledge to decide when to use depth and how to use it wisely.

Intro:
Depth property is used to find the position of the plugin in current call stack. To be simple, with this property we can find whether the plugin is triggered by another process(plugin/workflow) or directly by platform/user.

Default depth value is 1. 

If plugin depth is greater than 1, then it is triggered by another process. Depth of the plugin is incremented by 1, if called by another process.

Myth
There is a myth around depth, that it can be used to break infinite loops. Yes they can, but these checks may become dangerous and may skip your plugin logic at times. For example, If a plugin from account triggers a plugin in contact, the depth in contact plugin is 2 and that is not an infinite loop.

Example 1:
Lets take an example for infinite loop,
On an account update(post-operation) we have a plugin and this plugin updates the account again, This update triggers the same plugin again.

Here for the first time depth would be 1 and from then on every time it will be incremented by 1. So to avoid loop, we should to check the depth but personally I don't prefer using depth here.

Example 2:
Lets take an example for parent child,
On an account update post-operation we have a plugin and this plugin updates a contact record which in-turn triggers another plugin. If we may need to restrict the plugin execution on contact, only when there is a direct operation on contact and not from account. We can use depth to achieve this.

Here for the first plugin depth would be 1 and for the child/triggered plugin the depth would be 2. You can use depth validation to exit the plugin,

Conclusion:
Be wise when using depth validation!

Feel free to comment your views, hope this post is informative.

Also check out my blog on IntitatingUserId and UserId