Skip to content

DataVerse 9.2 Event Structure

Overview

This document provides a comprehensive explanation of the JSON event structure emitted by Microsoft DataVerse 9.2 (formerly Dynamics 365 CRM). Understanding this structure is crucial for translating generic CRUD events into meaningful business events within the 7N20 platform.

Event Message Structure

DataVerse emits events through Azure Event Hub with a complex JSON structure. Here's a real-world example of a Create event for a custom entity (rqm_requestshortlist):

{
  "BusinessUnitId": "55adc078-92be-e911-a837-000d3a2aabe6",
  "CorrelationId": "fc65709c-7b89-460a-bafc-7193dd5f7c5b",
  "Depth": 1,
  "InitiatingUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
  "InitiatingUserAzureActiveDirectoryObjectId": "00662bfc-cb05-4266-8741-1de13f9db3f9",
  "InitiatingUserId": "f88d0d38-940d-ed11-82e4-000d3a2fc6ad",
  "InputParameters": [
    {
      "key": "Target",
      "value": {
        "__type": "Entity:http://schemas.microsoft.com/xrm/2011/Contracts",
        "Attributes": [
          {
            "key": "rqm_candidateid",
            "value": {
              "__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
              "Id": "12ae6e67-6f3b-45ad-819e-dde77feb6d5a",
              "LogicalName": "contact",
              "Name": null
            }
          },
          {
            "key": "rqm_saleperhour",
            "value": {
              "__type": "Money:http://schemas.microsoft.com/xrm/2011/Contracts",
              "Value": 8
            }
          },
          {
            "key": "statecode",
            "value": {
              "__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
              "Value": 0
            }
          }
        ],
        "FormattedValues": [
          {
            "key": "rqm_saleperhour",
            "value": "zł8,00"
          },
          {
            "key": "statecode",
            "value": "Active"
          }
        ],
        "Id": "ab89c994-065d-f011-bec2-000d3ac241ab",
        "LogicalName": "rqm_requestshortlist"
      }
    }
  ],
  "IsExecutingOffline": false,
  "IsInTransaction": false,
  "IsOfflinePlayback": false,
  "IsolationMode": 1,
  "MessageName": "Create",
  "Mode": 1,
  "OperationCreatedOn": "/Date(1752094336000+0000)/",
  "OperationId": "b389c994-065d-f011-bec2-000d3ac241ab",
  "OrganizationId": "2b1dd4ce-5af3-ef11-b013-6045bd9a7c61",
  "OrganizationName": "unq2b1dd4ce5af3ef11b0136045bd9a7",
  "OutputParameters": [
    {
      "key": "id",
      "value": "ab89c994-065d-f011-bec2-000d3ac241ab"
    }
  ],
  "OwningExtension": {
    "Id": "36d8066a-bc53-ee11-be6d-000d3a4571fd",
    "LogicalName": "sdkmessageprocessingstep"
  },
  "ParentContext": {
    "BusinessUnitId": "55adc078-92be-e911-a837-000d3a2aabe6",
    "CorrelationId": "fc65709c-7b89-460a-bafc-7193dd5f7c5b",
    "Depth": 1,
    "InitiatingUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
    "InitiatingUserAzureActiveDirectoryObjectId": "00662bfc-cb05-4266-8741-1de13f9db3f9",
    "InitiatingUserId": "f88d0d38-940d-ed11-82e4-000d3a2fc6ad",
    "InputParameters": [...],
    "MessageName": "Create",
    "Mode": 1,
    "OperationCreatedOn": "/Date(1752094336000+0000)/",
    "OperationId": "b389c994-065d-f011-bec2-000d3ac241ab",
    "OrganizationId": "2b1dd4ce-5af3-ef11-b013-6045bd9a7c61",
    "OrganizationName": "unq2b1dd4ce5af3ef11b0136045bd9a7"
  },
  "PostEntityImages": [
    {
      "key": "PostImage",
      "value": {
        "Attributes": [
          {
            "key": "rqm_candidateid",
            "value": {
              "__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
              "Id": "12ae6e67-6f3b-45ad-819e-dde77feb6d5a",
              "LogicalName": "contact",
              "Name": "Andrzej Numerek"
            }
          },
          {
            "key": "rqm_title",
            "value": "Andrzej Numerek is considered for request SR Type for client Nordea Poland"
          }
        ],
        "FormattedValues": [
          {
            "key": "createdon",
            "value": "2025-07-09T22:52:14+02:00"
          }
        ],
        "Id": "ab89c994-065d-f011-bec2-000d3ac241ab",
        "LogicalName": "rqm_requestshortlist"
      }
    }
  ],
  "PreEntityImages": [],
  "PrimaryEntityId": "ab89c994-065d-f011-bec2-000d3ac241ab",
  "PrimaryEntityName": "rqm_requestshortlist",
  "RequestId": "b41ea0f1-81da-4218-9558-c1bcd3cce484",
  "SecondaryEntityName": "none",
  "SharedVariables": [
    {
      "key": "IsAutoTransact",
      "value": true
    },
    {
      "key": "AcceptLang",
      "value": "pl-PL,pl;q=0.9,en;q=0.8,en-US;q=0.7"
    }
  ],
  "Stage": 40,
  "UserAzureActiveDirectoryObjectId": "00662bfc-cb05-4266-8741-1de13f9db3f9",
  "UserId": "f88d0d38-940d-ed11-82e4-000d3a2fc6ad"
}

