Thursday 29 July 2021

Pre- validation plugins

 Recently we had a requirement to delete the Account record without deleting the associated Contact records.

If we try deleting the account record we’d get the following message box

The relationship definition can’t be updated as well to achieve this

So, we wrote a plugin on the pre-validation stage of pre-delete event of Account, which will retrieve and loop through all the child contact records and set its parent customer field as null.

In case of pre-operation the child records were not available.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</p>
<p>public void Execute(IServiceProvider serviceProvider)<br />
{<br />
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));<br />
IPluginExecutionContext pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));<br />
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));<br />
IOrganizationService organizationService = serviceFactory.CreateOrganizationService(pluginContext.UserId);<br />
EntityReference targetEntity = (EntityReference)pluginContext.InputParameters["Target"];<br />
QueryExpression getContacts = new QueryExpression("contact");<br />
getContacts.Criteria.AddCondition(new ConditionExpression("parentcustomerid", ConditionOperator.Equal, targetEntity.Id));EntityCollection allContacts = organizationService.RetrieveMultiple(getContacts);foreach (Entity contact in allContacts.Entities)<br />
{<br />
Entity contactToBeUpdated = new Entity("contact");<br />
contactToBeUpdated.Id = contact.Id;<br />
contactToBeUpdated.Attributes["parentcustomerid"] = null;<br />
organizationService.Update(contactToBeUpdated);<br />
}}<br />





******************************


Plugin Pre-validation Operation to Show an Error Message as well as Log the Error



We had a business requirement, where we created a custom entity with a grid of Associated Accounts. Here, we wanted to restrict the Account while adding Accounts in the Associated View. We wanted to do this when the Account does not have the status reason ‘Approved’ by showing an error message and sending an email to the owner of the account

Issue?

As we know, to show an error message using plugin, we have to use InvalidPluginExecutionException.

However, when we use InvalidPluginExecutionException it rollbacks any additional code executed on ‘Pre-operation’ and ‘Post-operation’ irrespective of it being ‘Synchronous’ or ‘Asynchronous’.

The need over here was not just to throw an error and notify the user but also send an email/log an error in the background.

Throwing an exception in the plugin registered on “Pre-Operation” or “Post-Operation” would also prevent the additional logging of the error message that was required.

Solution:

We found an alternate way to achieve this by registering plugin on “Pre-Validation” operation.

Pre-validation operation allows processing the actions written, before throwing invalid plugin exception.

We added a new plugin step and registered it as seen in the below screenshot:

Plugin Pre-validation operation to Show an Error Message

We have also written the code mentioned below to process actions before throwing invalid plugin exception:

try{
bool isApproved = false;
                if (context.MessageName.ToLower() == "associate")
                {
                    //validate relationship
                    if (context.InputParameters.Contains("Relationship"))
                    {
                       string relationship = context.InputParameters["Relationship"].ToString();

                    }
                    //check relationship
                    if (relationship != "relationshipname")
                    {
                        return;
                    }
                    
//business logic execution

if (!isApproved)
                        {
			//send email code

			//throw error to prevent association

			throw new InvalidPluginExecutionException(" Account Status Reason needs to be Approved !!");	
                 }

                    }
                }
}

 

Conclusion: Code in ‘Pre-validation’ is executed outside the transaction and therefore any updates made to the database in this stage persists and can therefore be used for error logging mechanism that needs to be implemented.



*****************************************************************


As per the Event Execution Pipeline for plugins in Dynamics 365, here we will look at a pre-validation plugin.

These plugins execute before the main system operation and outside the database transaction. Pre-validation runs before validation occurs. You can also modify values at this stage, though this may be generally done in pre-operation. If you are creating a record, as the record is not created at this point, you will not have a record GUID.

In Visual Studio, create a new Class Library:

Through NuGet, add the latest Microsoft.CrmSdk.CoreAssemblies:

Add:

using Microsoft.Xrm.Sdk;

We will call our class UpdateAccount, IPlugin with an Execute method:

Add the code. We will update the fax number of the account:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
 
namespace Carl.PluginPreValidationSample
{
    public class UpdateAccount : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
 
            if (context.InputParameters.Contains("Target") &amp;&amp; context.InputParameters["Target"] is Entity)
            {
                Entity entity = (Entity)context.InputParameters["Target"];
 
                if (entity.LogicalName == "account")
                {
                    if (entity.Attributes.Contains("fax") == false)
                    {
                        entity.Attributes.Add("fax", "1112221111");
                    }
                }
            }
        }
    }
}

Sign the assembly:

Now open the Plugin Registration Tool and register:

Click Register Selected Plugins:

Click Register New Step. We make this an update to account, pre-validation:

Note as this is pre-validation, it needs to be synchronous and cannot be asynchronous.

Now we can test this. On an account record, insert a fax number:

After saving and refreshing, we can see the fax has been overwritten by our plugin:

We can see if we run this in the debugger, the Execution Pipeline stage is 10 (pre-event, pre-validation). As this executes outside the database, the IsInTransaction is false:

 

No comments:

Post a Comment

Git Basic working