Asked by:
"This workflow job was canceled because the workflow that started it included an infinite loop..."

Question
-
I have a Post Update-step for custom Plugin that are executing another Update on the same entity:
I now get a Exception:
I don' see why this would happen, because Update #2 doesn't change "log_bookedstartdate" or "log_bookedenddate" and a infinite loop should therefore be avoided.... or am I missing something here?
regards,
Marius H. Enerud
Thursday, December 22, 2016 1:03 PM
All replies
-
Can you please provide full code of your plugin?
Dynamics CRM MVP
Read My blog
Subscribe for one of my coursesThursday, December 22, 2016 2:32 PMModerator -
Hi,
here are the full code for the plugin step:
public PostUpdate(string unsecureConfig, string secureConfig) : base(unsecureConfig, secureConfig)
{
// Register for any specific events by instantiating a new instance of the 'PluginEvent' class and registering it
base.RegisteredEvents.Add(new PluginEvent()
{
Stage = eStage.PostOperation,
MessageName = "Update",
EntityName = log_workorders.GetLogicalName(),
PluginAction = ExecutePluginLogic
});
}
public static void ExecutePluginLogic(IServiceProvider serviceProvider)
{
// Use a 'using' statement to dispose of the service context properly
// To use a specific early bound entity replace the 'Entity' below with the appropriate class type
using (var localContext = new LocalPluginContext<Entity>(serviceProvider))
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}string preImageAlias = "preimage";
string postImageAlias = "postimage";IPluginExecutionContext context = localContext.PluginExecutionContext;
Entity preImageWorkOrder = (context.PreEntityImages != null && context.PreEntityImages.Contains(preImageAlias)) ? context.PreEntityImages[preImageAlias] : null;
Entity postImageWorkOrder = (context.PostEntityImages != null && context.PostEntityImages.Contains(postImageAlias)) ? context.PostEntityImages[postImageAlias] : null;
Entity WorkOrder = (Entity)(context.InputParameters.ContainsKey("Target") ? context.InputParameters["Target"] : null);
Guid workorderid = WorkOrder.Id;log_workorders workorder = WorkOrder.ToEntity<log_workorders>();
log_workorders preimageworkorder = preImageWorkOrder.ToEntity<log_workorders>();
log_workorders postimageworkorder = postImageWorkOrder.ToEntity<log_workorders>();#region SMS (Booked appointment) functionality
// Booked start date and Booked end date have been deleted. SMS message must be deleted
if (preimageworkorder.log_Bookedstartdate.HasValue && !postimageworkorder.log_Bookedstartdate.HasValue
&& preimageworkorder.log_Bookedenddate.HasValue && !postimageworkorder.log_Bookedenddate.HasValue)
{
using (OrganizationServiceContext ctx = new OrganizationServiceContext(localContext.OrganizationService))
{
var existingsms = (from s in ctx.CreateQuery<log_sms>()
where s.log_SMS != null && s.log_SMS.Id == postimageworkorder.Id
&& s.log_DispatchStatus != null && !s.log_DispatchStatus.Value.Equals(182400003) // not dispatched
select s);foreach (var sms in existingsms)
{
localContext.OrganizationService.Delete(log_sms.GetLogicalName(), sms.Id);
}
}
}
// Booked start date or Booked end date have been updated. An SMS message must be created/updated
if (workorder.log_Bookedstartdate.HasValue || workorder.log_Bookedenddate.HasValue)
{
workorder.log_ScheduledBy = new EntityReference("systemuser", context.InitiatingUserId);
// localContext.OrganizationService.Update(workorder);using (OrganizationServiceContext ctx = new OrganizationServiceContext(localContext.OrganizationService))
{
string templatename = GetSMSTemplateName((int)postimageworkorder.log_TypeofWorkOrder.Value);log_smstemplate smstemplate = (from st in ctx.CreateQuery<log_smstemplate>()
where st.log_name == templatename
select st).FirstOrDefault();
if (smstemplate != null)
{
EntityCollection customers = (EntityCollection)postimageworkorder["customers"];
Entity ap = customers.Entities[0];
EntityReference accountRef = (EntityReference)(customers.Entities[0])["partyid"];
Account account = localContext.OrganizationService.Retrieve(Account.GetLogicalName(), accountRef.Id, new ColumnSet(true)).ToEntity<Account>();string smsbody = (string)smstemplate.log_SMSBody;
DateTime senddatetime = CalculateSendTime(postimageworkorder, smstemplate);
localContext.Trace("senddatetime: " + senddatetime.ToString());
log_sms existingsms = GetExistingSMS(localContext, preimageworkorder, postimageworkorder, ctx);
if (existingsms != null)
{
UpdateExistingSMS(localContext, postimageworkorder, smsbody, senddatetime, existingsms);
}
else
{
CreateNewSMS(localContext, postimageworkorder, accountRef, account, smsbody, senddatetime);
}
}
}
}#endregion
#region No-show and SectorMobile (PDA) related functionality
// No-show logic
if (workorder.log_ProcessNoShow == "Activated") return;
else if (workorder.log_ProcessNoShow == "Activate")
{
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.OpenTimeout = new TimeSpan(0, 3, 0);
myBinding.ReceiveTimeout = new TimeSpan(0, 3, 0);
myBinding.SendTimeout = new TimeSpan(0, 3, 0);
myBinding.CloseTimeout = new TimeSpan(0, 3, 0);
myBinding.Name = "BasicHttpBinding_ITwoWayAsyncVoid";
myBinding.Security.Mode = BasicHttpSecurityMode.None;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
EndpointAddress endPointAddress = new EndpointAddress(Utilities.GetConfigItem<string>("log_noshowactivationserviceendpoint", localContext.OrganizationService));
// get engineer id and country
EntityReference engineerRef = workorder.log_ReportedbyId ?? preimageworkorder.log_ReportedbyId;
if (engineerRef == null) localContext.Trace("engineerRef = null");
log_employee engineer = ((Entity)localContext.OrganizationService.Retrieve("log_employee", engineerRef.Id, new ColumnSet("log_employeenumber"))).ToEntity<log_employee>();
localContext.Trace("engineer: " + engineer.log_name);
string dataareaid = Utilities.GetConfigItem<string>("log_axdataareaid", localContext.OrganizationService);
string country = Utilities.GetConfigItem<string>("log_noshowactivationcountry", localContext.OrganizationService);//the "old" noshow-solution (not working in TEST, therefore skip it)
var servername = Environment.MachineName.ToLower();
if (!servername.Contains("dev") && !servername.Contains("test") && !servername.Contains("tst"))
{
NoShowActivationServiceClient noshowclient = new NoShowActivationServiceClient(myBinding, endPointAddress);
NoShow noshow = new NoShow();
noshow.ActivityNumber = workorder.log_ActivityNumber ?? preimageworkorder.log_ActivityNumber;
noshow.Country = country;
noshow.Engineer = engineer.log_EmployeeNumber;noshowclient.ActivateNoShow(noshow);
}string noshowendpoint = null;
using (var orgcontext = new OrganizationServiceContext(localContext.OrganizationService))
{
noshowendpoint = (from s in orgcontext.CreateQuery<log_sectormobileconfigurationsetting>()
where s.log_name == "NoShowEndpoint"
select s.log_Value).FirstOrDefault();
}//the "new" noshow-solution
if (!string.IsNullOrWhiteSpace(noshowendpoint))
{
BasicHttpBinding mynoshowBinding = new BasicHttpBinding();
mynoshowBinding.OpenTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.ReceiveTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.SendTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.CloseTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.Name = "BasicHttpBinding_ITwoWayAsync";
mynoshowBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
mynoshowBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
mynoshowBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
mynoshowBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
EndpointAddress endPointAddressNoShow = new EndpointAddress(noshowendpoint);
NoShowBTService.WcfService_WorkOrderIntegration_v3Client client = new NoShowBTService.WcfService_WorkOrderIntegration_v3Client(mynoshowBinding, endPointAddressNoShow);
NoShowBTService.UpdateWorkorderEvent ev = new NoShowBTService.UpdateWorkorderEvent();
ev.ActivityNumber = workorder.log_ActivityNumber ?? preimageworkorder.log_ActivityNumber;
ev.EmployeeNumber = engineer.log_EmployeeNumber;
ev.EventType = NoShowBTService.UpdateWorkorderEventEventType.ActivateNoShow;
client.ClientCredentials.UserName.UserName = "xxx";
client.ClientCredentials.UserName.Password = "xxx";
client.UpdateWorkorderEvent(ev);
}workorder.log_ProcessNoShow = "Activated";
localContext.Trace("Activated.");
if (localContext.PluginExecutionContext.InitiatingUserId == null) localContext.Trace("initiatinguserid = null");
localContext.Trace("InitiatingUserId: " + localContext.PluginExecutionContext.InitiatingUserId.ToString());
EntityReference callinguserRef = new EntityReference("systemuser", localContext.PluginExecutionContext.InitiatingUserId);
workorder.log_NoShowActivatedBy = callinguserRef;
localContext.OrganizationService.Update(workorder);
return;
}// PDA logic
if (workorder.log_ProcessPDA == "Activated") return;
else if (workorder.log_ProcessPDA == "Activate")
{
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.OpenTimeout = new TimeSpan(0, 3, 0);
myBinding.ReceiveTimeout = new TimeSpan(0, 3, 0);
myBinding.SendTimeout = new TimeSpan(0, 3, 0);
myBinding.CloseTimeout = new TimeSpan(0, 3, 0);
myBinding.Name = "BasicHttpBinding_ITwoWayAsyncVoid1";
myBinding.Security.Mode = BasicHttpSecurityMode.None;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
EndpointAddress endPointAddress = new EndpointAddress(Utilities.GetConfigItem<string>("log_wopdaupdateserviceendpoint", localContext.OrganizationService));
WorkOrderUpdateServiceClient WOupdateservice = new WorkOrderUpdateServiceClient(myBinding, endPointAddress);EntityReference engineerRef = workorder.log_EmployeeId ?? preimageworkorder.log_EmployeeId;
if (engineerRef == null) throw new InvalidPluginExecutionException("Engineer must be specified before submitting to SectorMobile.");
log_employee engineer = ((Entity)localContext.OrganizationService.Retrieve("log_employee", engineerRef.Id, new ColumnSet(true))).ToEntity<log_employee>();
string engineerno = engineer.log_EmployeeNumber;
string country = Utilities.GetConfigItem<string>("log_noshowactivationcountry", localContext.OrganizationService);//oppdaterer WO (gml metode)...
//BizTalk endpoint disabled in TEST, therefore skip it)
var servername = Environment.MachineName.ToLower();
if (!servername.Contains("dev") && !servername.Contains("test") && !servername.Contains("tst"))
{
UpdateWorkOrder updateWO = new UpdateWorkOrder() { ActivityNumber = (workorder.log_ActivityNumber ?? preimageworkorder.log_ActivityNumber), Country = country, Engineer = engineerno };
WOupdateservice.UpdateWorkOrder(updateWO);
}//oppdaterer WO (ny metode)...
string noshowendpoint = null;
using (var orgcontext = new OrganizationServiceContext(localContext.OrganizationService))
{
noshowendpoint = (from s in orgcontext.CreateQuery<log_sectormobileconfigurationsetting>()
where s.log_name == "NoShowEndpoint"
select s.log_Value).FirstOrDefault();
}//oppdaterer WO products..
if (!string.IsNullOrWhiteSpace(noshowendpoint))
{
BasicHttpBinding mynoshowBinding = new BasicHttpBinding();
mynoshowBinding.OpenTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.ReceiveTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.SendTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.CloseTimeout = new TimeSpan(0, 3, 0);
mynoshowBinding.Name = "BasicHttpBinding_ITwoWayAsync";
mynoshowBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
mynoshowBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
mynoshowBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
mynoshowBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
EndpointAddress endPointAddressNoShow = new EndpointAddress(noshowendpoint);
NoShowBTService.WcfService_WorkOrderIntegration_v3Client client = new NoShowBTService.WcfService_WorkOrderIntegration_v3Client(mynoshowBinding, endPointAddressNoShow);
NoShowBTService.UpdateWorkorderEvent ev = new NoShowBTService.UpdateWorkorderEvent();
ev.ActivityNumber = workorder.log_ActivityNumber ?? preimageworkorder.log_ActivityNumber;
ev.EmployeeNumber = engineer.log_EmployeeNumber;
ev.EventType = NoShowBTService.UpdateWorkorderEventEventType.UpdateWorkorderProducts;
client.ClientCredentials.UserName.UserName = "xxx";
client.ClientCredentials.UserName.Password = "xxx";
client.UpdateWorkorderEvent(ev);
}workorder.log_ProcessPDA = "Activated";
localContext.OrganizationService.Update(workorder);
return;
}
#endregion#region Cancel WorkOrder/Contract/Installation if CancelOptyStatusCode is given
int opportunitystatuscode = -1;
if (preImageWorkOrder.Attributes.ContainsKey("log_canceloptystatuscode")) opportunitystatuscode = (int)preImageWorkOrder.Attributes["log_canceloptystatuscode"];
else if (WorkOrder.Attributes.ContainsKey("log_canceloptystatuscode")) opportunitystatuscode = (int)WorkOrder.Attributes["log_canceloptystatuscode"];localContext.Trace("log_canceloptystatuscode = " + opportunitystatuscode);
if (opportunitystatuscode == -1) return;
EntityReference opportunityRef = (EntityReference)preImageWorkOrder.Attributes["log_regardingopportunity"];
Entity opportunity = localContext.OrganizationService.Retrieve("opportunity", opportunityRef.Id, new ColumnSet(true));EntityReference installationRef = (EntityReference)preImageWorkOrder.Attributes["log_installationid"];
Entity installation = null;
if (installationRef != null)
installation = localContext.OrganizationService.Retrieve("log_installation", (Guid)installationRef.Id, new ColumnSet(true));//Finding all contracts related to installation
var ceInstallation = new ConditionExpression("log_installationid", ConditionOperator.Equal, installation.Id);
//Finding all contracts with status active
var ceStatusReason = new ConditionExpression("statecode", ConditionOperator.Equal, 0);
var fe = new FilterExpression(LogicalOperator.And);
fe.Conditions.Add(ceInstallation);
fe.Conditions.Add(ceStatusReason);var qe = new QueryExpression("log_contract") { Criteria = fe, ColumnSet = new ColumnSet(true) };
Entity contract = null;
DataCollection<Entity> contracts = localContext.OrganizationService.RetrieveMultiple(qe).Entities;
if (contracts != null && contracts.Count > 0)
contract = contracts[0];SetStateRequest setOpportunityStateReq = new SetStateRequest();
setOpportunityStateReq.EntityMoniker = new EntityReference(opportunity.LogicalName, opportunity.Id);
setOpportunityStateReq.State = new OptionSetValue(0); // Open
setOpportunityStateReq.Status = new OptionSetValue(1); // In-Progress
SetStateResponse OpportunitySetStateResponse = (SetStateResponse)localContext.OrganizationService.Execute(setOpportunityStateReq);if (installation != null)
{
SetStateRequest setInstallationStateReq = new SetStateRequest();
setInstallationStateReq.EntityMoniker = new EntityReference(installation.LogicalName, installation.Id);
setInstallationStateReq.State = new OptionSetValue(1); // Inactive
setInstallationStateReq.Status = new OptionSetValue(2); // Terminated
SetStateResponse InstallationSetStateResponse = (SetStateResponse)localContext.OrganizationService.Execute(setInstallationStateReq);
}if (contract != null)
{
SetStateRequest setContractStateReq = new SetStateRequest();
setContractStateReq.EntityMoniker = new EntityReference(contract.LogicalName, contract.Id);
setContractStateReq.State = new OptionSetValue(1); // Inactive
setContractStateReq.Status = new OptionSetValue(2); // Terminated
SetStateResponse ContractStateResponse = (SetStateResponse)localContext.OrganizationService.Execute(setContractStateReq);
}Entity closeOpportunity = new Entity("opportunityclose");
closeOpportunity.Attributes.Add(new KeyValuePair<string, object>("opportunityid", new EntityReference("opportunity", opportunity.Id)));
LoseOpportunityRequest loseOpportunityRequest = new LoseOpportunityRequest();
loseOpportunityRequest.OpportunityClose = closeOpportunity;
loseOpportunityRequest.RequestName = "LoseOpportunity";
loseOpportunityRequest.Status = new OptionSetValue(opportunitystatuscode);
LoseOpportunityResponse loseOpportunityResponse = (LoseOpportunityResponse)localContext.OrganizationService.Execute(loseOpportunityRequest);SetStateRequest setWorkOrderStateReq = new SetStateRequest();
setWorkOrderStateReq.EntityMoniker = new EntityReference(WorkOrder.LogicalName, workorderid);
setWorkOrderStateReq.State = new OptionSetValue(2);
setWorkOrderStateReq.Status = new OptionSetValue(182400003);
SetStateResponse WorkOrderSetStateResponse = (SetStateResponse)localContext.OrganizationService.Execute(setWorkOrderStateReq);
#endregion
}
}- Edited by morris80 Friday, December 23, 2016 9:20 PM
Friday, December 23, 2016 7:59 AM -
Anyone have a clue? :-)Thursday, December 29, 2016 9:26 AM
-
Hi,
Create a new object for the entity(log_workorders) and then add the necessary attributes. Do not directly push/assign the entity object from target/preimage/postimage.
Technically when the entity object has some attributes on update, it is considered as update even though the attribute value is not modified. This causes infinite loop if I am not wrong. Below is a sample
log_workorders workorders = new log_workorders() { Id = <Id of the record to be updated>}
workorders.<attribute to be updated> = <value>;Please mark as resolved if this solves your problem. All the best.
Ramanathan Rajendran MCTS - Dynamics CRM
- Proposed as answer by Ramanthan Rajendran Friday, December 30, 2016 12:05 AM
Friday, December 30, 2016 12:04 AM