{"id":11002,"date":"2025-05-20T12:43:53","date_gmt":"2025-05-20T12:43:53","guid":{"rendered":"https:\/\/www.aegissofttech.com\/insights\/?p=11002"},"modified":"2026-05-06T14:04:23","modified_gmt":"2026-05-06T14:04:23","slug":"prevalidation-plugins-dynamics-365","status":"publish","type":"post","link":"https:\/\/www.aegissofttech.com\/insights\/prevalidation-plugins-dynamics-365\/","title":{"rendered":"Prevalidation Plugins in Dynamics 365 Explained"},"content":{"rendered":"\n<p>It was Monday morning, and Maya, a Dynamics 365 developer, was reviewing a new data import for a key client. Everything seemed fine until she noticed several records had slipped through with missing fields. Workflows triggered, emails went out, and suddenly the CRM was full of errors that would take hours to fix.<\/p>\n\n\n\n<p>Prevalidation plugins in Dynamics 365 catch these problems before they ever reach the database. They run at the earliest point in the plugin execution pipeline, giving <a href=\"https:\/\/www.aegissofttech.com\/hire-ms-crm-developers.html\">Dynamics CRM developers<\/a> the ability to enforce rules, block duplicates, and validate incoming data immediately.<\/p>\n\n\n\n<p>In this guide, we\u2019ll break down the prevalidation stage in Dynamics CRM, explain how it differs from other stages, and show how to use it. All of these will help make your Dynamics 365 plugin development smoother, faster, and far more reliable.&nbsp;<\/p>\n\n\n\n<p>Here we go!<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Key Takeaways<\/strong><\/p>\n\n\n\n<div style=\"border:1px solid #000; padding:15px; margin:20px 0;\">\nHere\u2019s what you need to know about prevalidation plugins in Dynamics 365:\n<ul style=\"margin-top:10px; line-height:1.6;\">\n<li><b>Prevalidation plugins in Dynamics 365<\/b> run before security checks and database operations, allowing early interception of invalid data.<\/li>\n<li>They are ideal for <b>blocking duplicates, enforcing business rules, validating imports<\/b>, and preventing unauthorized updates or deletions.<\/li>\n<li>Since they <b>operate outside the transaction scope<\/b>, failed validations stop operations without affecting system performance or starting database transactions.<\/li>\n<li><b>Prevalidation logic should remain light<\/b>, focusing on simple checks, while complex logic belongs in pre-operation or post-operation stages.<\/li>\n<li>These plugins are particularly <b>useful for bulk imports, integrations<\/b>, and scenarios requiring cross-entity or global data validation.<\/li>\n<\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">The Plugin Execution Pipeline in Dynamics 365<\/h2>\n\n\n\n<p>Every time a user creates, updates, or deletes a record in Microsoft Dynamics 365, that operation passes through a defined plugin execution pipeline. This pipeline determines when and how custom business logic executes. Knowing exactly where your plugin fits in this flow is essential for building a reliable and <a href=\"https:\/\/www.aegissofttech.com\/dynamics-365\">scalable Dynamics 365 solution<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"932\" height=\"671\" src=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/05\/Plugin-execution-pipeline-in-Dynamics-365.webp\" alt=\"Plugin execution pipeline in Dynamics 365\" class=\"wp-image-19342\" title=\"Plugin execution pipeline in Dynamics 365\" srcset=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/05\/Plugin-execution-pipeline-in-Dynamics-365.webp 932w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/05\/Plugin-execution-pipeline-in-Dynamics-365-300x216.webp 300w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/05\/Plugin-execution-pipeline-in-Dynamics-365-768x553.webp 768w\" sizes=\"(max-width: 932px) 100vw, 932px\" \/><\/figure>\n\n\n\n<p>Each stage has a specific purpose and impact on how data moves through the system. Let\u2019s break them down one by one.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Pre-Validation (Stage 10)<\/h3>\n\n\n\n<p>The prevalidation stage in Dynamics CRM executes before the platform\u2019s core operations and before any security or database validation occurs. Since it runs outside the transaction, this stage gives developers the earliest chance to act on incoming data.<\/p>\n\n\n\n<p>You can inspect input parameters, run quick data checks, or stop invalid requests before they even reach the system. For example, if an import contains duplicate records or missing mandatory fields, a prevalidation plugin in Dynamics 365 can reject the operation instantly, which saves hours of cleanup later.<\/p>\n\n\n\n<p>When to use it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Blocking duplicate records or invalid data<\/li>\n\n\n\n<li>Enforcing business rules before database interaction<\/li>\n\n\n\n<li>Validating imports or integrations that push large volumes of data<\/li>\n<\/ul>\n\n\n    \t<section class=\"call-to-action-section\">\n    \t\t<div class=\"call-to-action-container\">\n    \t\t\t<div class=\"call-to-action-body\">\n    \t\t\t\t<div class=\"cta-title\"><\/div>\n    \t\t\t\t<p><\/p>\n<div style='text-align:left; color:white;'>\n<b>Pro Tip:<\/b> Since security checks haven\u2019t occurred yet, make sure your plugin doesn\u2019t rely on restricted data access.<\/div>\n<p><\/p>\n    \t\t\t<\/div>\n    \t\t\t    \t\t<\/div>\n    \t<\/section>\n    \n\n\n\n<h3 class=\"wp-block-heading\">Pre-Operation (Stage 20)<\/h3>\n\n\n\n<p>The pre-operation stage runs after security checks but before the database transaction commits. It\u2019s part of the same transaction, meaning any exceptions you throw here will roll back the entire operation.<\/p>\n\n\n\n<p>This stage is perfect for adjusting field values, applying conditional logic, or ensuring related data is ready before saving. For instance, you could automatically populate fields, calculate totals, or update related entities before the record is persisted.<\/p>\n\n\n\n<p>When to use it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Modifying data before it\u2019s saved<\/li>\n\n\n\n<li>Implementing calculated or dependent field updates<\/li>\n\n\n\n<li>Performing logic that must execute within the same transaction<\/li>\n<\/ul>\n\n\n\n<p>Be careful with performance-heavy operations here; anything that slows execution delays the transaction itself.<\/p>\n\n\n\n<section class=\"call-to-action-section\">\n<div class=\"call-to-action-container\">\n<div class=\"call-to-action-body\">\n<div class=\"cta-title\"><\/div>\n<p><\/p>\n<div style=\"text-align:center; color:white;\">\n<strong>Also Read:<\/strong> <a href=\"https:\/\/www.aegissofttech.com\/insights\/dynamics-365-crm-using-ai\/\" target=\"_blank\">Automate &#038; Optimize Dynamics 365 CRM Using AI<\/a><\/div>\n<p><\/p>\n<\/div>\n<\/div>\n<\/section>\n\n\n\n<h3 class=\"wp-block-heading\">Main Operation (Stage 30)<\/h3>\n\n\n\n<p>The main operation is where Dynamics 365 performs its internal logic: creating, updating, or deleting the actual record. Developers can\u2019t register plugins in this stage, but understanding it helps determine when your pre- and post-operation logic executes relative to the system\u2019s native actions.<\/p>\n\n\n\n<p>Essentially, this is the moment when the data change happens. Your pre-operation logic prepares for it, and your post-operation logic reacts to it.<\/p>\n\n\n    \t<section class=\"call-to-action-section\">\n    \t\t<div class=\"call-to-action-container\">\n    \t\t\t<div class=\"call-to-action-body\">\n    \t\t\t\t<div class=\"cta-title\"><\/div>\n    \t\t\t\t<p><\/p>\n<div style='text-align:left; color:white;'>\nEvery business has its quirks, and <a href='https:\/\/www.aegissofttech.com' target='_blank'>Aegis Softtech<\/a> gets that. We design Dynamics 365 solutions that fit your unique processes, so your workflows stay seamless, and mistakes are minimized.<br \/>\nLearn how we can improve system performance and save time for your team.<\/div>\n<p><\/p>\n    \t\t\t<\/div>\n    \t\t\t    \t\t\t\t<div class=\"call-to-action-btn\">\n    \t\t\t\t\t<a href=\"https:\/\/www.aegissofttech.com\/contact-us.html\">Book a FREE Consultation<\/a>\n    \t\t\t\t<\/div>\n    \t\t\t    \t\t<\/div>\n    \t<\/section>\n    \n\n\n\n<h3 class=\"wp-block-heading\">Post-Operation (Stage 40)<\/h3>\n\n\n\n<p>The post-operation stage fires after the record has been committed to the database. Depending on whether the plugin is synchronous or asynchronous, this can happen either within the same transaction or later as a background process.<\/p>\n\n\n\n<p>This is the best place for actions that depend on finalized data, such as notifications, logging, or updating related records. Now, because the data exists in the database, your plugin can safely access the record\u2019s GUID and other system-generated fields.<\/p>\n\n\n\n<p>When to use it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Sending emails or triggering workflows<\/li>\n\n\n\n<li>Updating related entities<\/li>\n\n\n\n<li>Logging completed actions or audit data<\/li>\n<\/ul>\n\n\n    \t<section class=\"call-to-action-section\">\n    \t\t<div class=\"call-to-action-container\">\n    \t\t\t<div class=\"call-to-action-body\">\n    \t\t\t\t<div class=\"cta-title\"><\/div>\n    \t\t\t\t<p><\/p>\n<div style='text-align:left; color:white;'>\n<b>Pro Tip:<\/b> Be cautious with synchronous post-operation plugins that modify the same entity, as they can trigger recursive updates if not carefully configured.<\/div>\n<p><\/p>\n    \t\t\t<\/div>\n    \t\t\t    \t\t<\/div>\n    \t<\/section>\n    \n\n\n\n<h2 class=\"wp-block-heading\">What are Prevalidation Plugins in Dynamics 365?<\/h2>\n\n\n\n<p>Prevalidation plugins in Dynamics 365 are executed before the main transaction pipeline begins. They run even before the platform performs security checks or starts database-level operations, giving developers an early interception point to validate or control incoming data.<\/p>\n\n\n\n<p>These plugins operate outside the transaction scope, so they allow developers to stop invalid operations before they affect system performance or data integrity.<\/p>\n\n\n\n<p>In practical terms, a prevalidation plugin serves as a gatekeeper.<\/p>\n\n\n\n<p>When a record is created, updated, or deleted, the plugin checks whether the data meets predefined business rules before allowing the process to continue. This is especially useful for scenarios that require early data verification, such as checking an email field format, validating mandatory attributes, or preventing duplicate records across multiple entities.<\/p>\n\n\n\n<p>For example, when users create a new contact with an incorrectly formatted email address, a prevalidation plugin can block the request immediately, long before any database write occurs. Similarly, in account creation workflows, developers can use this stage to verify if a record with the same tax ID already exists. This avoids duplicates that could later cause compliance or reporting issues.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">When to Use Prevalidation Plugins<\/h2>\n\n\n\n<p>Think of the prevalidation stage in Dynamics CRM as your first line of defense\u2014it stops bad data before the system even starts processing it. Let\u2019s look at when you should use it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Preventing Invalid Record Imports<\/h3>\n\n\n\n<p>Bulk imports can go wrong fast. When users upload hundreds or thousands of records, you want to catch issues before the system wastes resources on invalid data. Say you&#8217;re importing contacts, and each one needs to link to an active account. A prevalidation plugin in Dynamics 365<strong><em> <\/em><\/strong>checks this before anything gets written:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public void Execute(IServiceProvider serviceProvider)\n{\n    var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));\n    var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));\n    var service = serviceFactory.CreateOrganizationService(null);\n    \n    if (context.InputParameters.Contains(\"Target\") &amp;&amp; context.InputParameters&#091;\"Target\"] is Entity target)\n    {\n        if (target.LogicalName == \"contact\" &amp;&amp; target.Contains(\"parentcustomerid\"))\n        {\n            var accountRef = target.GetAttributeValue&lt;EntityReference&gt;(\"parentcustomerid\");\n            var account = service.Retrieve(\"account\", accountRef.Id, new ColumnSet(\"statecode\"));\n            \n            if (account.GetAttributeValue&lt;OptionSetValue&gt;(\"statecode\").Value != 0)\n            {\n                throw new InvalidPluginExecutionException(\"Cannot create contact linked to an inactive account.\");\n            }\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>The beauty here is efficiency. If 500 contacts reference dead accounts, they fail immediately. No transactions started, no resources wasted. The user gets clear feedback about what went wrong.<\/p>\n\n\n\n<p>Using system context (<strong>CreateOrganizationService(null)<\/strong>) enables the plugin to check accounts regardless of who&#8217;s doing the import. The rule applies to everyone, so the plugin enforces it universally.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Restricting Unauthorized Updates or Deletions<\/h3>\n\n\n\n<p>Sometimes your business rules go beyond what security roles can handle. You might need to block actions based on record status, not user permissions. Here&#8217;s a common one: preventing users from deleting active opportunities. Security roles control who can delete opportunities, but they can&#8217;t check whether those opportunities are still open. Prevalidation plugins in Dynamics 365 fill that gap:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (context.MessageName == \"Delete\" &amp;&amp; context.PrimaryEntityName == \"opportunity\")\n{\n    var opportunityId = (Guid)context.InputParameters&#091;\"Target\"];\n    var opportunity = service.Retrieve(\"opportunity\", opportunityId, new ColumnSet(\"statecode\"));\n    \n    if (opportunity.GetAttributeValue&lt;OptionSetValue&gt;(\"statecode\").Value == 0)\n    {\n        throw new InvalidPluginExecutionException(\"Active opportunities cannot be deleted. Close the opportunity first.\");\n    }\n}<\/code><\/pre>\n\n\n\n<p>This runs before security checks and before any database transaction. The operation stops immediately with a clear message.<\/p>\n\n\n\n<p>The same pattern works for update restrictions. If approved, invoices should become read-only; a prevalidation plugin enforces that:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (context.MessageName == \"Update\" &amp;&amp; context.PrimaryEntityName == \"invoice\")\n{\n    var invoiceId = ((EntityReference)context.InputParameters&#091;\"Target\"]).Id;\n    var invoice = service.Retrieve(\"invoice\", invoiceId, new ColumnSet(\"statuscode\"));\n    \n    if (invoice.GetAttributeValue&lt;OptionSetValue&gt;(\"statuscode\").Value == 100001)\n    {\n        throw new InvalidPluginExecutionException(\"Approved invoices cannot be modified.\");\n    }\n}<\/code><\/pre>\n\n\n\n<p>These rules protect your data across the board\u2014API calls, manual updates, workflows, everything.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Validating Cross-Entity Business Rules<\/h3>\n\n\n\n<p>Data validation in Dynamics 365 CRM often means checking relationships between records. You need to make sure parent-child relationships make sense before committing changes.<\/p>\n\n\n\n<p>Here\u2019s a manufacturing scenario: work orders must link to locations with available capacity. The prevalidation plugin checks this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (target.LogicalName == \"msdyn_workorder\" &amp;&amp; target.Contains(\"msdyn_servicelocation\"))\n{\n    var locationRef = target.GetAttributeValue&lt;EntityReference&gt;(\"msdyn_servicelocation\");\n    \n    var location = service.Retrieve(\"msdyn_servicelocation\", locationRef.Id, \n        new ColumnSet(\"msdyn_maxcapacity\", \"msdyn_currentload\"));\n    \n    var maxCapacity = location.GetAttributeValue&lt;int&gt;(\"msdyn_maxcapacity\");\n    var currentLoad = location.GetAttributeValue&lt;int&gt;(\"msdyn_currentload\");\n    \n    if (currentLoad &gt;= maxCapacity)\n    {\n        throw new InvalidPluginExecutionException(\"Selected location has reached maximum capacity.\");\n    }\n}<\/code><\/pre>\n\n\n\n<p>This validation happens before any transaction starts. During bulk work order creation, invalid assignments fail fast without consuming database resources.<\/p>\n\n\n    \t<section class=\"call-to-action-section\">\n    \t\t<div class=\"call-to-action-container\">\n    \t\t\t<div class=\"call-to-action-body\">\n    \t\t\t\t<div class=\"cta-title\"><\/div>\n    \t\t\t\t<p><\/p>\n<div style='text-align:left; color:white;'>\n<b>Watch For This:<\/b> Prevalidation sees the current state of related records, not pending changes in the same transaction. If you need transactional consistency, pre-operation stages work better.<\/div>\n<p><\/p>\n    \t\t\t<\/div>\n    \t\t\t    \t\t<\/div>\n    \t<\/section>\n    \n\n\n\n<h3 class=\"wp-block-heading\">Avoiding Duplicates During Create Events<\/h3>\n\n\n\n<p>Duplicate detection fits naturally in the prevalidation stage in Dynamics CRM. You want to catch duplicates before creating the record, not after.<\/p>\n\n\n\n<p>If your organization enforces unique email addresses across all contacts, here&#8217;s how:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (context.MessageName == \"Create\" &amp;&amp; target.LogicalName == \"contact\" &amp;&amp; target.Contains(\"emailaddress1\"))\n{\n    var email = target.GetAttributeValue&lt;string&gt;(\"emailaddress1\");\n    \n    var query = new QueryExpression(\"contact\")\n    {\n        ColumnSet = new ColumnSet(\"contactid\"),\n        Criteria = new FilterExpression\n        {\n            Conditions =\n            {\n                new ConditionExpression(\"emailaddress1\", ConditionOperator.Equal, email)\n            }\n        },\n        TopCount = 1\n    };\n    \n    var results = service.RetrieveMultiple(query);\n    \n    if (results.Entities.Count &gt; 0)\n    {\n        throw new InvalidPluginExecutionException($\"A contact with email address {email} already exists.\");\n    }\n}<\/code><\/pre>\n\n\n\n<p>The check runs before the create operation begins. You avoid starting a transaction, attempting the insert, and then discovering the duplicate.<\/p>\n\n\n\n<p>For complex duplicate detection\u2014multiple fields, fuzzy matching, calculated values\u2014evaluate whether prevalidation gives you enough context. Sometimes, pre-operation plugins provide better reliability when you need to compare more sophisticated criteria.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Build a Prevalidation Plugin in Dynamics 365<\/h2>\n\n\n\n<p>Building a prevalidation plugin in Dynamics 365 follows a straightforward process. Let&#8217;s walk through each step thoroughly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step #1: Define and Register the Plugin<\/h3>\n\n\n\n<p>Start by creating a new Class Library project in Visual Studio targeting .NET Framework 4.6.2 or later. Add the Microsoft.CrmSdk.CoreAssemblies NuGet package to get the necessary references.<\/p>\n\n\n\n<p>Your plugin class needs to implement the IPlugin interface:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>using System;\nusing Microsoft.Xrm.Sdk;\n\nnamespace AegisSofttech.Dynamics.Plugins\n{\n    public class ValidateContactEmail : IPlugin\n    {\n        public void Execute(IServiceProvider serviceProvider)\n        {\n            \/\/ Plugin logic goes here\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>Build the project and sign the assembly with a strong name key. This creates the DLL file you&#8217;ll register with Dynamics 365.<\/p>\n\n\n\n<p>Now comes the registration part. Open the Plugin Registration Tool and connect to your environment. Register your assembly, then register a new step with these settings:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Message: <\/strong>Create (or Update\/Delete depending on your needs)<\/li>\n\n\n\n<li><strong>Primary Entity: <\/strong>The entity you&#8217;re validating (e.g., contact)<\/li>\n\n\n\n<li><strong>Event Pipeline Stage of Execution: <\/strong>PreValidation (10)<\/li>\n\n\n\n<li><strong>Execution Mode: <\/strong>Synchronous<\/li>\n\n\n\n<li><strong>Deployment: <\/strong>Server<\/li>\n<\/ul>\n\n\n\n<p>The stage selection matters here. Prevalidation corresponds to stage 10 in the pipeline. This ensures your validation runs before security checks and before any database transaction begins.<\/p>\n\n\n\n<p>You can register multiple steps for the same plugin to validate different messages or entities. Each step runs independently based on its configuration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step #2: Implement Validation Logic<\/h3>\n\n\n\n<p>The validation logic retrieves necessary data, checks conditions, and throws an exception if validation fails. Here&#8217;s a complete example that validates email uniqueness:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public void Execute(IServiceProvider serviceProvider)\n{\n    \/\/ Get the execution context\n    var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));\n    \n    \/\/ Get the organization service (using system context for universal validation)\n    var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));\n    var service = serviceFactory.CreateOrganizationService(null);\n    \n    \/\/ Get the target entity from the input parameters\n    if (context.InputParameters.Contains(\"Target\") &amp;&amp; context.InputParameters&#091;\"Target\"] is Entity target)\n    {\n        \/\/ Check if this is a contact with an email address\n        if (target.LogicalName == \"contact\" &amp;&amp; target.Contains(\"emailaddress1\"))\n        {\n            var email = target.GetAttributeValue&lt;string&gt;(\"emailaddress1\");\n            \n            \/\/ Skip validation if email is empty\n            if (string.IsNullOrWhiteSpace(email))\n            {\n                return;\n            }\n            \n            \/\/ Query for existing contacts with this email\n            var query = new QueryExpression(\"contact\")\n            {\n                ColumnSet = new ColumnSet(\"contactid\"),\n                Criteria = new FilterExpression\n                {\n                    Conditions =\n                    {\n                        new ConditionExpression(\"emailaddress1\", ConditionOperator.Equal, email)\n                    }\n                },\n                TopCount = 1\n            };\n            \n            \/\/ For updates, exclude the current record\n            if (context.MessageName == \"Update\")\n            {\n                query.Criteria.AddCondition(\"contactid\", ConditionOperator.NotEqual, target.Id);\n            }\n            \n            var results = service.RetrieveMultiple(query);\n            \n            \/\/ Throw exception if duplicate found\n            if (results.Entities.Count &gt; 0)\n            {\n                throw new InvalidPluginExecutionException(\n                    $\"A contact with email address '{email}' already exists. Please use a unique email address.\");\n            }\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>Key points in this code:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>System context (CreateOrganizationService(null)) <\/strong>allows checking for duplicates regardless of user permissions<\/li>\n\n\n\n<li><strong>TopCount = 1<\/strong> optimizes the query since we need to know if any duplicates exist<\/li>\n\n\n\n<li><strong>Update handling<\/strong> excludes the current record when validating updates<\/li>\n\n\n\n<li><strong>Clear error message<\/strong> tells users exactly what went wrong and how to fix it<\/li>\n\n\n\n<li><strong>Null checks<\/strong> prevent errors when required data is missing<\/li>\n<\/ul>\n\n\n\n<p>The validation returns silently if everything checks out. If validation fails, the InvalidPluginExecutionException stops the operation and displays your message to the user.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step #3: Testing and Debugging<\/h3>\n\n\n\n<p>Testing <strong><em>prevalidation plugins in Dynamics 365<\/em><\/strong> requires checking both success and failure scenarios.<\/p>\n\n\n\n<p>Start with the Plugin Registration Tool&#8217;s profiler feature. Select your plugin step and click &#8220;Start Profiling.&#8221; This captures execution details, including any errors, timing information, and trace logs.<\/p>\n\n\n\n<p>Add tracing to your plugin for debugging:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));\ntracingService.Trace(\"Starting email validation for contact\");\ntracingService.Trace($\"Email address being validated: {email}\");\n<\/code><\/pre>\n\n\n\n<p>These traces appear in the Plugin Trace Log when you enable logging for your plugin step.<\/p>\n\n\n\n<p>For local debugging, use the Plugin Registration Tool to download the profiler results. Then use the Plug-in Profiler Utility in Visual Studio to replay the execution with breakpoints.<\/p>\n\n\n\n<p>Test these scenarios:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Single record creation<\/strong> through the UI to verify basic validation<\/li>\n\n\n\n<li><strong>Bulk import<\/strong> using the Data Import wizard with both valid and invalid records<\/li>\n\n\n\n<li><strong>API calls<\/strong> through tools like Postman or custom code<\/li>\n\n\n\n<li><strong>Update operations<\/strong> if your validation applies to updates<\/li>\n<\/ul>\n\n\n\n<p>During bulk imports, check that invalid records fail with your error message while valid records succeed. The prevalidation plugin should handle high volumes efficiently since no transactions start for failed validations.<\/p>\n\n\n\n<p>Monitor execution time in the Plugin Trace Log. Prevalidation plugins in Dynamics 365 should complete quickly\u2014aim for under one second. If validation takes longer, optimize your queries or reconsider whether prevalidation is the right stage.<\/p>\n\n\n    \t<section class=\"call-to-action-section\">\n    \t\t<div class=\"call-to-action-container\">\n    \t\t\t<div class=\"call-to-action-body\">\n    \t\t\t\t<div class=\"cta-title\"><\/div>\n    \t\t\t\t<p><\/p>\n<div style='text-align:left; color:white;'>\nOur work doesn\u2019t stop after implementation. We stick around to make sure your Dynamics 365 environment stays secure, updated, and trouble-free as your business grows.<\/div>\n<p><\/p>\n    \t\t\t<\/div>\n    \t\t\t    \t\t\t\t<div class=\"call-to-action-btn\">\n    \t\t\t\t\t<a href=\"https:\/\/www.aegissofttech.com\/contact-us.html\">Contact Us Today to Keep Your System Running at Its Best<\/a>\n    \t\t\t\t<\/div>\n    \t\t\t    \t\t<\/div>\n    \t<\/section>\n    \n\n\n\n<h2 class=\"wp-block-heading\">Common Mistakes and How to Avoid Them<\/h2>\n\n\n\n<p>Below are some of the most frequent issues developers face when working with prevalidation plugins in Dynamics 365 and the right ways to prevent them.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Common Mistake<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>Impact on System or Logic<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>How to Avoid It<\/strong><\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Placing heavy or complex business logic in the prevalidation stage<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Slows execution and may cause timeouts during data entry or imports<\/td><td class=\"has-text-align-center\" data-align=\"center\">Keep prevalidation logic light. Restrict this stage to simple validation and filtering; move complex logic to the pre-operation or post-operation stages.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Skipping null or type checks<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Leads to unexpected exceptions when certain attributes are missing or incorrectly typed<\/td><td class=\"has-text-align-center\" data-align=\"center\">Always validate attribute existence and data types before accessing them. Implement null checks at the start of each operation.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Ignoring plugin execution order<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Causes conflicts when multiple plugins act on the same entity or message<\/td><td class=\"has-text-align-center\" data-align=\"center\">Define explicit execution order in the plugin execution pipeline in Dynamics 365 to maintain predictable behavior.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Failing to handle security context<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">May cause unauthorized access or skipped validation based on user privileges<\/td><td class=\"has-text-align-center\" data-align=\"center\">Validate user roles and context in the plugin registration. Ensure the plugin runs under a secure, least-privilege user context.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Not managing dependencies between plugins<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Creates cascading failures when one plugin relies on another to run first<\/td><td class=\"has-text-align-center\" data-align=\"center\">Use shared variables or dependency injection to maintain data consistency and manage inter-plugin communication.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Using hardcoded values or static references<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Makes code brittle and hard to maintain when schema or configuration changes<\/td><td class=\"has-text-align-center\" data-align=\"center\">Store configurable data in environment variables or custom settings instead of embedding them directly in code.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Neglecting exception handling or custom error messages<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Causes vague CRM errors and poor user experience<\/td><td class=\"has-text-align-center\" data-align=\"center\">Throw clear, descriptive exceptions that guide users toward corrective actions while logging detailed technical data for developers.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Strategies to Optimize Prevalidation Plugins for Performance<\/h2>\n\n\n\n<p>Since prevalidation plugins execute synchronously, slow validation logic directly impacts user experience and system throughput. Here are some strategies to optimize the pre-validation stage in Dynamics CRM<strong><em> <\/em><\/strong>for performance:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Cache Configuration Data<\/h3>\n\n\n\n<p>Dynamics 365 plugin development often requires referencing configuration values or lookup tables. Loading this data on every execution creates unnecessary database overhead.<\/p>\n\n\n\n<p>Implement static caching for data that changes infrequently:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private static Dictionary&lt;string, int&gt; _validationThresholds;\nprivate static DateTime _cacheExpiry = DateTime.MinValue;\n\nprivate Dictionary&lt;string, int&gt; GetValidationRules(IOrganizationService service)\n{\n    if (_validationThresholds == null || DateTime.UtcNow &gt; _cacheExpiry)\n    {\n        var query = new QueryExpression(\"aegis_validationconfig\")\n        {\n            ColumnSet = new ColumnSet(\"aegis_rulename\", \"aegis_threshold\")\n        };\n        \n        var results = service.RetrieveMultiple(query);\n        _validationThresholds = results.Entities.ToDictionary(\n            e =&gt; e.GetAttributeValue&lt;string&gt;(\"aegis_rulename\"),\n            e =&gt; e.GetAttributeValue&lt;int&gt;(\"aegis_threshold\")\n        );\n        \n        _cacheExpiry = DateTime.UtcNow.AddMinutes(15);\n    }\n    \n    return _validationThresholds;\n}<\/code><\/pre>\n\n\n\n<p>This pattern reduced one client&#8217;s validation from 450ms to 80ms by eliminating repeated configuration queries during bulk imports.<\/p>\n\n\n\n<section class=\"call-to-action-section\">\n<div class=\"call-to-action-container\">\n<div class=\"call-to-action-body\">\n<div class=\"cta-title\"><\/div>\n<p><\/p>\n<div style=\"text-align:center; color:white;\">\n<strong>Also Read:<\/strong> <a href=\"https:\/\/www.aegissofttech.com\/insights\/crm-market\/\" target=\"_blank\">Comprehensive Guide to Conquering CRM Markets Using Testing<\/a><\/div>\n<p><\/p>\n<\/div>\n<\/div>\n<\/section>\n\n\n\n<h3 class=\"wp-block-heading\">Write Efficient Queries<\/h3>\n\n\n\n<p>Query optimization dramatically affects Dynamics 365 CRM data validation<strong><em> <\/em><\/strong>performance. Retrieve only the columns you need and limit result sets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Slow: Retrieves all columns\nvar account = service.Retrieve(\"account\", accountId, new ColumnSet(true));\n\n\/\/ Fast: Retrieves only needed field\nvar account = service.Retrieve(\"account\", accountId, new ColumnSet(\"statecode\"));\n\n\/\/ For existence checks, use TopCount\nvar query = new QueryExpression(\"contact\")\n{\n    ColumnSet = new ColumnSet(\"contactid\"),\n    Criteria = new FilterExpression\n    {\n        Conditions = { new ConditionExpression(\"emailaddress1\", ConditionOperator.Equal, email) }\n    },\n    TopCount = 1  \/\/ Stop after finding first match\n};<\/code><\/pre>\n\n\n\n<p>For duplicate detection in the pre-validation stage in Dynamics CRM, TopCount prevents retrieving thousands of matching records when you need to know if any exist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Leverage Execution Context<\/h3>\n\n\n\n<p>The execution context contains valuable information that avoids additional queries:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public void Execute(IServiceProvider serviceProvider)\n{\n    var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));\n    \n    \/\/ Use context properties to avoid queries\n    var userId = context.InitiatingUserId;\n    var organizationId = context.OrganizationId;\n    var depth = context.Depth;\n    \n    \/\/ Skip validation for system-initiated operations\n    if (depth &gt; 1)\n    {\n        return;  \/\/ Prevents validation loops in recursive scenarios\n    }\n    \n    \/\/ Check shared variables set by other plugins\n    if (context.SharedVariables.Contains(\"SkipValidation\"))\n    {\n        return;\n    }\n}<\/code><\/pre>\n\n\n\n<p>Checking the depth property prevents infinite loops and unnecessary validation when plugins trigger other plugins.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Batch Validation Checks<\/h3>\n\n\n\n<p>When validating multiple conditions, structure checks from simplest to most complex:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Fast checks first\nif (string.IsNullOrWhiteSpace(email))\n{\n    throw new InvalidPluginExecutionException(\"Email is required.\");\n}\n\nif (!email.Contains(\"@\"))\n{\n    throw new InvalidPluginExecutionException(\"Invalid email format.\");\n}\n\n\/\/ Expensive database query last\nvar existingContact = CheckForDuplicate(service, email);\nif (existingContact != null)\n{\n    throw new InvalidPluginExecutionException(\"Duplicate email found.\");\n}<\/code><\/pre>\n\n\n\n<p>This approach exists early on, with simple validation failures, avoiding costly database queries when basic checks fail.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prevalidation, Pre-Operation, and Post-Operation Plugins Compared<\/h2>\n\n\n\n<p>Knowing how prevalidation, pre-operation, and post-operation plugins differ helps developers decide where specific logic belongs for optimal performance and maintainability.<\/p>\n\n\n\n<p>Here\u2019s a clear comparison of the three stages:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Plugin Stage<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>Execution Timing<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>Purpose<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>Transaction Scope<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>Typical Use Cases<\/strong><\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Prevalidation<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Runs before the core transaction begins and before security checks<\/td><td class=\"has-text-align-center\" data-align=\"center\">Ensures data accuracy and compliance before any database or platform operations start<\/td><td class=\"has-text-align-center\" data-align=\"center\">Outside the transaction scope<\/td><td class=\"has-text-align-center\" data-align=\"center\">Early validation such as checking for missing mandatory fields, duplicate records, or invalid formats<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Pre-Operation<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Executes after security checks but before data is committed to the database<\/td><td class=\"has-text-align-center\" data-align=\"center\">Adjusts or enriches data before the system writes it to the database<\/td><td class=\"has-text-align-center\" data-align=\"center\">Inside the transaction scope<\/td><td class=\"has-text-align-center\" data-align=\"center\">Calculating derived fields, modifying record attributes, or enforcing specific constraints<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>Post-Operation<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Runs after the main database operation completes<\/td><td class=\"has-text-align-center\" data-align=\"center\">Performs logic that depends on successfully committed data<\/td><td class=\"has-text-align-center\" data-align=\"center\">Inside the transaction scope (synchronous) or outside it (asynchronous)<\/td><td class=\"has-text-align-center\" data-align=\"center\">Sending confirmation emails, updating related entities, or triggering integrations with external systems<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Debugging and Testing Best Practices<\/h2>\n\n\n\n<p>Effective debugging makes Dynamics 365 plugin <span style=\"box-sizing: border-box; margin: 0px; padding: 0px;\">development<em><strong>&nbsp;<\/strong><\/em>predictable<\/span> and maintainable. These are some of the best practices you can try:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Use Plugin Trace Viewer for Real-Time Diagnostics<\/h3>\n\n\n\n<p>The Plugin Trace Log captures execution details when you enable tracing during plugin registration. Add strategic trace points throughout your validation logic:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));\n\ntracingService.Trace(\"Prevalidation started for contact creation\");\ntracingService.Trace($\"Validating email: {email}\");\ntracingService.Trace($\"Query execution time: {stopwatch.ElapsedMilliseconds}ms\");\n\nif (results.Entities.Count &gt; 0)\n{\n    tracingService.Trace(\"Duplicate found - validation failed\");\n}<\/code><\/pre>\n\n\n\n<p>Access traces through <strong>Settings &gt; Plugin Trace Log<\/strong> or by downloading profiler results from the Plugin Registration Tool. These traces show exactly where validation fails and how long each operation takes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Integrate Application Insights for Production Monitoring<\/h3>\n\n\n\n<p>For production environments, Application Insights provides deeper visibility into the plugin execution pipeline in Dynamics 365:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var telemetryClient = new TelemetryClient();\ntelemetryClient.TrackEvent(\"PrevalidationExecuted\", new Dictionary&lt;string, string&gt;\n{\n    { \"EntityName\", context.PrimaryEntityName },\n    { \"ExecutionTime\", executionTime.ToString() },\n    { \"ValidationResult\", validationPassed ? \"Success\" : \"Failed\" }\n});<\/code><\/pre>\n\n\n\n<p>This telemetry helps identify performance bottlenecks and validation patterns across thousands of operations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Test in Isolation<\/h3>\n\n\n\n<p>Create a dedicated development environment for testing prevalidation plugins in Dynamics 365. Use the Plugin Registration Tool&#8217;s profiler to capture real execution contexts, then replay them locally in Visual Studio with breakpoints.<\/p>\n\n\n\n<p>Test individual validation rules separately before combining them. This isolation makes debugging specific failures easier.<\/p>\n\n\n\n<section class=\"call-to-action-section\">\n<div class=\"call-to-action-container\">\n<div class=\"call-to-action-body\">\n<div class=\"cta-title\"><\/div>\n<p><\/p>\n<div style=\"text-align:center; color:white;\">\n<strong>Also Read:<\/strong> <a href=\"https:\/\/www.aegissofttech.com\/insights\/top-5-plugins-integrations-for-crm\/\" target=\"_blank\">Top 5 Plugins &#038; Integrations for Your CRM Platform<\/a><\/div>\n<p><\/p>\n<\/div>\n<\/div>\n<\/section>\n\n\n\n<h3 class=\"wp-block-heading\">Test Concurrent Updates<\/h3>\n\n\n\n<p>Multiple users might trigger the same validation logic simultaneously. Use tools like Postman or custom scripts to send parallel API requests:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var tasks = new List&lt;Task&gt;();\nfor (int i = 0; i &lt; 50; i++)\n{\n    tasks.Add(Task.Run(() =&gt; CreateContact(service, $\"test{i}@example.com\")));\n}\nawait Task.WhenAll(tasks);<\/code><\/pre>\n\n\n\n<p>This stress testing reveals race conditions or caching issues in your validation logic. Monitor the Plugin Trace Log during concurrent execution to confirm thread safety and consistent performance.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Keep Your CRM Data Safe With Prevalidation Plugins<\/h2>\n\n\n\n<p>Prevalidation plugins in Dynamics 365 help your CRM stay clean and reliable. They catch errors before they reach the database, enforce business rules, and prevent messy issues from affecting other processes. Combined with pre-operation and post-operation plugins, they keep your data consistent and your workflows running efficiently.<\/p>\n\n\n\n<p>At Aegis Softtech, we create custom Dynamics 365 plugin solutions that fit your business needs. Our <a href=\"https:\/\/www.aegissofttech.com\/dynamics-365\/crm\" target=\"_blank\" rel=\"noreferrer noopener\">Microsoft Dynamics CRM Consulting Services<\/a> involve building plugins that maintain data quality, optimize system performance, and enforce your rules without disrupting daily operations.<\/p>\n\n\n    \t<section class=\"call-to-action-section\">\n    \t\t<div class=\"call-to-action-container\">\n    \t\t\t<div class=\"call-to-action-body\">\n    \t\t\t\t<div class=\"cta-title\"><\/div>\n    \t\t\t\t<p><\/p>\n<div style='text-align:center; color:white;'>\nWith Aegis Softtech, Dynamics 365 works the way your business needs it to.<br \/>\n<a href='https:\/\/www.aegissofttech.com\/contact-us.html' target='_blank'>Schedule a free consultation<\/a> with our team today!<\/div>\n<p><\/p>\n    \t\t\t<\/div>\n    \t\t\t    \t\t<\/div>\n    \t<\/section>\n    \n\n\n\n<h2 class=\"wp-block-heading\">FAQs<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Can we have an async plugin in preoperative?<\/h3>\n\n\n\n<p>No, pre-operation plugins in Dynamics 365 must always be synchronous. This is because pre-operation logic runs within the same transaction as the database operation, and asynchronous execution cannot participate in a transaction. Only post-operation plugins can be asynchronous.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. What is the difference between asynchronous and synchronous plugins?<\/h3>\n\n\n\n<p>Synchronous plugins execute immediately during the plugin pipeline and block the operation until they finish running. Asynchronous plugins, on the other hand, run in the background after the operation completes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Which will execute first in an async workflow and an async plugin?<\/h3>\n\n\n\n<p>When both an asynchronous plugin and an asynchronous workflow are registered on the same entity, the asynchronous plugin generally executes first. This is because async plugins registered on post-operation stages are queued immediately after the transaction completes, while asynchronous workflows are processed slightly later by the system\u2019s workflow engine.<\/p>\n","protected":false},"excerpt":{"rendered":" ","protected":false},"author":11,"featured_media":19343,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[19,21],"tags":[1625],"class_list":["post-11002","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dynamics-365","category-dynamics-crm","tag-prevalidation-plugins-in-dynamics-365"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts\/11002","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/comments?post=11002"}],"version-history":[{"count":12,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts\/11002\/revisions"}],"predecessor-version":[{"id":19350,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts\/11002\/revisions\/19350"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/media\/19343"}],"wp:attachment":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/media?parent=11002"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/categories?post=11002"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/tags?post=11002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}