Ribbon Troubleshooting using Command Checker

The only reason you might have landed to this page is because your recent ribbon customization is giving you hard time and like me you did not knew about this very help full tool provided by Microsoft with D365 CRM.

If you are working on ribbon customization then the normal issues that you might face other then the logic that should happen after the click event is with either display of the newly added ribbon button, i.e. with Display Rule or Value Rule. It may be because of some small incorrect or missing configuration but that may take some time to identify.

We all know that some very basic things to check are:
1. Display Rule Configuration
2. Value Rule Configuration
3. Missing Command definition (yes, if your button does not have a Comment associated, the button will not be displayed on the ribbon).

But even after validating all this and even more if the issue is still not resolved then MS has provided a very good article on some more possible steps to be performed.

https://support.microsoft.com/en-us/help/4552163/ribbon-troubleshooting-guide

The article uses an in-app tool called the Command Checker to inspect the ribbon component definitions to help us determine why the button is hidden.

To enable the Command Checker, you must append a parameter ‘&ribbondebug=true‘ to your D365 application URL. For example: https://yourorgname.crm.dynamics.com/main.aspx?appid=9ab590fc-d25e-ea11-a81d-000d3ac2b3e6&ribbondebug=true

Once the Command Checker has been enabled, within the application in each of the various ribbon bars (global, form, grid, subgrid), there will be a new special “Command checker” button to open the tool.

More details on how to use the tool are available on the link shared above.

Hope this helps!

SLA Timer does not consider the paused duration

I was required to configure an Enhanced SLA which should honor Business Hours and can also be paused and resumed. So I created an SLA record by selecting “Business Hours” and setting “Allow pause and Resume” to “Allow”. I also added an timer control on the form that will show the SLA status.

Next I enabled an status upon selecting of which the SLA will pause and resume.

While testing what I noticed was that when I used to change the status of the record to pause, the timer used to stop and show the status as Paused. If I change the record status again to active, the timer used to continue again from paused. All looks good till now.

But when checked closely, the SLA timer used to pause. Also the SLA KPI Instance status used to change to paused. When resumed, SLA KPI Instance status used to change from paused to Active and timer used to continue. But the timer also considered the duration while the record was paused. I.e. if i paused the SLA for 2 mins when the timer value was 00:05:00, upon resuming the SLA the timer control used to start from 00:03:00 and NOT resume from 00:05:00.

Upon checking, configuration was correct and as per MS the behavior is also correct. That is because I was checking the record outside of Business Hours that I had configured on SLA record.

SLA does not consider the pause duration outside of Business Hours. Below is a snippet from MS Documentation explaining this. I’m also including the link to the documentation as it mentions few more scenarios similar to above that should be noted while working on SLA.

Create a case during non-working hours. Pause and resume the case before working hours start. Hold time between Pause and Resume will not be considered.

https://docs.microsoft.com/en-us/dynamics365/customer-service/troubleshoot-sla-timer-issue

Get Business Process ID and Stage ID using name

Quick Post:

It is an normal request to get to auto set the Business Process Flow stage based on some condition. It is stright forward and you will also find many blogs to update the stage. But when i was working on it, it found it difficult to search for a post that explains how to get Process ID and Stage ID based on name. This is important to avoid hardcoding of process and stage id in the code.

Below sample will help to get both Process ID and Stage ID based on Process and Stage name and also update the business process stage.

