Plugin Event Execution Pipeline
Plugin Event Execution Pipeline

Microsoft Dynamics 365 allows you to extend its functionality using plugins custom code that runs in response to specific events, such as creating, updating, or deleting records. The Plugin Event Execution Pipeline is the process Dynamics 365 follows to execute these plugins, with distinct stages where your code can interact with the system.

What is the Plugin Event Execution Pipeline?

The pipeline is a sequence of stages that Dynamics 365 goes through when an event (e.g., creating a contact) triggers a plugin. Each stage lets you add custom logic to validate data, modify records, or perform actions like sending emails. Think of it as a conveyor belt where your plugin can jump in at specific points to do its job.

How Does the Pipeline Work?

Here’s a breakdown of the pipeline’s key components:

  1. Event Registration:
  • You register a plugin to respond to a specific event (e.g., Create, Update, Delete) on an entity (e.g., Contact, Account) using the Plugin Registration Tool or the Dynamics 365 SDK.
  • You specify the entity, event, stage, and whether the plugin runs synchronously (immediately) or asynchronously (in the background with a potential delay).
  1. Pipeline Stages:
    The pipeline has four customizable stages, each with a specific purpose:
  • Pre-Validation (Stage 10):
    • Runs before the main operation and outside the database transaction.
    • Used for early checks, like validating data before processing.
    • If the plugin fails, the operation stops immediately.
    • Example: Check if an email address is valid before creating a contact.

  • Pre-Operation (Stage 20):
    • Runs before the main operation but inside the database transaction.
    • Used to modify data before it’s saved.
    • If the plugin fails, the operation is rolled back.
    • Example: Set a default value for a field.

  • Main Operation (Stage 30):
    • The system performs the core action (e.g., creating or updating a record).
    • You cannot register plugins here; it’s handled by Dynamics 365.

  • Post-Operation (Stage 40, Synchronous):
    • Runs after the main operation, inside the database transaction.
    • Used for additional logic that needs to be part of the transaction.
    • If the plugin fails, the entire operation is rolled back.
    • Example: Create a related record after the main record is saved.

  • Post-Operation (Stage 40, Asynchronous):
    • Runs after the main operation, outside the database transaction.
    • Used for independent tasks, like sending notifications or calling external services.
    • If the plugin fails, it doesn’t affect the main operation.
    • Example: Send an email notification.
  1. Execution Context:
  • The execution context provides details about the event, including:
    • Input Parameters: Data being processed (e.g., fields of a new record).
    • Output Parameters: Results of the operation (e.g., the new record’s ID).
    • Pre/Post-Images: Snapshots of the record’s data before and after the operation (must be explicitly registered in the Plugin Registration Tool).
    • Message: The action type (e.g., Create, Update, Delete).
  • Plugins use this context to read or modify data.
  1. Transaction Handling:
  • Pre-Operation and Post-Operation (Synchronous) plugins are part of the database transaction. If they fail, the entire operation is undone.

  • Post-Operation (Asynchronous) plugins run independently, so their failure doesn’t affect the main operation and may involve a slight delay due to queuing.

Example: Creating a Contact Record

Let’s illustrate with a scenario where a new Contact record is created in Dynamics 365.

Scenario:

When a user creates a contact, you want to:

  1. Validate the email address (Pre-Validation, Stage 10).
  2. Set the “Customer Type” to “Prospect” (Pre-Operation, Stage 20).
  3. Create a follow-up task (Post-Operation, Synchronous, Stage 40).
  4. Send a welcome email (Post-Operation, Asynchronous, Stage 40).

Pipeline Workflow:

  1. User Action:
  • A user creates a contact: “John Doe” with email “john.doe@example.com”.
  1. Pre-Validation (Stage 10):
  • Plugin checks if the email contains “@”. If not (e.g., “invalid-email”), it throws an error (“Invalid email format”), stopping the operation.
  1. Pre-Operation (Stage 20):
  • Plugin sets the “Customer Type” field to “Prospect” by adding customerType = "Prospect" to the input parameters.
  1. Main Operation (Stage 30):
  • Dynamics 365 saves the contact record with the modified data.
  1. Post-Operation (Stage 40, Synchronous):
  • Plugin creates a task: “Call John Doe” linked to the contact.
  • If this fails, the contact creation is rolled back.
  1. Post-Operation (Stage 40, Asynchronous):
  • Plugin sends a welcome email to “john.doe@example.com” via an external service.
  • If this fails, the contact and task remain unaffected.
  1. Completion:
  • The contact is created, the task is added, and the email is sent (if successful).

Example Plugin Code (C#)

Here’s a simplified plugin for the contact creation scenario:

using Microsoft.Xrm.Sdk;

public class ContactPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        IOrganizationService service = ((IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)))
            .CreateOrganizationService(context.UserId);

        if (context.MessageName == "Create" && context.PrimaryEntityName == "contact")
        {
            Entity contact = (Entity)context.InputParameters["Target"];

            // Pre-Validation: Validate email
            if (context.Stage == 10)
            {
                string email = contact.GetAttributeValue<string>("emailaddress1");
                if (string.IsNullOrEmpty(email) || !email.Contains("@"))
                    throw new InvalidPluginExecutionException("Invalid email format.");
            }

            // Pre-Operation: Set Customer Type
            if (context.Stage == 20)
            {
                contact["customertypecode"] = new OptionSetValue(1); // 1 = Prospect
            }

            // Post-Operation (Synchronous): Create task
            if (context.Stage == 40 && context.Mode == 0)
            {
                Entity task = new Entity("task");
                task["subject"] = "Call " + contact.GetAttributeValue<string>("fullname");
                task["regardingobjectid"] = new EntityReference("contact", context.PrimaryEntityId);
                service.Create(task);
            }

            // Post-Operation (Asynchronous): Send email
            if (context.Stage == 40 && context.Mode == 1)
            {
                // Code for external email service (simplified)
            }
        }
    }
}

Registration Steps:

  • Use the Plugin Registration Tool to register the plugin for the “Create” event on the “Contact” entity.
  • Specify stages (10, 20, 40) and modes (synchronous for validation/task, asynchronous for email).
  • Register Pre/Post-Images if needed to access record data before/after the operation.

Key Takeaways

  • Plugins extend Dynamics 365 by running custom code during events like Create or Update.
  • The pipeline includes Pre-Validation (10), Pre-Operation (20), and Post-Operation (40, synchronous or asynchronous) stages.
  • The execution context provides data like input/output parameters and images (if registered).
  • Synchronous plugins (inside transaction) can roll back operations; asynchronous plugins (outside transaction) cannot.
  • Use the Plugin Registration Tool or Dynamics 365 SDK for setup.

Best Practices

  • Keep plugins lightweight to avoid performance issues.
  • Handle exceptions with clear error messages for users.
  • Test plugins in a sandbox environment before deploying to production.
  • For simpler logic, consider Power Automate or JavaScript web resources. use plugins for complex, server-side tasks requiring transactional consistency.

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *