Sunday, 21 January 2018

Pre-Image and Post-Image in Dynamics CRM



What is Pre and Post Images in CRM?

In Real Life,

Let's understand the Images in CRM by taking one real-life example of ATM Withdrawal Process:

Suppose, I have 10,000 Rs in my bank account. So this amount would be the Pre-Image of my account balance. Now, If I withdraw 5000 Rs from my account, then the remaining amount left in my account would be 5000 Rs. So the current amount left in my account would be the Post-Image of my account balance.

Here

Pre-Image of my Account Balance = 10,000 Rs
Performing Database Transaction
Transaction Done (Core Operation) of 5000Rs
Post-Image of my Account Balance = 5000 Rs

In CRM,
  • Images are the snapshots of the entity's attributes, before and after the core system operation. 
  • PreEntityImages contain snapshots of the primary entity's attributes before the core platform operation perform and PostEntityImages contains the snapshot of the primary entity's attributes after the core platform operation performed.
Let say: I have a contact record in the CRM with FirstName and LastName as Arpit and Shrivastava respectively. Suppose I change the values of both the field as Mike and Hussey respectively. Then the  Pre-Image of FirstName and LastName would be Arpit and Shrivastava respectively while the Post-Image of FirstName and LastName would get Mike and Hussey respectively.


Difference between Plugin Context and Plugin Images? 



Context means Current.

Context contains the entity business information which is being updated currently on CRM Platform.

In Plugin,

IPluginExecutionContext contains information that describes the run-time environment that the plug-in executes, information related to the execution pipeline, and entity business information.

When a system event is fired that a plug-in is registered for, the system creates and populates the context and passes it to a plug-in through the previously mentioned classes and methods. The execution context is passed to each registered plug-in in the pipeline when they are executed.

Context Example - 

Let say. I have a plugin registered on Update of Contact Entity, If I update only Firstname and Lastname of contact record then plugin code can get only Firstname and Lastname 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 emailaddress and account name 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 context we can get the updated field's values only

Advantages of using Pre-Image and Post-Image in CRM?

One of the best uses for this is in update plug-ins. 

  • In update plug-in, target entity only contains the updated attributes. However, often the plug-in will require information from other attributes as well. Instead of issuing a retrieve, the best practice is to push the required data in an image instead.

For Example- I have a plugin trigger on Update of Account's email address and website fields. 

Logic is if any user updates the account's email address and website URL then, create a task with the updated email address and website URL along with account name and its parent account.

To implement this logic in my plugin, I can get account's email address and website URL from Context while account name and parent account.not. Because the user has updated only account's email address and website URL not rest of the account's data. So Plugin Context contains only updated information instead of unchanged information.

So how would I get the account's account name, parent account or any other data?

Option 1- Perform Retrieve Query to get rest of account information.

Option 2- Use Pre-Image and configure the fields from which we want to pull the information without performing any query on the database.

  • Comparison of data before and after. This allows for various audit-type plugins, that logs what the value was before and after, or calculating the time spent in a stage or status.


When the different images are available in the event execution pipeline? 






Plugin Image Example:

Let understand the plugin code by taking a very simple example- 

Whenever a user updates the emailaddress and topic(subject) on the Lead entity, we want to get the old and new value respectively of the topic field before and after the changes made in the database. And update both the values in the description field.

So here, the old value of topic field would be called as pre-image and the new value of topic field would be called as post image.

Register a Plugin on Update of Lead 'Email Address' Field.

























Register a new Image on Update Step



















Select 'Topic' from the Field List. Because we want to get the Pre and Post Image of Topic Field.



























Give Image name and check PreImage and PostImage checkbox



You can specify to have the platform populate these PreEntityImages and PostEntityImages properties when you register your plug-in. The entity alias value you specify during plug-in registration is used as the key into the image collection in your plug-in code


















using Microsoft.Xrm.Sdk;