Guid processId = Guid.Empty;
Guid stageId = Guid.Empty;

        //Get Process ID for BPF "Case Resolution"
        EntityCollection workflowRecords = new EntityCollection();
        QueryExpression query = new QueryExpression("workflow");
        query.NoLock = true;
        query.ColumnSet = new ColumnSet("workflowid");
        query.Criteria.AddCondition("name", ConditionOperator.Equal, "Case Resolution");
        workflowRecords = service.RetrieveMultiple(query);
        if (workflowRecords.Entities.Count > 0)
        {
            processId = workflowRecords.Entities.FirstOrDefault().GetAttributeValue<Guid>("workflowid");
        }

        //Get Stage ID for Stage "Resolution"
        EntityCollection stageRecords = new EntityCollection();
        QueryExpression query2 = new QueryExpression("processstage");
        query2.NoLock = true;
        query2.ColumnSet = new ColumnSet("processstageid");
        query2.Criteria.AddCondition("stagename", ConditionOperator.Equal, "Resolutions");
        query2.Criteria.AddCondition("processid", ConditionOperator.Equal, processId);
        stageRecords = service.RetrieveMultiple(query2);
        if (stageRecords.Entities.Count > 0)
        {
            stageId = stageRecords.Entities.FirstOrDefault().GetAttributeValue<Guid>("processstageid");
        }


        //Change the stage
        Entity updatedStage = new Entity("incident"); //Parent entity on which the BPF is
        updatedStage.Id = new Guid("ED973BF5-D382-493B-8E31-55892B2F0C52"); //Record id for which you which to update stage.
        updatedStage["stageid"] = stageId;
            updatedStage["processid"] = processId;
            service.Update(updatedStage);

Hope this helps!

Get selected options from Multiselect Option set

{QuickPost}

Recently had a requirement to get all selected option texts from a multi select option set. Getting selected values is straight forward but I wanted to get the Label of selected values. For normal option set we can get it easily by using FormattedValues but that does not work with Multiselect Option set.

For C#:

Then found an handy code by Ravi Kashyap that was posted on community here. I have just restructured the function to make it generic.

Now just call the getSelectedOptionSetText() function and pass Organization Service, entity name and MultiSelect optionset field name.

The function first retrieves all the labels from the Option Set and then filters it with selected option set values.

public string getSelectedOptionSetText(IOrganizationService service, Entity enRecord, string fieldName)
{
string selectedText = string.Empty;
// Get the Formatted Values of MultiSelect OptionSet
List multiSelectTextCollection = GetOptionSetTextCollection(service, enRecord.LogicalName, fieldName);

if (enRecord.Contains(fieldName))
{
OptionSetValueCollection multiSelectValueCollection = (OptionSetValueCollection)enRecord[fieldName];

foreach (var relationshipType in multiSelectValueCollection)
{
if (selectedText.Equals(string.Empty))
{
selectedText = multiSelectTextCollection.Where(x => x.Value == relationshipType.Value).FirstOrDefault().Label.UserLocalizedLabel.Label;
}
else
{
selectedText = selectedText + ", " + multiSelectTextCollection.Where(x => x.Value == relationshipType.Value).FirstOrDefault().Label.UserLocalizedLabel.Label;
}
}
}
return selectedText;
}


public static List GetOptionSetTextCollection(IOrganizationService service, string entityName, string fieldName)
{
var retrieveAttributeRequest = new RetrieveAttributeRequest()
{
EntityLogicalName = entityName,
LogicalName = fieldName,
RetrieveAsIfPublished = true
};

var retrieveAttributeResponse =(RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);

var attMetadata = (EnumAttributeMetadata)retrieveAttributeResponse.AttributeMetadata;

return attMetadata.OptionSet.Options.ToList();
}

For JavaScript:

To achieve the same using JavaScript is comparatively easy.

To get all selected option set values:

//Returns Array of Selected OptionSet Values: [798090000,798090001,798090002]
var selectedValues = formContext.getAttribute("new_multiselect").getValue();

To get all selected option set texts:

//Returns Array of Selected OptionSet Text: ["One", "Two","Three"]
var selectedTexts = formContext.getAttribute("new_multiselect").getText();

To set value (Overwrite existing selection with passed comma separated values)
formContext.getAttribute("net_multiselect").setValue([798090000,798090001,798090002]);

{Observation} Execution context of Real-time workflow

We all know that if we call a child workflow from a parent real-time workflow, it runs in context of that parent workflow but what happens if the trigger for the parent real-time workflow is updated using a custom application outside of CRM?

I had a custom .Net application which used to get values from CRM, send them to SAP and update the return values from SAP back into CRM. The custom application used to trigger as an batch application. There was a real-time workflow configured on update of the fields populated by the .Net application in CRM which internally used to call a child workflow process.

One day issue was reported by the .Net application as “[Microsoft.Xrm.Sdk.OrganizationServiceFault]: This workflow cannot run because one or more child workflows it uses have not been published or have been deleted. Please check the child workflows and try running this workflow again. (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault).”.

