The Microsoft Dynamics CRM Blog
News and views from the Microsoft Dynamics CRM Team

Microsoft Dynamics CRM 4.0 IWorkflowContext Interface

Microsoft Dynamics CRM 4.0 IWorkflowContext Interface

  • Comments 1

Recently there have been some questions raised on how to use the IWorkflowContext and what data and objects it provides that can be used in your custom workflow activity logic. In this post we will cover the different members available in the IWorkflowContext interface.

The IWorkflowContext interface is the interface that is used to provide a way to obtain business data that is needed to correctly implement your business logic in a custom workflow activity.

In order to start we first need to understand how the IWorkflowContext is initialized.

Where does the IWorkflowContext come from?

The IWorkflowContext is initialized for a particular asyncoperation of type workflow (operationtype 10) when the asyncoperation of type workflow is processed and executed by the Asynchronous Service. However that is only where the context object is created. The data that is contained in the context object was collected prior to this action.

The Workflow Expansion Task plugin executes asynchronously for a particular message in CRM. For example if you have published a workflow to execute on Create of account, the Workflow Expansion Task plugin will be registered as a step on the Create message for the account entity when the workflow is published. The step will execute asynchronously. The Workflow Expansion Task plugin will retrieve all workflow rules that are published and that are configured to execute when the current message executes. So if you have more than one workflow that is published and should execute on the create message, the primary entity for the workflow is account, and you have access to the workflow based on the scope setting, those workflows will be retrieved.

The Workflow Expansion Task plugin will loop over each of the workflows retrieved and create an asyncoperation with an operationtype of 10 (Workflow). When the asyncoperation is created certain attributes are populated so that when the asyncoperation is processed by the Asynchronous Service it knows how to process the record. One of the attributes that is populated is the data attribute. In the SDK documentation the data attribute is a string property. The data property contains one of two types of serialized objects

AsyncOperationData

WorkflowData

Since we are working with an asyncoperation record of type workflow, the object is a WorkflowData object. When the asyncoperation is processed and executed by the Asynchronous Service, this WorkflowData object will be the basis of the IWorkflowContext object that we will have access to in our custom workflow activity.

Now that we know where the IWorkflowContext comes from, let’s look at how we can get access to the interface

How to get the IWorkflowContext object

The IWorkflowContext object can be obtained through the IContextService interface. Great, another interface! How do you get the IContextService interface??? Simple, we can obtain the IContextService interface through the GetService method on the ActivityExecutionContext which is provided as a parameter in our overridden Execute method for our custom workflow activity.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

{

IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService ));

Now that we have our IContextService interface, we can now access the Context property which is of type IWorkflowContext.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

{

IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService ));

IWorkflowContext context = contextService.Context;

Now that we know how to get the IWorkflowContext we can now look at what data it can provide

Great, we have the IWorkflowContext! Now what can we do with it?

In order to see what we have access to through the IWorkflowContext we can view the definition of it in Visual Studio by right-clicking IWorkflowContext, then clicking “Go To Definition”. When we do this we see the following

public interface IWorkflowContext

{

Guid ActivationId { get; }

Guid AsyncOperationId { get; }

Collection<EntityDependencyBase> EntityDependencies { get; }

PropertyBag InputParameters { get; }

string MessageName { get; }

Guid OrganizationId { get; }

PropertyBag OutputParameters { get; }

Guid PluginTypeId { get; }

Guid PrimaryEntityId { get; }

DynamicEntity PrimaryEntityImage { get; }

string PrimaryEntityName { get; }

DynamicEntity PrimaryEntityPostImage { get; }

DynamicEntity PrimaryEntityPreImage { get; }

PropertyBag SharedVariables { get; }

string StageName { get; }

Guid UserId { get; }

ICrmService CreateCrmService();

ICrmService CreateCrmService(bool asAdminUser);

IMetadataService CreateMetadataService();

IMetadataService CreateMetadataService(bool asAdminUser);

bool EvaluateCondition(ConditionOperator op, object primaryValue, params object[] values);

object EvaluateExpression(ExpressionOperator op, params object[] values);

void PopulateEntitiesFrom(CrmWorkflow workflow, string parameterName);

int RetrieveActivityCount(bool includeActivitiesCreatedByWorkflow);

}

Let’s go over each member in this interface
Properties

ActivationId: This is the workflowid for the workflowbase record that is the activation record for the workflow. In other words, this describes which workflow this is an instance of.

AsyncOperationId: This is the ID of the asyncoperationbase record.

EntityDependencies: This is a generic collection of EntityDependencyBase objects. An EntityDependencyBase object can be of one of the following types

PrimaryEntityDependency: Specifies the objectTypeCode (Int32), comma delimited attributes to retrieve for the primary entity (String), and the type of parameter it is (Type)

RelatedEntityDependency: Specifies the objectTypeCode (Int32), comma delimited attributes to retrieve for a related entity (String), and the type of parameter it is (Type)

You are going to have 1 PrimaryEntityDependency, and X RelatedEntityDependencies.

InputParameters: InputParameters is a property bag which contains the objects from the request that triggered the workflow. For example, if the workflow executed due to a create message for account, the InputParameters property bag would contain the target account as a DynamicEntity. You access the objects in the property bag just as you would when using a plugin.

MessageName: The name of the message which triggered the workflow to execute. Create, Delete, Update, or SetState.

OrganizationId: The ID of the organization to which this asyncoperation belongs

OutputParameters: OutputParameters is exactly the same as InputParameters. It contains the output of the request. For create, it would contain the GUID of the business entity created.

PluginTypeId: The ID of the plugin type. This is the ID for the compiled Windows Workflow that this asyncoperation is an instance of.

PrimaryEntityImage: A DynamicEntity object that represents the primary business entity for which the workflow is regarding. If you want to get attributes included in the create or update request, you don’t want to use this. Instead get the Target property out of the InputParameters property bag

PrimaryEntityName: The schema name for the entity that this workflow is regarding.

PrimaryEntityPostImage: DynamicEntity which contains the primary entity’s ID attribute along with the values for the attributes defined in the PrimaryEntityDependency after the operation which triggered the workflow to execute. This is not specific to a singular workflow, but contains all the needed attributes for all workflows registered to execute on the same message for the same entity type.

PrimaryEntityPreImage: DynamicEntity which contains the primary entity’s ID attribute along with the values for the attributes defined in the PrimaryEntityDependency after the operation which triggered the workflow to execute. This is not specific to a singular workflow, but contains all the needed attributes for all workflows registered to execute on the same message for the same entity type.

SharedVariables: Another property bag in which you can store data to be persisted to the database for use through-out the execution of the workflow. Also SharedVariables will contain any objects that have been stored in the SharedVariables property bag from the plugin execution context during the entire life of the pipeline for the message which triggered the workflow to execute. So you could store an object in the SharedVariables property bag pre create of an account, and that object would be available in any workflows that were created on create of the account.

Note: The IWorkflowContext’s SharedVariables property gets populated from the SharedVariables property on the IPluginExecutionContext for the “Workflow Expansion Task” asynchronous plugin. The “Workflow Expansion Task” executes in the Child pipeline. So if you want values from before the main operation (BeforeMainOperationOutsideTransaction) you need to register your Pre plugin step in the Child pipeline as well. Further, any SharedVariables you populate after the main operation (AfterMainOperationOutsideTransaction) will not be included even if you register your Post plugin step in the Child pipeline since the “Workflow Expansion Task” executes in the pipeline stage that is not available to third parties (AfterMainOperationInsideTransaction).

StageName: The name of the stage that workflow is currently in.

UserId: If the workflow was executed on demand, this will be the ID of the user who executed the workflow. If the workflow was executed due to a message executing, then it will be the ID of the workflow owner.

Methods

CreateCrmService:

CreateCrmService(bool asAdminUser):

Both of these methods return an ICrmService interface. This is optimal way to interact with CRM to execute the various requests in the CRM web service. The overload allows you to execute with more privileges if needed; just in case the current user doesn’t have the required privileges to perform some action in your custom business logic.

CreateMetadataService():

CreateMetadataService(bool asAdminUser):

Both of these methods return an IMetadataService interface. This is optimal way to interact with CRM to execute the various requests in the MetadataService web service. The overload allows you to execute with more privileges if needed; just in case the current user doesn’t have the required privileges to perform some action in your custom business logic.

RetrieveActivityCount: Retrieves the number of CRM activity records created so far by this workflow

The following methods are for internal use only and are not intended for third party use

EvaluateCondition(ConditionOperator op, object primaryValue, params object[] values):

EvaluateExpression(ExpressionOperator op, params object[] values):

PopulateEntitiesFrom(CrmWorkflow workflow, string parameterName):

Cheers,

Clint Warriner

Page 1 of 1 (1 items)
Leave a Comment
  • Please add 8 and 3 and type the answer here:
  • Post