using Microsoft.Xrm.Sdk.Query;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace PluginImageExample
{

 public class LeadUpdate : IPlugin

  {

    public void Execute(IServiceProvider serviceProvider)

    {

    // Extract the tracing service for use in debugging sandboxed plug-ins.

    ITracingService tracingService =

    (ITracingService)serviceProvider.GetService(typeof(ITracingService));


    // Obtain the execution context from the service provider.

    IPluginExecutionContext context = 

    (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));


    // Obtain the organization service factory.
    
    IOrganizationServiceFactory serviceFactory = 

    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

    
    // Obtain the organization service.    
    IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);


    if (context.InputParameters.Contains("Target") && 

                  context.InputParameters["Target"] is Entity)

     {

        // Obtain the target entity from the input parameters.

         Entity entity = (Entity)context.InputParameters["Target"];

        // User is updating only email address in lead form so we will get only 
           emailaddress from the context not lead's description.To get description
           orsubject field we will use plugin images
     
        // get the lead email from context.

         string email = entity["emailaddress1"].ToString();

        // get the current record guid from context

         Guid leadRecordGuid = entity.Id;

       
// Define variables to store Preimage and Postimage string pretopic = string.Empty; string posttopic = string.Empty;

        // in below leadimage has been added in plugin registration tool

        // get PreImage from Context

          if (context.PreEntityImages.Contains("LeadTopicImage") && 
                context.PreEntityImages["LeadTopicImage"] is Entity)
          {

               Entity preMessageImage = (Entity)context.PreEntityImages["LeadTopicImage"];

               // get topic field value before database update perform
pretopic = (String)preMessageImage.Attributes["subject"]; } // get PostImage from Context

            if (context.PostEntityImages.Contains("LeadTopicImage") && 
                   context.PostEntityImages["LeadTopicImage"] is Entity)

            {

              Entity postMessageImage = (Entity)context.PostEntityImages["LeadTopicImage"];

            // get topic field value after database update performed
posttopic = (String)postMessageImage.Attributes["subject"]; } // update the old and new values of topic field in description field

          Entity leadObj = 
          service.Retrieve(context.PrimaryEntityName,leadRecordGuid, new ColumnSet("description"));

          leadObj["description"] = 
          "Pre-Image of description- "+pretopic+"   "+"Post-Image of description-- "+posttopic;

          service.Update(leadObj);

           }

        }

    }

}


Let's test the functionality. Open any existing Lead record.




















Update Email and Topic field's value and Save the record.





















Check the 'Description' field. It has been updated with old and new value both of Topic Field.




Points to Note:

                                      
  • 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. 
  • There are some events where images aren’t available. For example, only synchronous post-event and asynchronous registered plug-ins have PostEntityImages populated. The create operation doesn’t support a pre-image and a delete operation doesn’t support a post-image.
  • 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.
  • A pre-image passed in the execution context to a plug-in or custom workflow activity might contain data that the logged-on user doesn't have the privileges to access. Microsoft Dynamics 365 administrators and other users with high-level permissions can register plug-ins to run under the “system” user account or plug-in code can make calls as a “system” user on behalf of the logged-on user. If this happens, logged-on users can access data that their field level security does not allow access to.
  • Context contains only 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)


Cheers😎

5 comments:

  1. if i had to run the plugin on update of checkbox value, means in context i will only get value of Checkbox and for other fields i have to use preImage?
    My question is Do i require Post Image here? because its a boolean value i only require T/F value to run the plugin.
    Thanks

    ReplyDelete
    Replies
    1. Hi Bhavendra,

      Yes if only checkbox value is being changed from CRM application then you will get checkbox value in the context. In order to get other field's information you will require to use pre images.
      I don't feel like using post image in this requirement. Because, purpose of post image is to get the updated value of any field after database transaction occured which is not required in this requirement.
      Thanks

      Delete
  2. Hello Arpit,
    Very useful information. I am new to this dynamics crm.
    I have a requirement that if any user changes values from other source other than CRM then I have to update a status of contact entity in CRM. Which one is better to use? please help me if you can explain

    ReplyDelete
  3. Wonderful post! We will be linking to this particularly great article on our Site. Keep up the great writing.
    CRM Software in Dubai
    CRM Software
    CRM Software in UAE
    CRM Software for Small Business

    ReplyDelete
  4. Better explained Arpit. Today I got clear concept of use of image in plugins

    ReplyDelete

Blogger Widgets