Dynamics CRM 2011 check previous value in preimage in workflow

Sometimes it is required to check the previous value in a workflow triggered when record is updated.

The out of the box workflow create user interface only provide access to current value of the record which is the value after modification.

We could write one custom workflow activity to retrieve that value from IExecutionContext, which can be accessed from IWorkflowContext within custom workflow activity.


protected override void Execute(CodeActivityContext executionContext)
 {
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
Entity preImageEntity = context.PreEntityImages.Values.FirstOrDefault();
}

When use InOutArgument<EntityReference > in custom workflow activity, we need to specify the entity name which made it difficult to reuse, instead we could accept the attribute name of the lookup field and output entity name and record id for that lookup field. We can use entity name and record id in other workflow activity to perform generic tasks.

Here is a sample code to retrieve record id and entity name from custom workflow activity


public sealed class GetRecordIdEntityName : CodeActivity
 {
 [Input("Attribute Name for Related Record")]
 public InArgument<String> AttributeName { get; set; }

[Output("Primary Entity Name")]
 public OutArgument<String> PrimaryEntityName { get; set; }

[Output("Primary Record Id")]
 public OutArgument<String> PrimaryRecordId { get; set; }

[Output("Related Entity Name")]
 public OutArgument<String> RelatedEntityName { get; set; }

[Output("Pre Related Record Id")]
 public OutArgument<String> PreRelatedRecordId { get; set; }

[Output("Post Related Record Id")]
 public OutArgument<String> PostRelatedRecordId { get; set; }

/// <summary>
 /// Executes the workflow activity.
 /// </summary>
 /// <param name="executionContext">The execution context.</param>
 protected override void Execute(CodeActivityContext executionContext)
 {
 // Create the tracing service
 ITracingService tracingService = executionContext.GetExtension<ITracingService>();

if (tracingService == null)
 {
 throw new InvalidPluginExecutionException("Failed to retrieve tracing service.");
 }

tracingService.Trace("Entered GetRecordId.Execute(), Activity Instance Id: {0}, Workflow Instance Id: {1}",
 executionContext.ActivityInstanceId,
 executionContext.WorkflowInstanceId);

// Create the context
 IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();

if (context == null)
 {
 throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
 }

tracingService.Trace("GetRecordId.Execute(), Correlation Id: {0}, Initiating User: {1}",
 context.CorrelationId,
 context.InitiatingUserId);

IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
 IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

try
 {
 // TODO: Implement your custom Workflow business logic.
 ExecuteCore(executionContext, context, service);
 }
 catch (FaultException<OrganizationServiceFault> e)
 {
 tracingService.Trace("Exception: {0}", e.ToString());

// Handle the exception.
 throw;
 }

tracingService.Trace("Exiting GetRecordId.Execute(), Correlation Id: {0}", context.CorrelationId);
 }

private void ExecuteCore(CodeActivityContext executionContext, IWorkflowContext context, IOrganizationService service)
 {
 this.PrimaryRecordId.Set(executionContext, context.PrimaryEntityId.ToString());

this.PrimaryEntityName.Set(executionContext, context.PrimaryEntityName.ToLowerInvariant());

string attributeName = this.AttributeName.Get(executionContext);

this.RelatedEntityName.Set(executionContext, null);

if (!string.IsNullOrWhiteSpace(attributeName))
 {
 Entity preImageEntity = context.PreEntityImages.Values.FirstOrDefault();
 if (preImageEntity != null && preImageEntity.Contains(attributeName) && preImageEntity[attributeName] is EntityReference)
 {
 EntityReference entityRef = preImageEntity.GetAttributeValue<EntityReference>(attributeName);
 this.RelatedEntityName.Set(executionContext, entityRef.LogicalName.ToLowerInvariant());
 this.PreRelatedRecordId.Set(executionContext, entityRef.Id.ToString());
 }
 else
 {
 this.PreRelatedRecordId.Set(executionContext, null);
 }

Entity postImageEntity = context.PostEntityImages.Values.FirstOrDefault();
 if (postImageEntity != null && postImageEntity.Contains(attributeName) && postImageEntity[attributeName] is EntityReference)
 {
 EntityReference entityRef = postImageEntity.GetAttributeValue<EntityReference>(attributeName);
 this.RelatedEntityName.Set(executionContext, entityRef.LogicalName.ToLowerInvariant());
 this.PostRelatedRecordId.Set(executionContext, entityRef.Id.ToString());
 }
 else
 {
 this.PostRelatedRecordId.Set(executionContext, null);
 }
 }
 else
 {
 this.PreRelatedRecordId.Set(executionContext, null);
 this.PostRelatedRecordId.Set(executionContext, null);
 }
 }
 }

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s