Monday, May 14, 2012

How to trigger a plugin for a many to many relationship

The blog will explain “ How to trigger a plugin for many to many (N:N) relationship. For this blog, I have created a new N:N relationship between account and contact entity. I am displaying this relationship just in account entity. The following screen shot is displaying the properties of the relationship.
a1
To trigger a plugin on association of 2 entities in a n:n relationship, we will use associate plugin message. I am using the developer’s toolkit for writing code from last 6 months. The problem is developer’s toolkit does not support “Associate” message. To create a plugin in developer’s toolkit, you need to choose primary entity and to use “Associate” message primary entity and secondary entity has to be “none”. There is a workaround to register  plugin step on “Associate” message. Here are the steps.
  1. Follow the steps in this blog on how to create a plugin using developer’s toolkit.
  2. In the step 12th of above-mentioned blog, replace the function “ExecutePostAccountCreate” with the following code
    protected void ExecutePostAccount(LocalPluginContext localContext)
    {
    
        if (localContext == null)
        {
            throw new ArgumentNullException("localContext");
        }
    
        // TODO: Implement your custom Plug-in business logic.
        // Obtain the execution context from the service provider.
        IPluginExecutionContext context = localContext.PluginExecutionContext;
        IOrganizationService service = localContext.OrganizationService;
        ITracingService tracingService = localContext.TracingService;
    
        try{
        // The InputParameters collection contains all the data passed in the message request.
        if (!context.InputParameters.Contains("Target")) { return; }
    
        EntityReference ef = (EntityReference)context.InputParameters["Target"];
        if (ef.LogicalName != "account") { return; }
    
        Relationship relationship = (Relationship)context.InputParameters["Relationship"];
        if (relationship.SchemaName != "new_account_contact") { return; }
    
        // Get Related Entities 
        EntityReferenceCollection re = (EntityReferenceCollection)context.InputParameters["RelatedEntities"];
    
        foreach (EntityReference rel in re)
        {
    
            Entity relatedEntity = service.Retrieve("contact", rel.Id, new ColumnSet("address1_city"));
            string city = (string)relatedEntity.Attributes["address1_city"];
            if (city=="Sydney")
            {
                //create a task
                Entity task = new Entity("task");
                task["subject"] = "A new contact from sydney is added to the account";
                task["regardingobjectid"] = ef;
                task["description"] = "A new contact from sydney is added to the account";
                // Create the task in Microsoft Dynamics CRM.
                service.Create(task);
    
            }
        }//endfor
        }
        catch (FaultException ex)
        {
            tracingService.Trace(ex.Message.ToString());
            throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
        }
    
    }//end function
    
  3. Add the following reference to your plugin class.
    using Microsoft.Xrm.Sdk.Query;
  4. The above code will create a task, when we add a contact with “address1_city” field equal to “Sydney” to an account. Just remember we are relating a contact to account using N:N relationship.
  5. Now change the RegisterFile.crmregister file  to register on an “Associate” message. Open the file and look for your plugin definition. It will look something like the following code.
    <Plugin Description="Plug-in to PostAccountCreate" FriendlyName="PostAccountCreate" Name="CRM2011PluginSeries.Plugins.PostAccountCreate" Id="420419bd-9fe7-404e-a5e3-afa582f21dd3" TypeName="CRM2011PluginSeries.Plugins.PostAccountCreate">
              <Steps>
                <clear />
                <Step CustomConfiguration="" Name="PostAccountCreate" Description="Post-Operation of Account Create" Id="b248f264-2b3f-e111-ab54-00155d32042e" MessageName="Create" Mode="Synchronous" PrimaryEntityName="account" Rank="1" SecureConfiguration="" Stage="PostOutsideTransaction" SupportedDeployment="ServerOnly">
                  <Images />
                </Step>
              </Steps>
            </Plugin>
  6. Now change the MessageName="Create" to MessageName="Associate" and PrimaryEntityName="account" to PrimaryEntityName="".
  7. Save the changes and deploy the plugin.
  8. If you get any errors during deployment, just deploy the plugin using plugin registeration tool. Don't forget to leave the "PrimaryEntityName" = none.
  9. Please provide some feedback

6 comments:

  1. what if you have two n:n relationships say account to contact and account to opportunity.. how do we specify which relationship to trigger?

    ReplyDelete
  2. It will trigger for all the relationships. You need to check the relationship name and write a code for that relationship.
    In the code above, the following line is checkingthe relationship is
    if (relationship.SchemaName != "new_account_contact") { return; }
    Change the relationship.SchemaName based on the relationship you want to run the code on.

    ReplyDelete
  3. Thanks a lot for your blog.
    I wasted 4 hours on this plugin ; trying to figure out how it would get triggered!!
    Your code makes it run perfectly!!
    Thanks :)

    ReplyDelete
    Replies
    1. I m glad it worked for you.
      Thanks.

      Delete
  4. Microsoft Dynamics CRM training will help you manage and prioritize your business goals, customize.we teach MS Dynamics CRM training and class available at Hyderabad.

    ReplyDelete
  5. EntityReferenceCollection re = (EntityReferenceCollection)context.InputParameters["RelatedEntities"];

    The above line of code only gets one record. So if i HAVE SELECTED MULTIPLE RECORDS TO BE ASSOCIATED The Plugin triggers for multiple times.

    Cant I have all the records in the EntityReferenceCollection and then process them.

    ReplyDelete