Key Event Properties

Core Properties

Property Type Description Example
MessageName string The CRUD operation type "Create", "Update", "Delete", "Retrieve"
PrimaryEntityName string The logical name of the entity "contact", "rqm_requestshortlist", "account"
PrimaryEntityId GUID Unique identifier of the entity "ab89c994-065d-f011-bec2-000d3ac241ab"
SecondaryEntityName string Related entity name (for association events) "none" for single entity operations
BusinessUnitId GUID Business unit where operation occurred "55adc078-92be-e911-a837-000d3a2aabe6"
OperationCreatedOn string Timestamp of the operation "/Date(1752094336000+0000)/" (epoch format)
OperationId GUID Unique identifier for this operation "b389c994-065d-f011-bec2-000d3ac241ab"
OrganizationId GUID The DataVerse organization ID "2b1dd4ce-5af3-ef11-b013-6045bd9a7c61"
OrganizationName string The organization name "unq2b1dd4ce5af3ef11b0136045bd9a7"
CorrelationId GUID Unique ID for tracking related operations "fc65709c-7b89-460a-bafc-7193dd5f7c5b"
RequestId GUID Unique ID for the HTTP request "b41ea0f1-81da-4218-9558-c1bcd3cce484"
UserId GUID The user who initiated the operation "f88d0d38-940d-ed11-82e4-000d3a2fc6ad"
UserAzureActiveDirectoryObjectId GUID Azure AD object ID of the user "00662bfc-cb05-4266-8741-1de13f9db3f9"
InitiatingUserId GUID Same as UserId "f88d0d38-940d-ed11-82e4-000d3a2fc6ad"
InitiatingUserAzureActiveDirectoryObjectId GUID Same as UserAzureActiveDirectoryObjectId "00662bfc-cb05-4266-8741-1de13f9db3f9"
InitiatingUserAgent string Browser user agent string "Mozilla/5.0 (Windows NT 10.0...)"
Depth number Plugin execution depth 1
Mode number Execution mode 0=Synchronous, 1=Asynchronous
Stage number Pipeline stage 10=PreValidation, 20=PreOperation, 40=PostOperation
IsExecutingOffline boolean Whether executing offline false
IsInTransaction boolean Whether in a database transaction false
IsOfflinePlayback boolean Whether offline playback false
IsolationMode number Plugin isolation mode 1=None, 2=Sandbox

Execution Context (ParentContext)

The ParentContext object provides crucial information about the execution environment. It contains the same properties as the root level but represents the parent execution context:

{
  "BusinessUnitId": "55adc078-92be-e911-a837-000d3a2aabe6",
  "CorrelationId": "fc65709c-7b89-460a-bafc-7193dd5f7c5b",
  "Depth": 1,
  "InitiatingUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
  "InitiatingUserAzureActiveDirectoryObjectId": "00662bfc-cb05-4266-8741-1de13f9db3f9",
  "InitiatingUserId": "f88d0d38-940d-ed11-82e4-000d3a2fc6ad",
  "MessageName": "Create",
  "Mode": 1,
  "OperationCreatedOn": "/Date(1752094336000+0000)/",
  "OperationId": "b389c994-065d-f011-bec2-000d3ac241ab",
  "OrganizationId": "2b1dd4ce-5af3-ef11-b013-6045bd9a7c61",
  "OrganizationName": "unq2b1dd4ce5af3ef11b0136045bd9a7"
}

The ParentContext is particularly important when dealing with nested plugin executions or when one operation triggers another.

Pre and Post Entity Images

The most critical components for detecting changes are the entity images:

  • PreEntityImages: Snapshot of the entity before the operation (empty array for Create operations)
  • PostEntityImages: Snapshot of the entity after the operation

In the real-world structure, entity images use a more complex format with typed attributes:

{
  "key": "PostImage",
  "value": {
    "Attributes": [
      {
        "key": "rqm_candidateid",
        "value": {
          "__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
          "Id": "12ae6e67-6f3b-45ad-819e-dde77feb6d5a",
          "LogicalName": "contact",
          "Name": "Andrzej Numerek"
        }
      },
      {
        "key": "rqm_saleperhour",
        "value": {
          "__type": "Money:http://schemas.microsoft.com/xrm/2011/Contracts",
          "Value": 8.0000
        }
      },
      {
        "key": "statecode",
        "value": {
          "__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
          "Value": 0
        }
      }
    ],
    "FormattedValues": [
      {
        "key": "rqm_saleperhour",
        "value": "zł8,00"
      },
      {
        "key": "statecode",
        "value": "Active"
      }
    ],
    "Id": "ab89c994-065d-f011-bec2-000d3ac241ab",
    "LogicalName": "rqm_requestshortlist"
  }
}

Input Parameters

The InputParameters array contains the operation's input data, with the "Target" parameter being the most important:

{
  "key": "Target",
  "value": {
    "__type": "Entity:http://schemas.microsoft.com/xrm/2011/Contracts",
    "Attributes": [...],
    "FormattedValues": [...],
    "Id": "ab89c994-065d-f011-bec2-000d3ac241ab",
    "LogicalName": "rqm_requestshortlist",
    "RowVersion": "1152134471"
  }
}

Translating to Business Events

Change Detection Pattern

To translate generic CRUD events into specific business events, compare pre and post images:

// Example: Detecting email change
public class ContactEmailChangedDetector
{
    public bool HasEmailChanged(JObject preImage, JObject postImage)
    {
        var preEmail = preImage?["emailaddress1"]?.ToString();
        var postEmail = postImage?["emailaddress1"]?.ToString();

        return !string.Equals(preEmail, postEmail, StringComparison.OrdinalIgnoreCase);
    }
}

Business Event Translation Example

Transform a generic Update event into a specific ContactEmailChanged business event:

// Input: Generic DataVerse Update Event
{
  "MessageName": "Update",
  "PrimaryEntityName": "contact",
  "PreEntityImages": [{
    "value": {
      "emailaddress1": "old@email.com"
    }
  }],
  "PostEntityImages": [{
    "value": {
      "emailaddress1": "new@email.com"
    }
  }]
}

// Output: Specific Business Event
{
  "EventType": "ContactEmailChanged",
  "ContactId": "12345678-1234-1234-1234-123456789012",
  "OldEmail": "old@email.com",
  "NewEmail": "new@email.com",
  "ChangedBy": "87654321-4321-4321-4321-210987654321",
  "ChangedAt": "2024-01-15T10:35:00.123Z",
  "CorrelationId": "22222222-2222-2222-2222-222222222222"
}

Common Entity Attributes

Contact Entity

{
  "contactid": "GUID",
  "firstname": "string",
  "lastname": "string",
  "emailaddress1": "string",
  "emailaddress2": "string",
  "telephone1": "string",
  "mobilephone": "string",
  "jobtitle": "string",
  "parentcustomerid": "GUID",
  "ownerid": "GUID",
  "statecode": 0,
  "statuscode": 1
}

Account Entity

{
  "accountid": "GUID",
  "name": "string",
  "emailaddress1": "string",
  "telephone1": "string",
  "websiteurl": "string",
  "primarycontactid": "GUID",
  "ownerid": "GUID",
  "statecode": 0,
  "statuscode": 1
}

Event Processing Considerations

1. Field Selection

Not all fields are included in pre/post images. Configure DataVerse plugins to include specific fields:

// Plugin registration step configuration
preImage.Attributes = new string[] { 
    "firstname", 
    "lastname", 
    "emailaddress1", 
    "telephone1" 
};

2. Null vs Missing Values

  • Null value: Field explicitly set to null
  • Missing field: Field not included in the image (no change or not configured)

3. Data Types

DataVerse uses specific typed formats with __type annotations:

EntityReference (Lookup)

{
  "__type": "EntityReference:http://schemas.microsoft.com/xrm/2011/Contracts",
  "Id": "12ae6e67-6f3b-45ad-819e-dde77feb6d5a",
  "LogicalName": "contact",
  "Name": "Andrzej Numerek",
  "KeyAttributes": [],
  "RowVersion": null
}

Money

{
  "__type": "Money:http://schemas.microsoft.com/xrm/2011/Contracts",
  "Value": 8.0000
}

OptionSetValue

{
  "__type": "OptionSetValue:http://schemas.microsoft.com/xrm/2011/Contracts",
  "Value": 112020000
}

DateTime

DataVerse uses epoch format with timezone offset:

"/Date(1752094334000+0000)/"

4. Additional Properties

SharedVariables

Contains execution context information:

[
  {"key": "IsAutoTransact", "value": true},
  {"key": "AcceptLang", "value": "pl-PL,pl;q=0.9,en;q=0.8,en-US;q=0.7"},
  {"key": "x-ms-app-name", "value": "CRMHub"},
  {"key": "ChangedEntityTypes", "value": [
    {"key": "rqm_request", "value": "Update"},
    {"key": "fileattachment", "value": "Create"}
  ]}
]

OwningExtension

Identifies the plugin step that generated the event:

{
  "Id": "36d8066a-bc53-ee11-be6d-000d3a4571fd",
  "LogicalName": "sdkmessageprocessingstep",
  "KeyAttributes": [],
  "Name": null,
  "RowVersion": null
}

Service Endpoint Configuration for Change Detection

To effectively capture and process DataVerse events for change detection, you must configure service endpoints and plugin registration steps correctly. This configuration determines what events are sent to your external systems and what data is included.

1. Service Endpoint Configuration

Create a service endpoint in DataVerse that points to your Azure Event Hub:

Connection String Format

Endpoint=sb://your-eventhub-namespace.servicebus.windows.net/;SharedAccessKeyName=your-policy-name;SharedAccessKey=your-key;EntityPath=your-eventhub-name

Service Endpoint Properties

Property Value Description
Name DataVerseEventEndpoint Descriptive name for the endpoint
Namespace Address sb://your-namespace.servicebus.windows.net/ Service Bus namespace URL
Contract Queue Use Queue contract for Event Hub
Path your-eventhub-name Event Hub name
Message Format JSON Use JSON format for structured data
User Information Sent UserId Include user context in events
Description Sends DataVerse events to Event Hub Optional description

2. Plugin Registration Configuration

For effective change detection, register plugin steps on the PostOperation stage with appropriate entity images.

Required Plugin Step Configuration

<!-- Example Plugin Registration Tool XML -->
<Solution>
  <PluginTypes>
    <PluginType Name="Microsoft.Crm.Extensibility.InternalOperationPlugin" 
               FriendlyName="InternalOperationPlugin" 
               TypeName="Microsoft.Crm.Extensibility.InternalOperationPlugin" 
               WorkflowActivityGroupName="" 
               AssemblyName="Microsoft.Crm.Extensibility">
      <Steps>
        <!-- Contact Entity Events -->
        <Step Name="ContactCreate" 
              MessageName="Create" 
              PrimaryEntityName="contact" 
              Stage="PostOperation" 
              Mode="Asynchronous" 
              Rank="1" 
              AsyncAutoDelete="false"
              CustomConfiguration="MyServiceEndpointId">
          <Images>
            <Image Name="PostImage" 
                   Type="PostImage" 
                   Attributes="contactid,firstname,lastname,emailaddress1,telephone1,mobilephone,jobtitle,parentcustomerid,statecode,statuscode,modifiedon,modifiedby" />
          </Images>
        </Step>

        <Step Name="ContactUpdate" 
              MessageName="Update" 
              PrimaryEntityName="contact" 
              Stage="PostOperation" 
              Mode="Asynchronous" 
              Rank="1" 
              AsyncAutoDelete="false"
              CustomConfiguration="MyServiceEndpointId">
          <Images>
            <Image Name="PreImage" 
                   Type="PreImage" 
                   Attributes="contactid,firstname,lastname,emailaddress1,telephone1,mobilephone,jobtitle,parentcustomerid,statecode,statuscode" />
            <Image Name="PostImage" 
                   Type="PostImage" 
                   Attributes="contactid,firstname,lastname,emailaddress1,telephone1,mobilephone,jobtitle,parentcustomerid,statecode,statuscode,modifiedon,modifiedby" />
          </Images>
        </Step>

        <Step Name="ContactDelete" 
              MessageName="Delete" 
              PrimaryEntityName="contact" 
              Stage="PreOperation" 
              Mode="Asynchronous" 
              Rank="1" 
              AsyncAutoDelete="false"
              CustomConfiguration="MyServiceEndpointId">
          <Images>
            <Image Name="PreImage" 
                   Type="PreImage" 
                   Attributes="contactid,firstname,lastname,emailaddress1,telephone1,mobilephone,jobtitle,parentcustomerid,statecode,statuscode" />
          </Images>
        </Step>
      </Steps>
    </PluginType>
  </PluginTypes>
</Solution>

3. Critical Configuration Parameters

Stage Selection

Stage When to Use Change Detection Capability
PreValidation (10) Before validation Limited - entity may change
PreOperation (20) Before database operation Good for deletes
PostOperation (40) After database operation Best for change detection

Mode Selection

Mode Description Recommended For
Synchronous (0) Blocks the operation Critical validations only
Asynchronous (1) Non-blocking Event publishing

Entity Image Configuration

For Create Operations:

{
  "PostImage": {
    "Attributes": ["field1", "field2", "field3"],
    "AllAttributes": false
  }
}

For Update Operations (Required for Change Detection):

{
  "PreImage": {
    "Attributes": ["field1", "field2", "field3"],
    "AllAttributes": false
  },
  "PostImage": {
    "Attributes": ["field1", "field2", "field3", "modifiedon", "modifiedby"],
    "AllAttributes": false
  }
}

For Delete Operations:

{
  "PreImage": {
    "Attributes": ["field1", "field2", "field3"],
    "AllAttributes": false
  }
}

4. Best Practices for Change Detection

Field Selection Strategy

Only include fields you need to monitor for changes to reduce payload size and processing overhead:

