web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Customer experience | Sales, Customer Insights,...
Answered

Custom duplication rule with plugin

(0) ShareShare
ReportReport
Posted on by 1,243

Hi,

I had a requirement to create custom duplication rule using plugin.Is that possible to display the screen below if there is duplication record detected by the plugin?

duplicate-record-screen.jpg

Thanks.

Regards,

Teh

I have the same question (0)
  • Suggested answer
    cloflyMao Profile Picture
    25,210 on at

    Hi Teh,

    You can create your own custom duplication rule by QueryExpression class with some criterias,

    if the retrieved result length is greater than 0, then display the duplicated record and throw an custom error to prevent creation or update.

    1. Create a plug-in library and register it to Dynamics environment.

    https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/tutorial-write-plug-in

    2. My sample code: if new created lead last name could match to existing lead, then throw an exception error.

    using System;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Query;
    
    namespace DynamicsPlugins
    {
        public class plugin1 : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
                IOrganizationServiceFactory servicefactory =
                    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service =
                    servicefactory.CreateOrganizationService(context.UserId);
    
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    Entity entity = (Entity)context.InputParameters["Target"];
                    if (entity.LogicalName != "lead")
                    {
                        return;
                    }
                    if (context.Depth > 1)
                    {
                        return;
                    }
                    try
                    {
                        if (entity.Attributes.Contains("lastname"))
                        {
                            string lastname = entity.GetAttributeValue("lastname").ToString();
                            QueryExpression query = new QueryExpression("lead");
                            query.ColumnSet = new ColumnSet("fullname", "emailaddress1", "createdon");
                            query.Criteria.AddCondition("lastname", ConditionOperator.Equal, lastname);
                            EntityCollection collection = service.RetrieveMultiple(query);
                            if (collection.Entities.Count > 0)
                            {
                                // display customized exception in dialog in UCI
                                throw new InvalidPluginExecutionException("Duplicated record exists!\n"   collection[0].Attributes["fullname"]);
                                    //"Full name: "   collection[0].Attributes["fullname"]   "  "  
                                    //"Email: "   collection[0].Attributes["emailaddress1"]   "  "   email field is required to has value(not null)
                                    //"Created Time: "   collection[0].Attributes["createdon"]);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        tracingService.Trace("Error of Plugin: {0}", ex.ToString());
                        throw;
                    }
                }
    
            }
        }
    }

    Above code is modified from the code in this article:

    https://mylearnings26.wordpress.com/2018/06/26/detect-duplicate-records-in-ms-crm-using-plugin-c/

    I made a change to origin code:

    " throw new Exception("Duplicates found !!!"); " snippet won't display a dialog with custom exception in UCI,

    so I changed it to " throw new InvalidPluginExecutionException("Duplicated record exists!\n" collection[0.Attributes["fullname"); "

    Also, I added tracing service code for debug.

    3. Trigger of my demo plugin: (when a lead is created.)

    pastedimage1585047346279v2.png

    4. Result of test:

    pastedimage1585047307903v1.png

    However, you may find that the dialog is too simple without rich format and hasn't too much information.

    That because Duplicate Records Detected dialog could be only invoked by system duplicate detection process.

    To display more information with custom duplication rule, you need to do more jobs:

    1. Check whether all of retrieved fields of the matching record are not null.(have value), and handle this situation in C# code.

    2. You might create a list and covert it to string if multiple duplicated records exist.

    In a word, that's what a custom duplicate rule could provide with.

    Another option is that you could call RetrieveDuplicatesRequest for context entity in your plugin, it'll use published duplicate rules to do match job.

    https://www.inogic.com/blog/2015/11/use-retrieveduplicaterequest-in-dynamics-crm/(But it might not match your requirement about custom duplication rule, it's still system rules.)

    Regards,

    Clofly

     

  • Venedict Profile Picture
    1,243 on at

    Hi Clofly,

    I understand how to use plugin to create custom rule. Normally we would throw an exception to the user. But is that possible we can pop up the same duplicate record screen as per standard duplication rule checking function as in my 1st post?

    I did read the retrieveduplicaterequest using sdk, but it still based on standard rule correct?

    Thanks.

    Regards,

    Teh

  • cloflyMao Profile Picture
    25,210 on at

    Hi Teh,

    Yes, duplicate dialog (in your 1st post) could be only invoked by standard rule, and integrated method(retrieveduplicaterequest) in SDK all use standard rule.

    Could you share me what limitation have you encountered while using standard rules? thus you want a custom rule for deeper duplicate detection?

    And do you think "throw an exception" dialog is not so friendly compared with standard one?

    If so, you could design a web resource which has similar looks to standard duplicate detection dialog, convert your custom duplicate rules into javascript version, (find duplicate records with fetchxml or Xrm.WebApi.retrieveMultipleRecords), then fire detection function at form's onSave event.

    web resource: display duplicated records in HTML table.

    embbed javascript in entity form: 

    1. (disable standard rules) query duplicated records by fetchxml or retrieveMultipleRecords, if result lenght is greater than 0,

    open web resouce with with new client api: navigateTo and pass retrieved ID as parameter.

    2. In web resource, do a second retriving job to display more information from duplicated records and render a table.

    You should achieve both merge and delete functions on same page.

    3. Bind save event to custom button.

    Regards,

    Clofly

  • Venedict Profile Picture
    1,243 on at

    Hi Clofly,

    The limitation as such if I wanted to cross check First Name with Last Name, Last Name with First Name, or comparing name like John Doe against John Smith Doe.

    Yes, the throw an exception definitely is not friendly compared to standard one, as standard at least will pop up a screen and let user decide the next action. The throw exception is just prompt potential duplication records.

    So from your explanation above, for custom duplication rule, we have to write our own action, am I right?

    Thanks.

    Regards,

    Teh

  • Suggested answer
    cloflyMao Profile Picture
    25,210 on at

    Hi Teh,

    Yes, you're right.

    Situation of your is more complex than standard rule, so you should write your own function.

    My thought for your requirement is that you could reverse new record's fullname field value and query potential duplicate records by Web API with original fullname string and reversed fullname string:

    $select=fullname,firstname,lastname,emailaddress1,createdon&$filter=contains(fullname,'Mao Clofly') or contains(fullname,'Clofly Mao')

    pastedimage1585206213412v2.png

    It's easy to build Web API request with CRM Rest Builder, and render a HTML table which has similar look to standard rule dialog.

    You can also extend your web resouce with Merge function(while it's not available in standard rule dialog.) by Merge action.

    Example for how to run the action:

    https://butenko.pro/2017/03/21/merge-records-using-webapi/

    Regards,

    Clofly

  • Venedict Profile Picture
    1,243 on at

    Hi Clofly,

    I was trying to use your sample code in the 2nd post to create a custom plugin and check again contact entity for duplicate record.

    I noticed that if I manual create/update record, it will prompt the error. But when I try to data import function, it seem the plugin is not working. The plugin I just check the lastname column.

    In my past experience, the plugin should triggered regardless the data was create/update through the form itself or csv file import.

    Can you test do you experience the same thing for data import in marketing app? 

    Thanks.

    Regads,
    Teh

  • cloflyMao Profile Picture
    25,210 on at

    Hi Teh,

    Thanks for your feedback.

    I got off work now, I'll test it for you tomorrow.

    In addition, would you like to do it with javascript?

    Regards,

    Clofly

  • Venedict Profile Picture
    1,243 on at

    Hi Clofly,

    Thanks for your prompt reply. I would prefer plugin instead of javascript, as javascript looks a little bit complex to me compare to sdk.

    Thanks.

    Regards,

    Teh

  • Venedict Profile Picture
    1,243 on at

    Hi Clofly,

    Are you able to test the data import function?

    Thanks.

    Regards,

    Teh

  • cloflyMao Profile Picture
    25,210 on at

    Hi Teh,

    I have tested the function, and also encountered your issue.

    I'm trying to find a solution to handle it.

    Regards,

    Clofly

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Congratulations to our 2025 Community Spotlights

Thanks to all of our 2025 Community Spotlight stars!

Leaderboard > Customer experience | Sales, Customer Insights, CRM

#1
ManoVerse Profile Picture

ManoVerse 168 Super User 2026 Season 1

#2
NeerajPawar Profile Picture

NeerajPawar 65

#3
Jimmy Passeti Profile Picture

Jimmy Passeti 51 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans