Advertisements

Wait Condition with ‘Parallel Wait Branch’

February 19, 2017 Leave a comment

In my previous article , I explained using ‘Wait Condition’ with simple scenario. In this article, lets see using ‘Parallel Wait Branch’ with Wait Conditions.

Lets take a simple scenario

  • Up on Opportunity creation, if an Account associated with Opportunity ‘Send Mail’ to Opportunity owner OR close the Opportunity as Lost, if no association happen with in 7 days.

To achieve the above scenario, we have to go with ‘Parallel Wait Branch’ with 2 Wait Conditions

Configuring Work Flow :

  • Create a workflow on Opportunity which triggers when ‘Record is created’
  • Add a “Wait Condition” to check, if Account got assigned to Opportunity (I.e., Opportunity. Account ‘Contains Data’)
  • Create an Email Activity, if ‘Wait Condition’ met
  • Select that wait condition and then choose the ‘Parallel Wait Branch’ option from the Add Step menu
  • Add another “Wait Condition” with ‘Time Out’ option for 7 days

Wait Condition - Time Out.PNG

  • If condition met, add ‘Change Status’ step to close the Opportunity as Lost and Canceled.
  • Workflow looks as below

parallel-wait-condition

  • Save and Activate Workflow

Points to consider using Wait condition:

  • While using a Timeout, and if the date changes, the timeout will automatically adjust and wait until the new date.
  • Even if that date is changed to be in the past, the timeout will readjust to the new date, and will fire instantly.
  • If the server goes down, or the async service stops, any workflows that are ‘waiting’ will be resumed when the server/async service comes back up.
  • If the server/async is down at the exact time as when a wait condition is waiting until, the workflow will continue again when the server/async comes back up, and it will process the wait conditions that were due during the down time.

🙂

Advertisements
Categories: CRM Tags: ,

‘Wait Condition’ in Workflow Explained

February 19, 2017 1 comment

I was asked by one of my blog followers to explain ‘Wait Condition’ in Workflow.

wait-condition

To explain this better, I took a small scenario

  • Send an Email to Opportunity Owner, whenever an Account has been assigned to the Opportunity

Configuring Work Flow :

  • Create a workflow on Opportunity which triggers when ‘Record is created’
  • Add a “Wait Condition” to check, if Account got assigned to Opportunity (I.e., Opportunity. Account ‘Contains Data’)

workflow-wait-condition

  • Create an Email Activity, if ‘Wait Condition’ met

workflow-send-email-when-wait-condition-met

  • Save and Activate Workflow

Test the Workflow

  • Create new Opportunity

new-opportunity

  • Check the Waiting job in ‘System Jobs’
    • Since we have the Wait condition set in our workflow, the Job will wait until the condition met

waiting-job

  • Associate ‘Account’ to the ‘Opportunity’

opportunity-associated-account

  • Check the Waiting Job now and it should have completed.

waiting-job-completed

  • New Email created in system as the follow up action

Key Points to consider before using Wait Conditions:

While the ‘Wait conditions’ are useful in case of the timer related tasks which will be achieved with no coding, excessive use of wait conditions has a downside.

  • Performance:
    • Each waiting workflow instance carries performance overhead. The more waiting workflow you have, the more server resources will be consumed by the Asynchronous Processing Service.
    • If you change the logic in your workflow and republish (like update the text of the email sent to your client), it does not change waiting workflow instances. For example, if you change the renewal email frequency to 15 days rather than 30 days, any workflow instances that are waiting will not be updated.

🙂

 

Categories: CRM Tags: ,

Solution Import Failures / Publish Customizations Failures – Dynamics 365

February 12, 2017 Leave a comment

Recently we upgraded our organizations to Dynamics 365 and we were getting solution import failure while moving solutions between organizations.

Below are different kind of error messages popped up.

  • Getting Dependency Calculation There was an error calculating dependencies for this component. Missing component id {0}
  • Failure trying to associate it with CustomControlDefaultConfig
  • Can’t insert duplicate key for an entity