As the .Net application used to update the field which then used to trigger the real-time workflow (configured to run “After”) it was not quite obvious behavior for me. I did know that the child workflow was deactivated but my assumption was that the issue will be logged in system jobs and not in .Net application. I was expecting that .Net application will update the field in CRM, after which the parent real-time workflow will trigger which will try to call a deactivated child workflow and fail.

But after digging a bit it was observed that as the parent workflow was configured as real-time it keeps the context with calling .Net application and returns the error back to .Net application. Due to which the .Net application throw an exception. I’m still not sure why, but this is how it works.

Get a list of all Business Rules from your CRM environment

Referencing to the original post on CRM 2013 from here.

As Business Rules are created for a particular entity, we can see all the business rules that have been created for any particular entity from the entity customization itself.

This is ok when we need to see all the business rules on an entity. But it does not allow us to pull up a list of business rules across the whole system. Sometimes after deploying a solution, we need to check the business rules to make sure they’re activated, or if there are any errors, and we don’t want to have to go through each entity and check these.

As Business Rules are workflows under the hood, we can do an Advanced Find query with filter criteria on Categories as Business Rule (for CRM 2013, it was PBL) to get the list of all business rules in an organization. The result contains Name, Primary Entity, status and other basic information about the business rule.

p1

p2

 

Transaction aware batch process using ‘ExecuteMultipleRequest’

Rajeev Pentyala - Microsoft Power Platform

In this article, I am going to discuss about transaction aware batch processing in ExecuteMultipleRequest using  ExecuteTransactionRequest.

Is ‘ExecuteMultipleRequest’ not a transaction aware?

  • By design, ‘ExecuteMultipleRequest’ is non-transactional.
  • Which means ‘Request’ objects added to ‘ExecuteMultipleRequest’ are independent of each other and if any exception occurred in any of the ‘Request’ will not roll back previously committed ‘Requests’.
  • However you have an option to stop the batch (i.e., By setting ContinueOnError = false),  if any exception occurs.
  • Important to note is that, this behavior is not a transaction aware and ‘Requests’ executed prior to the error, will still be committed.

How can we achieve ‘Transaction’ in Batch execution?

  • Using ExecuteTransactionRequest, we can achieve ‘Transaction’ (i.e., Commit and Rollback) in Batch execution
  • ExecuteTransactionRequest will execute the all the ‘Requests’ in a single transaction.
  • If any exception occurred in any of the ‘Request’ execution, will roll back all the previously…

View original post 301 more words

MultiSelect Option Set in Dynamics 365

Nishant Rana's Weblog

With July 2017 update, we can now finally create multi-select option set in Dynamics 365.

We can also use Existing Global Option Set while defining our Multi Select Option set.

This is how control looks within the form.

Within Advanced Find View

We can use the existing option set client-side methods on Multi Select Option Set.

https://msdn.microsoft.com/en-us/library/gg334409.aspx#Anchor_1

getSelectedOption() – for new_weekday multiselect option-set with value Thursday and Friday selected –

Hope it helps..

View original post

Dynamics 365 v9 – NOT IN support for Advanced Find

Dynamics 365 Funda by Zohaib Uddin Khan

Let’s discuss all the new features of Dynamics 365 v9 updates. One of the interesting ones is ‘NOT IN Support for Advanced Find’.

Purpose of this new feature is to find all those Cases that do not contain a Task using Advanced Find.  Let’s kick in to play with it.

Go to Dynamics 365 – click on Advanced Find

Scenario # 1:

  • Look for: Cases
  • in the below pane, do ‘Tasks (regarding) = Contains Data”
  • Click on Results button.

This query will return all the Cases which have at least one Task associated with it.

D365-v9-NOT-IN-Advanced-Find-1

If you click on the ‘Download Fetch XML’, you will find the below info:

D365-v9-NOT-IN-Advanced-Find-3

Scenario # 2:

  • Look for: Cases
  • in the below pane, do ‘Tasks (regarding) = Does Not Contain Data”
  • Click on Results button.

This query will return all the Cases which don’t have any Task associated with it.

D365-v9-NOT-IN-Advanced-Find-2

If you click on the ‘Download Fetch XML’, you…

View original post 23 more words