Pre image and Post image in Dynamics 365 Customer Engagement (CRM) Plugins : Advanced Plugin concepts Part 1

Pre-image and Post-image in Dynamics Customer Engagement(CRM) plugins

By definition “A pre-image is a snapshot of the entity’s attributes before the core operation and a post-image is a snapshot of the entity’s attribute after the core operation.”

As definition suggested, pre image captures the entity’s attributes before the core platform operation takes place while the post image stores the attributes post core platform operation is performed.

In plugin registration tool, we can select the particular attributes which we want to capture in image or we can select all attributes depending on the requirement.

So when does we actually need to use it? We’ll learn to use images by implementing a scenario in dynamics Customer Engagement(CRM).

Scenario :

On case entity, we have priority field with values as Low, Normal and High. Let’s say, you have stop user from updating  the priority of case from Low to High. Nothing should happen if it turn from normal to high or any other combination.

So at first, it seems easy that on update event, we can check for priority value but how would you determine what was the value of priority before high? was it low or normal?

Here pre-image comes for the rescue. What we’ll do is, we’ll register a pre-image on the plugin and use the value of priority attribute in pre-image entity to check whether it was Low earlier or not.

Step 1 : Develop and build a plugin

Build a plugin with the code written below.

In this code, we are retrieving the priority value from pre-image and if it’s low then we are retrieving the priority value fromthe current context entity. If priority in current context entity is High means our condition got met. We’ll throw an exception in that case.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Customer Engagement(CRM).Sdk.Messages;

namespace TestPlugin
{
 public class ImageDemo : IPlugin
 {
 public void Execute(IServiceProvider serviceProvider)
 {
 #region Setup
 IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
 IOrganizationService service = ((IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory))).
 CreateOrganizationService(new Guid?(context.UserId));
 ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
 #endregion
 if ((context.InputParameters.Contains("Target")) && (context.InputParameters["Target"] is Entity) && context.MessageName.ToUpper()=="UPDATE")
 {
  Entity entity = (Entity)context.InputParameters["Target"];
  if (entity.LogicalName.ToLower() != "incident") return;
  try
  {
   Entity preImage = (Entity)context.PreEntityImages["Image"];
   if (preImage.Contains("prioritycode"))
   {
     if (preImage.GetAttributeValue<OptionSetValue>("prioritycode").Value == 3)//if Pre image have priority = Low
      { //if Current entity have priority = High
      if (entity.Contains("prioritycode") && entity.GetAttributeValue<OptionSetValue>("prioritycode").Value == 1)
         {
          throw new Exception("Changing priority form Low to High is now allowed");
          }
       }
    }
  }
   catch (Exception ex)
    {
     throw new Exception(""+ex.Message);
     }
   }
  }
 }
}

Below is how your code will look like:

Step 2: Register the plugin assembly and step

Register the plugin and add the step on post update of the case and set priority field as filtering attribute.

Make sure the plugin is synchronous and running on post operation.

Once a step is registered, we need to configure our Pre/Post Images manually. Just because we have referenced them in our code above doesn’t mean they will automatically become available to us as our plugin is executed. Fortunately, adding them on is not too difficult and we can do it directly within the Plugin Registration Tool.

Step 3: Register the Image:

Right click on the step we just added and click on

Step 4: Define properties of the image

Set the image properties as shown in below image. Make sure entity alias is same as you used in plugin code in the following line:

Entity preImage = (Entity)context.PreEntityImages["Image"];

One good thing about this is that we can configure both our Pre and Post Images in the one screen. We just confirm that our intended plugin step is selected, tick both of the boxes and ensure that the following details are completed:

  • Name: Specify a name for this image. This can be anything you want it to be, but I would recommend using the same value as Entity Alias
  • Entity Alias: This is the name that is used in our code above to reference the image. This must match exactly against this in order for the code to work correctly.
  • Parameters: Here you specify which attributes will be made available within the image. By default, all attributes are included, but you should specify only the attributes you need to work with in your plugin. For our example plugin, we only need the Priority field, so this is the only attribute we will select.

Step 5: Testing the result

Once registered, we are ready to test. Now make sure current priority of case if Low. Try changing it to High

You’ll get the expected error as shown below:

You can cross check it by first changing to priority to normal and then changing it to high from normal. It’ll get saved without any error.

So this was how we used pre-image to make sure user follow a defined order for priority update and couldn’t update it directly from low to high. There can be many more scenarios where you can utilize the images in Customer Engagement(CRM).

Similarly, you can register a post image and use below code to get the post image entity:

 Entity postImage = (Entity)context.PostEntityImages["Image"];

Following table shows when in the event pipeline different images are available:

Message Stage Pre-Image Post-Image
Create PRE No No
Create POST No Yes
Update PRE Yes No
Update POST Yes Yes
Delete PRE Yes No
Delete POST Yes No

Points to remember

  • Microsoft Dynamics 365 populates the pre-entity and post-entity images based on the security privileges of the impersonated system user. Only entity attributes that are set to a value or are null are available in the pre or post entity images
  • If you try to get the image on message and stage where we have mentioned No, you’ll get an exception “The given key was not found in the dictionary”
  • You can configure both our Pre and Post Images on one image in the plugin registration tool by clicking both pre and post image options.
  • Registering for pre or post images to access entity attribute values results in improved plug-in performance as compared to obtaining entity attributes in plug-in code through RetrieveRequest or RetrieveMultipleRequest requests.
  • Make sure you retrieve correct image in plugin code using PreEntityImages and PostEntityImages properties of context.
  • Microsoft Dynamics 365 populates the pre-entity and post-entity images based on the security privileges of the impersonated system user. Only entity attributes that are set to a value or are null are available in the pre or post entity image
  • The context contains only the updated field’s value information of any record. While the Pre-Image contains all the field’s values information (depends on what field you are being opted to be available as pre-images)

More use case of Pre-image

  • Comparing the field value. for eg: plugin got fired even if you just write service.update for the entity with setting the same value of a field as earlier. To make sure your logic run only when there is actually a change in a field value, you can use pre-image to get and compare the value of a field and if both are different then only proceed.
  • To get the field values in plugin running on post update of a particular field we can use pre-image. Otherwise, we have to write service.retrieve to get the attributed other than the updated one. By using pre-image here we just saved a service call.

For eg: I have a plugin registered on Update of Account Entity, If I update the only name of account record then plugin code can get only name field’s value from the Plugin Context along with the information related to the execution pipeline. But If I want to get the other field’s value like email, mobile phone, and account number etc. from plugin context, we will not be able to get the same and will get the error ‘The given key was not present in the dictionary’ error.
To get these values, either we will have to perform retrieve query or can achieve it through pre-images.

So Images are the best ways to get the copy of data (from whatever fields you want) before and after changes made to the database or changes committed to the database. While from the context we can get the updated field’s values only



Leave a Reply

× WhatsApp Chat with us