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

Tuesday 4 April 2017

Mobile compatible development - Microsoft Dynamics CRM - MoCA_Tip#1


After the release MoCA, I was interested in exploring the functionalities available and I am happy with the available features.

Now, we are going to see some tips based on my previous experience with MoCA. I will try to provide some more tips in upcoming blog posts,

Behavior of hidden tabs
  • ·        CRM web forms ignore hidden tabs when they are loaded in Mobile. Therefore, if you have any logic based on hidden section fields then those logics are going to break.
  • ·        Make sure the tab is visible on form. Then hide the same using JavaScript, this will make the tab and fields available on form.


Error with field's customized event – Random errors on specific forms
  • ·        This error is common on the forms, which contains multiple tabs/sections/fields, and the errors are random and not specific to any functionality.
  • ·        This is because, we have limits on the count of controls available on mobile form and these are configurable in orgsettings


The default and max allowed items for a mobile form is as follows,

Setting
Default Value
Max Value
TabletClientMaxFields
75
500
TabletClientMaxLists
10
50
TabletClientMaxTabs
5
50

Sunday 2 April 2017

MS CRM - Refresh Form - #JSTip2



In the latest version of CRM, there were situations where we need to refresh the whole form instead of refreshing date using Xrm.Page.data.refresh.

To achieve conventional refresh, we can use openEntityForm available in Xrm.Utility. This method reopens the record in a conventional way which is equivalent to full refresh.

Code snippet for the same is as follows


function refreshForm() {
        Xrm.Page.data.setFormDirty(false);
        Xrm.Utility.openEntityForm(Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId());
    }