Reason:

  • In our case the root cause for all these import failures was “customcontroldefaultconfig” component with Custom entities.
  • If there is any orphan record exists in “CustomControlDefaultConfigBase” table it would cause solution import failure or ‘Publish Customizations’ error.
  • The issue seems a product issue and got fixed in Service Update 5 of CRM 8.1.0 but resurfacing again in Dynamics 365.

Prevention Tip:

  • If you are adding an entity to your solution, always add ‘Primary key’ field
    • In the source environment open the Solution being imported
    • Open each Entity and expand Fields
  • Make sure that every entity has its “Primary Key” added to the solution.

solution-add-primary-key-field-of-entity

Fix:

CRM On-Premise

  • Check if any orphan records in CustomControlDefaultConfigBase tabel. (Use below queries)
    • SELECT * FROM CustomControlDefaultConfigBase WHERE PrimaryEntityTypeCode NOT IN (SELECT ObjectTypeCode FROM Entity)
  • Note: before continuing, a backup database is recommended.
  • Delete from the Target environment the CustomControlDefaultConfig records with orphaned Object Type Codes:
    • DELETE FROM CustomControlDefaultConfigBase WHERE PrimaryEntityTypeCode NOT IN (SELECT ObjectTypeCode FROM Entity)

CRM On-line

  • Create console application to delete the orphan record in CustomControlDefaultConfigBase using CRM SDK
  • Refer this URL for code.

🙂

CRM Record “Email a Link” feature not working

February 8, 2017 Leave a comment

Recently few of our CRM users complained OOB “Email a Link” not working.

email-link

Reason:

  • Machines default “Email” App was set to “Chrome”

email-settings

Fix:

  • Change default “Email” App to “Mail” or “Outlook” client

 

email-settings-set-to-mail-client

🙂

Categories: CRM, Uncategorized Tags: , ,

Retrieve Global Option set details – CRM SDK

January 28, 2017 Leave a comment

Below is the sample code to retrieve existing Global Option sets along with Option text & values using RetrieveAllOptionSetsRequest :

var retrieveAllOptionSetsRequest = new RetrieveAllOptionSetsRequest();

RetrieveAllOptionSetsResponse retrieveAllOptionSetsResponse = (RetrieveAllOptionSetsResponse)orgService.Execute(retrieveAllOptionSetsRequest);

