Preface

A few days ago, I happened to read Luo Yong’s blog about the use of Image in various message phases, which reminded me that I’ve been practicing something similar before. However, I haven’t written anything about it for a long time recently, so I’m going to take advantage of the free time I have today to try it out again and record it for future reference.

In the process of implementing Dynamics CRM project, sometimes you need to perform some custom logic before and after the entity update operation, so the two properties PreEntityImages and PostEntityImages play an important role. I will show you how to use these two properties to retrieve entity data and process it accordingly through a code example.

Sample code

The code is as follows:

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Text;

namespace Blog.D365.Plugins.Account
{
    public class AccountPostUpdate : IPlugin
    {
        private const string addressLine1 = "address1_line1";
        private const string addressLine2 = "address1_line2";
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            try
            {
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    Entity currentEntity = (Entity)context.InputParameters["Target"];
                    IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                    IOrganizationService service = factory.CreateOrganizationService(context.UserId);
                    IOrganizationService serviceAdmin = factory.CreateOrganizationService(null);
                    Entity preEntityImages, postEntityImages = new Entity();

                    // Get PreEntityImages
                    if (context.PreEntityImages.Contains("PreImg"))
                        preEntityImages = context.PreEntityImages["PreImg"];
                    else
                        throw new InvalidPluginExecutionException("Pre Update image - PreImg does not exist!");

                    // Get PostEntityImages 
                    if (context.PostEntityImages.Contains("PostImg"))
                        postEntityImages = context.PostEntityImages["PostImg"];
                    else
                        throw new InvalidPluginExecutionException("Post Update image - PostImg does not exist!");

                    // Get RetrieveEntity
                    Entity retrieveEntity = serviceAdmin.Retrieve("account", currentEntity.Id, new ColumnSet("address1_line1", "address1_line2"));

                    StringBuilder strBuilder = new StringBuilder(); // Build output message

                    AppendAddressInfo(strBuilder, postEntityImages, "postEntityImages", addressLine1);
                    AppendAddressInfo(strBuilder, preEntityImages, "preEntityImages", addressLine1);
                    AppendAddressInfo(strBuilder, retrieveEntity, "retrieveEntity", addressLine1);
                    AppendAddressInfo(strBuilder, currentEntity, "currentEntity", addressLine1);

                    AppendAddressInfo(strBuilder, postEntityImages, "postEntityImages", addressLine2);
                    AppendAddressInfo(strBuilder, preEntityImages, "preEntityImages", addressLine2);
                    AppendAddressInfo(strBuilder, retrieveEntity, "retrieveEntity", addressLine2);
                    AppendAddressInfo(strBuilder, currentEntity, "currentEntity", addressLine2);

                    throw new InvalidPluginExecutionException(strBuilder.ToString()); // print
                }

            }
            catch (Exception ex)
            {
                tracer.Trace($"AccountPostUpdate unexpected exception:\n{ex.Message}");
                throw;
            }
        }
        private void AppendAddressInfo(StringBuilder strBuilder, Entity entity, string entityName,string addressField)
        {
            if (entity.Contains(addressField))
                strBuilder.Append($"{entityName} contains attribute “{addressField}” = {entity.GetAttributeValue<string>(addressField)};\n");
            else
                strBuilder.Append($"{entityName} does not contain attribute “{addressField}”;\n");
        }
    }
}

Plugin Registration and Image

  • Plugin Registration 01

  • Image 02

Validation

Case 1

Originally two fields are not filled with data, now fill in the “East China Sea”, “West China Sea”, the results are as follows.

Before RevisionAfter Revision
address1_line1 = nulladdress1_line1 = “East China Sea”
address1_line2 = nulladdress1_line2 = “West China Sea”

Retule:

postEntityImages contains attribute “address1_line1” = East China Sea; 
preEntityImages does not contain attribute “address1_line1”; 
retrieveEntity contains attribute “address1_line1” = East China Sea; 
currentEntity contains attribute “address1_line1” = East China Sea; 

postEntityImages contains attribute “address1_line2” = West China Sea; 
preEntityImages does not contain attribute “address1_line2”; 
retrieveEntity contains attribute “address1_line2” = West China Sea; 
currentEntity contains attribute “address1_line2” = West China Sea;

Case 2

Originally both fields had data now modified to “Chai An” and “Li Sanniang” respectively. The result is as follows.

Before RevisionAfter Revision
address1_line1 = “XiaoMing”address1_line1 = “Chai An”
address1_line2 = “Rickey”address1_line2 = “Li Sanniang”

Retule:

postEntityImages contains attribute “address1_line1” = Chai An; 
preEntityImages contains attribute “address1_line1” = XiaoMing; 
retrieveEntity contains attribute “address1_line1” = Chai An; 
currentEntity contains attribute “address1_line1” = Chai An; 

postEntityImages contains attribute “address1_line2” = Li Sanniang; 
preEntityImages contains attribute “address1_line2” = Rickey; 
retrieveEntity contains attribute “address1_line2” = Li Sanniang; 
currentEntity contains attribute “address1_line2” = Li Sanniang; 

Case 3

Originally there was data in both fields, now only address1_line1 is modified to “Chai An” and the result is as follows.

Before RevisionAfter Revision
address1_line1 = “Peter”address1_line1 = “Chai An”
address1_line2 = “Benson”(no changes)

Retule:

postEntityImages contains attribute “address1_line1” = Chai An; 
preEntityImages contains attribute “address1_line1” = Peter; 
retrieveEntity contains attribute “address1_line1” = Chai An; 
currentEntity contains attribute “address1_line1” = Chai An; 

postEntityImages contains attribute “address1_line2” = Benson; 
preEntityImages contains attribute “address1_line2” = Benson; 
retrieveEntity contains attribute “address1_line2” = Benson; 
currentEntity does not contain attribute “address1_line2”; 

Case 4

Originally there was data in both fields, now only address1_line2 is modified to “KK” and the result is as follows.

Before RevisionAfter Revision
address1_line1 = “Benson”(no changes)
address1_line2 = “Peter”address1_line2 = “KK”

Retule:

postEntityImages contains attribute “address1_line1” = Benson; 
preEntityImages contains attribute “address1_line1” = Benson; 
retrieveEntity contains attribute “address1_line1” = Benson; 
currentEntity does not contain attribute “address1_line1”; 

postEntityImages contains attribute “address1_line2” = KK; 
preEntityImages contains attribute “address1_line2” = Peter; 
retrieveEntity contains attribute “address1_line2” = KK; 
currentEntity contains attribute “address1_line2” = KK; 

Case 5

Originally both fields had data, now address1_line1 is cleared and address1_line2 is left unchanged, the result is as follows.

Before RevisionAfter Revision
address1_line1 = “Ming”address1_line1 = null
address1_line2 = “Peter”(no changes)

Retule:

postEntityImages does not contain attribute “address1_line1”; 
preEntityImages contains attribute “address1_line1” = Ming; 
retrieveEntity does not contain attribute “address1_line1”; 
currentEntity contains attribute “address1_line1” = ; 

postEntityImages contains attribute “address1_line2” = Peter; 
preEntityImages contains attribute “address1_line2” = Peter; 
retrieveEntity contains attribute “address1_line2” = Peter; 
currentEntity does not contain attribute “address1_line2”;

Case 6

Originally address1_line1 has no value and address1_line2 has a value, now fill in address1_line1 as “Chaiyen” and the result is as follows.

Before RevisionAfter Revision
address1_line1 = nulladdress1_line1 = “Chaiyen”
address1_line2 = “Rickey”(no changes)

Retule:

postEntityImages contains attribute “address1_line1” = Chaiyen; 
preEntityImages does not contain attribute “address1_line1”; 
retrieveEntity contains attribute “address1_line1” = Chaiyen; 
currentEntity contains attribute “address1_line1” = Chaiyen;
 
postEntityImages contains attribute “address1_line2” = Rickey; 
preEntityImages contains attribute “address1_line2” = Rickey; 
retrieveEntity contains attribute “address1_line2” = Rickey; 
currentEntity does not contain attribute “address1_line2”;