I have this code that runs in a real time workflow on record creation. It basically determines on which entity it's running on, tries to get the "related to field", which can change from entity to another, then see if the related record is an account, if so, update some of the account's attributes.
public override void ExecuteWorkflowLogic(XrmObjects xrmObjects)
{
using (XrmServiceContext ctx = new XrmServiceContext(xrmObjects.Service))
{
var target = xrmObjects.WorkflowContext.InputParameters["Target"] as Entity;
Xrm.Account account = null;
var regardingFieldName = string.Empty;
var logicalName = string.Empty;
var primaryKeyName = string.Empty;
switch (target.LogicalName)
{
case Xrm.Task.EntityLogicalName:
case Xrm.Email.EntityLogicalName:
case Xrm.PhoneCall.EntityLogicalName:
case Xrm.Letter.EntityLogicalName:
case Xrm.Appointment.EntityLogicalName:
case Xrm.Fax.EntityLogicalName:
regardingFieldName = "regardingobjectid";
logicalName = Xrm.ActivityPointer.EntityLogicalName;
primaryKeyName = "activityid";
break;
case Xrm.Annotation.EntityLogicalName:
logicalName = Xrm.Annotation.EntityLogicalName;
regardingFieldName = "objectid";
primaryKeyName = "annotationid";
break;
case Xrm.Opportunity.EntityLogicalName:
regardingFieldName = "customerid";
logicalName = Xrm.Opportunity.EntityLogicalName;
primaryKeyName = "opportunityid";
break;
case Xrm.Post.EntityLogicalName:
regardingFieldName = "regardingobjectid";
logicalName = Xrm.Post.EntityLogicalName;
primaryKeyName = "postid";
break;
}
var activity = (from a in ctx.CreateQuery(logicalName)
where a[regardingFieldName] != null && (Guid)a[primaryKeyName] == target.Id
select a).FirstOrDefault();
var ec = (EntityReference)activity[regardingFieldName];
if (ec == null)
return;
//if regarding isn't an account...
if (ec.LogicalName != Xrm.Account.EntityLogicalName)
return;
account = ctx.AccountSet.SingleOrDefault(x => x.Id == ec.Id);
if (account == null)
return;
account.new_last_activity_created_by = (EntityReference)target["createdby"];
account.new_last_activity_date = (DateTime)target["createdon"];
account.new_last_activity_type = GetActivityType(target); //returns an optionset based on entity logical name....
account.new_last_activity_entity_logicalname = target.LogicalName;
if (!ctx.IsAttached(account))
ctx.Attach(account);
ctx.UpdateObject(account);
ctx.SaveChanges();
}
}
I want it to run in a real time workflow, because the changes are going to be instant and also, because the user created the entity above may not have the right to update the account, so a real time workflow allows me to do the update as another user (workflow owner) that has the rights to do so.
The problem is when it's for an activity entity (the first big block in the switch statement), the record looks like it has no been committed to the database and there's no way for me to fetch it and look further into it (activity
ends up null)
If I look for target
's GUID in ActivityPointerBase
or TaskBase
, EmailBase
, etc. I am not seeing it anywhere during the execution of this workflow (which happens after a record is created I assume)
If I run this in an async workflow, it works for all entities.
In real time mode, it only works for opportunities, posts and annotations. I am creating the activities from the social feed menu in my tests.
The code above runs within a method in a class that extends BaseWorkflowStep
:
public abstract class BaseWorkflowStep : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
var xrmObjects = new XrmObjects();
var serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
xrmObjects.CodeActivityContext = context;
xrmObjects.TracingService = context.GetExtension<ITracingService>();
xrmObjects.WorkflowContext = context.GetExtension<IWorkflowContext>();
xrmObjects.Service = serviceFactory.CreateOrganizationService(xrmObjects.WorkflowContext.UserId);
ExecuteWorkflowLogic(xrmObjects);
}
public virtual void ExecuteWorkflowLogic(XrmObjects xrmObjects)
{
throw new NotImplementedException();
}
}
What's happening here ?