// Example: Contact entity fields for business events
var contactFields = new[]
{
    "contactid",           // Required: Primary key
    "firstname",           // Business field
    "lastname",            // Business field
    "emailaddress1",       // Critical for email change events
    "telephone1",          // Critical for phone change events
    "mobilephone",         // Critical for mobile change events
    "jobtitle",           // Business field
    "parentcustomerid",   // Relationship field
    "statecode",          // Status tracking
    "statuscode",         // Status reason tracking
    "modifiedon",         // Audit field (PostImage only)
    "modifiedby"          // Audit field (PostImage only)
};

Entity-Specific Configurations

For Custom Entities (like rqm_requestshortlist):

{
  "PreImage": {
    "Attributes": [
      "rqm_requestshortlistid",
      "rqm_candidateid", 
      "rqm_requestid",
      "rqm_salesstatus",
      "rqm_saleperhour",
      "rqm_costperhour",
      "statecode",
      "statuscode"
    ]
  },
  "PostImage": {
    "Attributes": [
      "rqm_requestshortlistid",
      "rqm_candidateid", 
      "rqm_requestid",
      "rqm_salesstatus",
      "rqm_saleperhour",
      "rqm_costperhour",
      "rqm_title",
      "statecode",
      "statuscode",
      "modifiedon",
      "modifiedby"
    ]
  }
}

5. Filtering Configuration

Use filtering conditions to reduce unnecessary event volume:

Message Filtering

<FilteringAttributes>emailaddress1,telephone1,statecode</FilteringAttributes>
This ensures events are only sent when these specific fields change.

Custom Configuration

Pass configuration data to identify the service endpoint:

<CustomConfiguration>MyServiceEndpointId</CustomConfiguration>

6. Monitoring and Troubleshooting

Plugin Trace Log

Enable plugin trace logs to debug event flow: - Navigate to Settings > System > System Jobs - Filter by Plugin Type = Microsoft.Crm.Extensibility.InternalOperationPlugin - Check execution details and any errors

Service Endpoint Monitoring

Monitor Event Hub metrics: - Incoming Messages: Verify events are being sent - Outgoing Messages: Verify events are being consumed - Throttled Requests: Check for rate limiting - Server Errors: Identify connectivity issues

7. PowerShell Configuration Script

# Example PowerShell script for service endpoint registration
$connectionString = "Endpoint=sb://your-namespace.servicebus.windows.net/;SharedAccessKeyName=your-policy;SharedAccessKey=your-key;EntityPath=your-hub"

# Create service endpoint
$serviceEndpoint = New-CrmRecord -EntityLogicalName "serviceendpoint" -Fields @{
    "name" = "DataVerseEventEndpoint"
    "namespaceaddress" = "sb://your-namespace.servicebus.windows.net/"
    "contract" = "Queue"
    "path" = "your-hub-name"
    "messageformat" = "JSON"
    "userintentionsent" = "UserId"
    "connectionstring" = $connectionString
}

Write-Host "Service Endpoint Created: $($serviceEndpoint.Id)"

Microsoft Documentation References

For detailed information about DataVerse event structure and processing:

  1. DataVerse Event Framework - Core concepts and architecture
  2. Plugin Development - Creating and registering plugins
  3. Event Execution Pipeline - Understanding event flow
  4. Entity Images - Working with pre/post images
  5. Azure Service Bus Integration - Sending events to Azure
  6. Service Endpoints - Service endpoint registration
  7. Plugin Registration Tool - Tool for registering plugins and service endpoints

Implementation in 7N20

The 7N20 platform processes DataVerse events through a containerized .NET application that:

  1. Consumes events from Azure Event Hub
  2. Deserializes the JSON structure
  3. Compares pre/post images to detect changes
  4. Generates specific business events
  5. Publishes to business event topics

For implementation details, see: - DataVerse Event Transformation Guide - CRM Domain Business Events

Summary

Understanding the DataVerse 9.2 event structure enables: - Accurate change detection through pre/post image comparison - Translation of generic CRUD operations into domain-specific business events - Proper handling of DataVerse-specific data types and formats - Integration with the 7N20 event-driven architecture

The key to effective event translation is leveraging the pre and post entity images to identify specific field changes and emit targeted business events that downstream services can act upon.