My plugin doesn't work when i set it to be synchrounous, it says that it entered a infinite loop on the error message, when i debug it i don't see any error, when i set to Async it works.
One thing i noticed, when it's set to Async, the plugin will run 1 one time on the create step and a few times (6~8) on the update step (the last one fails, informing about the infite loop), but i only created the case, i didn't updated and my workflows don't touch the fields that were supposed to trigger the update case step of the plugin. The plugin is filtered for only 2 fields (customerid and subjectid) that are not changed by my plugin, so i don't know why it keeps calling the plugin again and again.
This is my code:
public class CaseContractFill : IPlugin
{
Contract checkForContract(Guid accountId, IOrganizationService service)
{
//Bring all contracts associated with a account
QueryExpression accountContractQuery = new QueryExpression
{
EntityName = Contract.EntityLogicalName,
ColumnSet = new ColumnSet(true),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression
{
AttributeName = "accountid",
Operator = ConditionOperator.Equal,
Values = { accountId }
}
}
}
};
DataCollection<Entity> accountContracts = service.RetrieveMultiple(accountContractQuery).Entities;
//Check if account has a Active or Invoiced contract and return it
if (accountContracts.Count > 0)
{
foreach (Contract item in accountContracts)
{
if (item.StateCode == ContractState.Active || item.StateCode == ContractState.Invoiced)
{
return item;
}
}
}
//Retrieves account information
Account account = (Account)service.Retrieve(Account.EntityLogicalName, accountId, new ColumnSet(true));
//Check if account has a parent and call this method again with that parent
if (account.ParentAccountId != null)
{
return checkForContract(account.ParentAccountId.Id, service);
}
//If no Contract and/or no Parent returns null
return null;
}
ContractDetail checkForContractLine(Guid contractId, Incident incident, IOrganizationService service)
{
//Query to bring all contract lines from a contract id
QueryExpression accountContractQuery = new QueryExpression
{
EntityName = ContractDetail.EntityLogicalName,
ColumnSet = new ColumnSet(true),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression
{
AttributeName = "contractid",
Operator = ConditionOperator.Equal,
Values = { contractId }
}
}
}
};
DataCollection<Entity> contractLines = service.RetrieveMultiple(accountContractQuery).Entities;
ContractDetail contractLine = null;
// Check all contract lines to find one that matches the Case subject with the contract line product name, if none is found, returns a active one
foreach (ContractDetail item in contractLines)
{
if ((item.StateCode == ContractDetailState.Existing) || (item.StateCode == ContractDetailState.Renewed))
{
if ((incident.SubjectId != null) && (item.ProductId != null))
{
if (incident.SubjectId.Name.Equals(item.ProductId.Name))
{
contractLine = item;
break;
}
contractLine = item;
}
}
}
return contractLine;
}
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
try
{
Entity entity = (Entity)context.InputParameters["Target"];
Incident incident = (Incident)entity.ToEntity<Incident>();
incident = (Incident)service.Retrieve(Incident.EntityLogicalName, incident.Id, new ColumnSet(true));
Contract contract = checkForContract(incident.CustomerId.Id, service);
if (contract != null)
{
incident.ContractId = contract.ToEntityReference();
ContractDetail contractLine = checkForContractLine(contract.Id, incident, service);
if (contractLine != null)
{
incident.ContractDetailId = contractLine.ToEntityReference();
}
service.Update(incident);
}
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
}