if (retrieveAllOptionSetsResponse.OptionSetMetadata.Count() > 0){
StringBuilder sb = new StringBuilder();
foreach (OptionSetMetadataBase optionSetMetadataBase in retrieveAllOptionSetsResponse.OptionSetMetadata){
if (optionSetMetadataBase.OptionSetType != null){
if ((OptionSetType)optionSetMetadataBase.OptionSetType == OptionSetType.Picklist){
OptionSetMetadata optionSetMetadata = (OptionSetMetadata)optionSetMetadataBase;
sb.AppendLine(“OptionSetDisplayName – ” + ((optionSetMetadata.DisplayName.LocalizedLabels.Count > 0) ? optionSetMetadata.DisplayName.LocalizedLabels[0].Label : String.Empty));
sb.AppendLine(“***************************************************”);

foreach (OptionMetadata option in optionSetMetadata.Options){
sb.AppendLine(“Option”);
sb.AppendLine(“OptionValue – ” + option.Value.ToString());
sb.AppendLine(“OptionDescription – ” + option.Label.UserLocalizedLabel.Label.ToString());
}
}
else if ((OptionSetType)optionSetMetadataBase.OptionSetType == OptionSetType.Boolean){
BooleanOptionSetMetadata optionSetMetadata = (BooleanOptionSetMetadata)optionSetMetadataBase;
// Start OptionSet Node
//metadataWriter.WriteAttributeString(“OptionSetType”, OptionSetType.Boolean.ToString());
if (optionSetMetadata.DisplayName.LocalizedLabels.Count != 0)
sb.AppendLine(“OptionSetDisplayName – ” + optionSetMetadata.DisplayName.LocalizedLabels[0].Label);
else
sb.AppendLine(“OptionSetDisplayName – ” + “UNDEFINED”);

sb.AppendLine(“**************************************************”);

// Writes the TrueOption
sb.AppendLine(“TrueOption”);
sb.AppendLine(“OptionValue – ” + optionSetMetadata.TrueOption.Value.ToString());
sb.AppendLine(“OptionDescription – ” + optionSetMetadata.TrueOption.Label.UserLocalizedLabel.Label.ToString());
sb.AppendLine(“FalseOption”);
sb.AppendLine(“OptionValue – ” + optionSetMetadata.FalseOption.Value.ToString());
sb.AppendLine(“OptionDescription – ” + optionSetMetadata.FalseOption.Label.UserLocalizedLabel.Label.ToString());
}
}
sb.AppendLine(string.Empty);
}

Console.WriteLine(sb.ToString());

Output would be

global-options-1

global-options-2

🙂

Categories: CRM, Uncategorized Tags: ,

New field ‘Sort Date’ in Activity Pointer entity – Dynamics 365

January 26, 2017 Leave a comment

A new field ‘Sort Date’ (Schema Name – sortdate) has been added to the ‘Activity Pointer’ entity to control the sorting of the Activities.

sort-date-activities

Limitation with earlier CRM versions:

  • To display a list of activities and order them by date, we can only use the common date attributes like ‘Created on’ or ‘Modified on’ defined in the activitypointer entity.
  • What if you have to sort Email activities by ‘Sent On’ attribute rather than the modifiedon attribute value?

How ‘Sort Date’ Solves This:

  • With ‘Sort Date’ attribute, we can control how activities are sorted by desired date.
  • By default, the ‘Sort Date’ attribute value is null.
  • Set the ‘Sort date’ attribute value using a workflow or a plugin with required Date value (For example, set ‘Sort Date’ with ‘Sent On’ value in case of Emails) and use that in views.

🙂

Create a child record by copying mapping fields data from Parent – Using CRM SDK

January 26, 2017 Leave a comment

Let’s take the OOB Account and Contact related entities.

Whenever we click ‘Add New Contact’ button from the ‘Associated view’ of ‘Account’ form, all the mapping fields data would be copied to ‘New Contact’ form.

Account:

account-form

New Contact Form:

create-contact

This is native CRM behavior, to copy the content from Parent to Child record, using the Relationship ‘Mappings’ to avoid the overhead of manual data entry on child record.

account-and-contact-mappings

What If we have to create a Contact from a console application using CRM SDK and achieve the same behavior?  ‘InitializeFromRequest’ is the answer.

Steps to use ‘InitializeFromRequest’:

  • Instantiate the ‘InitializeFromRequest’
  • Set the Target as ‘Contact’
  • Set the ‘EntityMoniker’ as the reference of parent ‘Account’ which you would want to copy the data from
  • Execute the ‘InitializeFromRequest’
  • From the ‘InitializeFromResponse’, read the Contact object with copied data from Account (**Contact would not be created in CRM at this point**)
  • Fill the other attributes
  • Create the Contact

Source Code:

InitializeFromRequest initialize = new InitializeFromRequest();

// Set the target entity (i.e.,Contact)
initialize.TargetEntityName = “contact”;

// Create the EntityMoniker of Source (i.e.,Account)
initialize.EntityMoniker = new EntityReference(“account”, new Guid(“D4CBEE74-B5E3-E611-8109-C4346BDD8041”));

// Execute the request
InitializeFromResponse initialized = (InitializeFromResponse)orgService.Execute(initialize);

// Read Intitialized entity (i.e.,Contact with copied attributes from Account)
if (initialized.Entity != null)
{
// Get entContact from the response
Entity entContact = initialized.Entity;

// Set the additional attributes of the Contact
entContact.Attributes.Add(“firstname”, “Rajeev”);
entContact.Attributes.Add(“lastname”, “Pentyala”);

// Create a new contact
orgService.Create(entContact);
}

If you put the debugger and watch the ‘initialized.Entity’ you would see the populated fields.

initialized-entity-contact

Post execution of this code, a new Contact would get created with copied data from Account.

contact-form

🙂