Domain 5 β€” Module 1 of 9 11%
15 of 26 overall
Domain 5: Extend the Platform Free ⏱ ~14 min read

The Plug-in Pipeline: How Dataverse Processes Events

Understand the engine behind every Dataverse operation. Learn the event execution pipeline stages, the execution context, and how Pre/Post Images give your plug-in a before-and-after view of data.

The pipeline that powers Dataverse

Simple explanation

Think of the Dataverse pipeline like an airport security checkpoint.

When you fly, you go through multiple stages: ticket check (are you even allowed here?), security screening (pre-check before you enter the secure area), and boarding (the main action). After boarding, there is a post-departure check (update the passenger manifest).

Every Dataverse operation (create a record, update a field, delete a row) passes through a similar pipeline with four stages. Your plug-in code can intercept the operation at any stage β€” to validate data before it is saved, modify it during processing, or trigger actions after the save completes.

Understanding these stages is the single most important concept for PL-400 Domain 5.

The four pipeline stages

StageWhen It RunsTransaction?Can Cancel Operation?Best For
Pre-validation (Stage 10)Before security checksNo β€” outside transactionYesLight validation, early rejection
Pre-operation (Stage 20)After security, before DB writeYes β€” inside transactionYesModify data before save, complex validation
Main operation (Stage 30)The actual database operationYes β€” the core transactionN/A (system only)Cannot register plug-ins here
Post-operation (Stage 40)After the DB writeYes β€” still inside transactionYes (rolls back entire transaction)Create related records, trigger integrations

Synchronous vs asynchronous execution

ModeRuns WhenUser ExperienceUse For
SynchronousImmediately, blocks the operationUser waitsValidation, data modification, must-run logic
AsynchronousAfter the transaction commits, in backgroundUser continues workingNotifications, logging, non-critical processing
Exam tip: The stage selection pattern

The exam will describe a scenario and ask which stage is correct. Use this decision tree:

  1. Need to reject invalid data before security checks run? β†’ Pre-validation
  2. Need to modify or enrich data before it is saved? β†’ Pre-operation
  3. Need to create related records or trigger integrations after save? β†’ Post-operation (sync)
  4. Need to send notifications or log events without blocking the user? β†’ Post-operation (async)

Red flag: If an answer says β€œregister on the Main operation stage” β€” it is always wrong. You cannot register plug-ins on Stage 30.

The execution context

Every plug-in receives an IPluginExecutionContext that tells you everything about the current operation:

public class ShipmentValidator : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        // Get the execution context
        IPluginExecutionContext context = (IPluginExecutionContext)
            serviceProvider.GetService(typeof(IPluginExecutionContext));
        
        // What operation triggered this plug-in?
        string messageName = context.MessageName;  // "Create", "Update", "Delete"
        
        // What entity is being affected?
        string entityName = context.PrimaryEntityName;  // "shipment"
        
        // What stage are we in?
        int stage = context.Stage;  // 10, 20, 30, or 40
        
        // Who triggered the operation?
        Guid userId = context.UserId;           // The calling user
        Guid initiatingUserId = context.InitiatingUserId;  // Original user (even through impersonation)
        
        // What data is being sent? (for Create/Update)
        Entity target = (Entity)context.InputParameters["Target"];
        string destination = target.GetAttributeValue<string>("destination");
        
        // What depth are we at? (prevents infinite loops)
        int depth = context.Depth;  // 1 = original, 2+ = triggered by another plug-in
    }
}

Key context properties

PropertyWhat It Tells You
MessageNameThe operation: Create, Update, Delete, Retrieve, etc.
PrimaryEntityNameThe table being affected
StageWhich pipeline stage (10, 20, 30, 40)
UserIdThe user executing the operation (may be impersonated)
InitiatingUserIdThe original user who started the chain
InputParameters[β€œTarget”]The record being created/updated (Entity object)
DepthRecursion depth (check to prevent infinite loops)
PreEntityImagesSnapshot of the record BEFORE the operation
PostEntityImagesSnapshot of the record AFTER the operation

Pre Images and Post Images

Images are snapshots of a record at specific points in the pipeline.

Images give your plug-in a before-and-after view β€” register only the fields you need
FeaturePre ImagePost Image
ShowsRecord values BEFORE the operationRecord values AFTER the operation
Available inPre-validation, Pre-operation, Post-operationPost-operation only
Useful forComparing old vs new values, checking what changedVerifying final state, accessing calculated fields
ContainsFields you registered for in the image definitionFields you registered for in the image definition
On CreateNot available (no previous state)Available in post-operation
On DeleteAvailable (record exists before delete)Not available (record is gone)

Using images to detect changes

// In a Post-operation Update plug-in
Entity preImage = context.PreEntityImages["preImage"];
Entity postImage = context.PostEntityImages["postImage"];

// statuscode is an OptionSetValue, not a string
int oldStatus = preImage.GetAttributeValue<OptionSetValue>("statuscode")?.Value ?? -1;
int newStatus = postImage.GetAttributeValue<OptionSetValue>("statuscode")?.Value ?? -1;

if (oldStatus != newStatus)
{
    // Status changed β€” trigger notification
    tracingService.Trace($"Status changed from {oldStatus} to {newStatus}");
}
Scenario: Kai uses images to track shipment changes

Kai registers a Post-operation Update plug-in on the Shipment table at LogiFlow. He configures:

  • Pre Image: includes status, destination, priority fields
  • Post Image: includes status, destination, priority fields

When a shipment’s status changes from β€œIn Transit” to β€œDelivered”, the plug-in compares the pre and post images, sees the status change, and creates a Delivery Confirmation record with the delivery timestamp.

Why images instead of Target? The Target entity in an Update only contains the fields that were actually changed. If Kai needs to check the destination (which was not changed in this update), it would not be in Target β€” but it IS in the Pre Image.

Question

What are the four stages of the Dataverse event execution pipeline?

Click or press Enter to reveal answer

Question

What is the difference between context.UserId and context.InitiatingUserId?

Click or press Enter to reveal answer

Question

Why is context.Depth important in plug-in development?

Click or press Enter to reveal answer

Question

Why would you use a Pre Image instead of reading the Target entity?

Click or press Enter to reveal answer

Knowledge Check

A developer needs to validate that a Shipment record's weight does not exceed 1000kg BEFORE security checks run. If the weight exceeds the limit, the operation should be cancelled immediately. Which pipeline stage should the plug-in be registered on?

Knowledge Check

A plug-in registered on Post-operation Update needs to check whether the Priority field changed. The developer reads context.InputParameters['Target'] but Priority is not in the Target entity. Why?

Next up: Writing Plug-ins β€” implementing business logic with the Organisation Service, performance optimisation, and plug-in registration.