Event Framework

The capability to extend the default behavior of Common Data Service depends on detecting when events occur on the server. The Event Framework provides the capability to register custom code to be run in response to specific events.

All capabilities to extend the default behavior of the platform depend on the event framework. When you configure a workflow to respond to an event using the workflow designer without writing code, that event is provided by the event framework.

As a developer, you will use the Plug-in registration tool to configure plug-ins, Azure integrations, virtual entity data providers, and Web Hooks to respond to events that are provided by the event framework. When events occur and an extension is registered to respond to them, contextual information about the data involved in the operation is passed to the extension. Depending on how the registration for the event is configured, the extension can modify the data passed into it, intiate some automated process to be applied immediately, or define that an action is added to a queue to be performed later.

To leverage the event framework for your custom extensions you must understand:

  • What events are available
  • How the event is processed
  • What kind of data is available to your extension when the event occurs
  • What time and resource constraints apply
  • How to monitor performance

Available events

As described in Use messages with the Organization service, data operations in the Common Data Service platform are based on messages and every message has a name. There are Create, Retrieve, RetrieveMultiple, Update, Delete, Associate and Disassociate messages that cover the basic data operations that happen with entities. There are also specialized messages for more complex operations. Custom actions add new messages.

When you use the Plug-in registration tool to associate an extension with a particular message, you will register it as a step. The screenshot below is the Register New Step dialog used when registering a plug-in.

Dialog to register a step

A step provides the information about which message the extensions should respond to as well as a number of other configuration choices. Use the Message field to choose the message your extension will respond to.

Generally, you can expect to find a message for most of the *Request classes in the Microsoft.Crm.Sdk.Messages or Microsoft.Xrm.Sdk.Messages namespaces, but you will also find messages for any custom actions that have been created in the organization. Any operations involving entity metadata are not available.

Data about messages is stored in the SdkMessage and SdkMessageFilter entities. The Plug-in registration tool will filter this information to only show valid messages.

To verify if a message and entity combination supports execution of plug-ins using a database query, use Advanced Find or a community tool (e.g., FetchXML Builder) to execute the following fetchXML query. When using Advanced Find, you must create the query interactively.

<fetch>
  <entity name='sdkmessage' >
    <attribute name='name' />
    <link-entity name='sdkmessagefilter' alias='filter' to='sdkmessageid' from='sdkmessageid' link-type='inner' >
      <filter type='and' >
        <condition attribute='iscustomprocessingstepallowed' operator='eq' value='1' />
        <condition attribute='isvisible' operator='eq' value='1' />
      </filter>
      <attribute name='primaryobjecttypecode' />
    </link-entity>
    <filter>
      <condition attribute='isprivate' operator='eq' value='0' />
      <condition attribute='name' operator='not-in' >
        <value>SetStateDynamicEntity</value>
        <value>RemoveRelated</value>
        <value>SetRelated</value>
	   <value>Execute</value>
      </condition>
    </filter>
    <order attribute='name' />
  </entity>
</fetch>

Caution

The Execute message is available, but you should typically not register extensions for it since it is called by every operation.

Note

There are certain cases where plug-ins and workflows that are registed for the Update event can be called twice. More information: Behavior of specialized update operations

Event execution pipeline

When you register a step using the Plug-in registration tool you must also choose the Event Pipeline Stage of Execution. Each message is processed in a series of 4 stages as described in the following table:

Name Description
PreValidation
Stage: 10
For the initial operation, this stage will occur before the main system operation.

This provides an opportunity to include logic to cancel the operation before the database transaction.

Subsequent operations triggered by extensions registered in other stages will pass through this stage as well but will be included within the transaction of the calling extensions.

This stage occurs before any security checks are preformed to verify that the calling or logged-on user has the correct permission to perform the intended operation.
PreOperation
Stage: 20
Occurs before the main system operation and within the database transaction.

If you want to change any values for an entity included in the message, you should do it here.

Avoid cancelling an operation here. Canceling will trigger a rollback of the transaction and have significant performance impact.
MainOperation
Stage: 30
For internal use only.
PostOperation
Stage: 40
Occurs after the main system operation and within the database transaction.

Use this stage to modify any properties of the message before it is returned to the caller.

Avoid applying changes to an entity included in the message because this will trigger a new Update event.

The stage you should choose depends on the purpose of the extension. You don't need to apply all your business logic within a single step. You can apply multiple steps so that your logic about whether to allow a operation to proceed can be in the PreValidation stage and your logic to make modifications to the message properties can occur in the PostOperation stage.

Important

An exception thrown by your code at any stage will cause the entire transaction to be rolled back. You should be careful to ensure that any possible exception cases are handled by your code. If you want to cancel the operation, you should detect this in the PreValidation stage and only throw a InvalidPluginExecutionException containing an appropriate message describing why the operation was cancelled.

Multiple extensions can be registered for the same message and stage. Within the step registration the Execution Order value determines the order in which multiple extensions should be processed for a given stage.

Information about registered steps is stored in the SdkMessageProcessingStep Entity.

Event context

If your extension is a Plug-in, it will receive a parameter that implements the IPluginExecutionContext interface. This class provides some information about the Stage that the plugin is registered for as well as information about the ParentContext which provides information about any operation within another Plug-in that triggered the current operation.

If your extension is an a Web hook or an Azure Service bus endpoint, the data that will be posted to the registered endpoint will be in form of a RemoteExecutionContext which implements both IPluginExecutionContext and IExecutionContext

For more information about the execution context, read Understand the execution context.