Reputation: 370
I have created a plugin for Update with PreImage. When something change in the entity, the plugin will fire.
In the plugin I call a webservice, and I want to save the webservice response in a field. But the plugin doesn't commit my change. And when I use Service.Update
, the plugin rises an error for workflow loop.
if (context.InputParameters.Contains("Target") && (context.InputParameters["Target"] is Entity))
{
Entity entity2 = (Entity)context.InputParameters["Target"];
Entity PreImageEntity = (Entity)context.PreEntityImages["PreImage"];
if (entity2.LogicalName == "ppp_sentsms")
{
QueryExpression expression3 = new QueryExpression("ppp_sentsms");
ColumnSet set2 = new ColumnSet();
set2.AllColumns = true;
expression3.ColumnSet = set2;
ConditionExpression item = new ConditionExpression();
item.AttributeName = "ppp_sentsmsid";
this.CurrentSmsGuid = (Guid)entity2.Attributes["ppp_sentsmsid"];
item.Values.Add(this.CurrentSmsGuid);
FilterExpression expression5 = new FilterExpression();
expression5.Conditions.Add(item);
expression3.Criteria = expression5;
EntityCollection entitys2 = service.RetrieveMultiple(expression3);
string strResponceValue = "";
string strResponceValuePreImage = "";
foreach (Entity smsentity in entitys2.Entities)
{
if (smsentity.Attributes.Contains("ppp_status") && smsentity.Attributes.Contains("ppp_webserviceid"))
{
strResponceValuePreImage = PreImageEntity["ppp_status"].ToString();
strResponceValue = CheckSMSStatus(this.username, this.password, smsentity["ppp_webserviceid"].ToString());
if (strResponceValue.Trim() != strResponceValuePreImage.Trim())
{
entity2["ppp_status"] = strResponceValue;
// service.Update(smsentity);
}
}
}
}
How can I fix this problem?
Upvotes: 0
Views: 1412
Reputation: 6715
The reason you are getting an error which references an infinite loop:
The plugin is registered on update, and itself updates the record. This means the plugin effectively calls itself.
CRM has an infinite loop detection mechanism and if triggered, will throw an exception to stop the plugin (or workflow) running. This is a useful facility - without it the plugin above would have looped forever, or to be more precise, until it forced your server to fall over.
A field on the plugin context, which is called 'Depth', can tell you about looping. It is an int value (default of 1) and it describes at what level the event was triggered.
So the initial update would have a depth of 1. When the plugin causes another update, the plugin runs again and this time the depth is 2. When the plugin causes another update, the plugin runs again and this time the depth is 3. And so on..
So to get around this, you can check the depth:
if (context.Depth > 1) {
return; //Exit to prevent looping
}
A further update on the infinite loop mechanism: by default (I believe it can be changed in the registry, but don't quote me on that!) if CRM sees a plugin/workflow loop eight times within one hour, an exception is thrown. Obviously with a synchronous plugin, this is quickly done. With a workflow, that might contain timeouts and waits', and this can be harder to diagnose.
IMO therefore, where possible, a pre-update plugin is preferable if you want to amend the record on which the plugin is acting.
Upvotes: 1
Reputation: 370
I found the problem after googling it. I registered the update step in the post operation. And I have to register in pre operation.
There is no need to do service.Update(smsentity);
.
CRM 2011: Plugin to update fields of current record
Upvotes: 1