Thursday, September 29, 2011

Difference between Parent and Child Pipeline Plugin in MS CRM 4.0

Stage of Execution:
Pre-Stage: (synchronous) called before the write to the database.
The main reasons to use a Pre-Stage of Execution are synchronous in nature:
  • Modify data before it is written to the database.
  • Abort the action being taken
  • Server Side Validity checking
Post-Stage: (synchronous or asynchronous)
Use the Post-Stage of Execution whenever you don't need to use Pre-Stage.
If you don't want the user to wait for the process to finish and there is no race condition use asynchronous.

Data Images:
Pre-Image: Get the image of the record as is stored in the SQL database before the CRM Platform action has been performed

Post-Image: Returns the image of the record after the CRM Platform action has been performed

Pipeline:
Parent Pipeline:
This is the pipeline that is the most common and there are no restrictions imposed in a parent pipeline.
Child Pipeline: This is the pipeline that causes the most confusion and there are limitations that vary with Stage and Execution Mode.
Sometimes a child pipeline is required to trap the event you need, and sometimes you need to trap both the parent and child pipeline for the same entity, message and stage
Have a look on following example for getting difference between Parent and Child Pipeline:

We can create “Quote” in following ways:
1.    Sales->Quotes->New
2.    Sales->Opportunity->(Open Opportunity)->Quotes->New Quote
Let us take first scenario Sales->Quotes->New
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.SdkTypeProxy.Metadata;
using Microsoft.Crm.Sdk.Metadata;
using System.Web.Services;
using Microsoft.Win32;

namespace TestQuotePlugin
{
    public class QuotePlugin : IPlugin
    {
        public void Execute(IPluginExecutionContext context)
        {
            ICrmService crmService = (ICrmService)context.CreateCrmService(true);
     IMetadataService metaData = context.CreateMetadataService(true);
     lead ld = new lead();
            ld.subject = "Test Subject";
            ld.firstname = "Test FirstName";
            ld.lastname = "Test LastName";
            ld.companyname = "Test Company";
            crmService.Create(ld);
        }       
    }
}

Register above plug-in as following:

Create new Quote from Sales -> Quotes -> New, then it will work and create a new Lead.

But when you create a Quote from
Sales->Opportunity->(Open Opportunity)->Quotes->New Quote then it will not work.

So you have to register a new child pipeline plug-in as following:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.SdkTypeProxy.Metadata;
using Microsoft.Crm.Sdk.Metadata;
using System.Web.Services;
using Microsoft.Win32;

namespace TestQuotePlugin
{
    public class QuotePlugin : IPlugin
    {
        public void Execute(IPluginExecutionContext context)
        {
            CrmService crmService = CreateCrmService(context);    
     lead ld = new lead();
            ld.subject = "Test Subject";
            ld.firstname = "Test FirstName";
            ld.lastname = "Test LastName";
            ld.companyname = "Test Company";
            crmService.Create(ld);
        }   

        private static CrmService CreateCrmService(IPluginExecutionContext context)
        {
            CrmAuthenticationToken token = new CrmAuthenticationToken();
            token.AuthenticationType = AuthenticationType.AD;
            token.OrganizationName = context.OrganizationName;

            CrmService crmService = new CrmService();
            crmService.UseDefaultCredentials = true;
            crmService.Url = (string)(Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\MSCRM").GetValue("ServerUrl")) + "/2007/crmservice.asmx";
            crmService.CrmAuthenticationTokenValue = token;
            return crmService;
        }   
    }
}


So now when you create a Quote from

Sales->Opportunity->(Open Opportunity)->Quotes->New Quote then it will work.

Hard Coded Restrictions:
A CrmService running Synchronously in a child pipeline is limited to the following:
·  Create
·  Delete
·  Update
·  RetrieveExchangeRate
However a child plugin running in Asynchronous Execution Mode is not limited this way.
Those 4 allowed actions are hard coded by MS whenever the plugin is executed inside a transaction, and it appears that all synchronous child pipeline events occur inside a transaction.
However you can do a query in child pipeline if it is registered as asynchronous.
In review:
·  Use ICrmService for all parent pipelines when at all possible.
·  Use CrmService for child pipelines in asynchronous execution mode.
·  There is very limited functionality allowed with CrmService for any plugin registered in a synchronous child pipeline
·  Querying CRM data in a plug-in registered as a synchronous Pre Create in a child process is currently unsupported. (i.e. direct SQL access)