Sunday, November 10, 2019

Pre and PostImage Optionset



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:
MessageStagePre-ImagePost-Image
CreatePRENoNo
CreatePOSTNoYes
UpdatePREYesNo
UpdatePOSTYesYes
DeletePREYesNo
DeletePOSTYesNo
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

No comments:

Post a Comment