Tag Cloud

CRM 2011 (161) CRM 4.0 (144) C# (116) JScript (109) Plugin (92) Registry (90) Techpedia (77) PyS60 (68) WScript (43) Plugin Message (31) Exploit (27) ShellCode (26) FAQ (22) JavaScript (21) Killer Codes (21) Hax (18) VB 6.0 (17) Commands (16) VBScript (16) Quotes (15) Turbo C++ (13) WMI (13) Security (11) 1337 (10) Tutorials (10) Asp.Net (9) Safe Boot (9) Python (8) Interview Questions (6) video (6) Ajax (5) VC++ (5) WebService (5) Workflow (5) Bat (4) Dorks (4) Sql Server (4) Aptitude (3) Picklist (3) Tweak (3) WCF (3) regex (3) Config (2) LINQ (2) PHP (2) Shell (2) Silverlight (2) TSql (2) flowchart (2) serialize (2) ASHX (1) CRM 4.0 Videos (1) Debug (1) FetchXml (1) GAC (1) General (1) Generics (1) HttpWebRequest (1) InputParameters (1) Lookup (1) Offline Plug-ins (1) OutputParameters (1) Plug-in Constructor (1) Protocol (1) RIA (1) Sharepoint (1) Walkthrough (1) Web.config (1) design patterns (1) generic (1) iframe (1) secure config (1) unsecure config (1) url (1)

Pages

Wednesday, December 12, 2012

CRM 4.0 Plug-in Stages, Pipelines and Execution Modes


 

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.
Triggering Pipeline:
The triggering pipeline is a little less obvious in nature and has an impact on what functionality that you can use in your plugin.
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.
Example: Change the quotenumber in the Pre-Stage for the Create of a Quote.

The quotenumber is a field that the CRM web service will not allow you to change after it is written to the database so you need to use the Pre-Stage and modify the context Entity before the end of the Execute method as shown below.
var entity = (DynamicEntity)context.InputParameters.Properties[ParameterName.Target];  // . . . retrieve data to populate number . . .  // Set value before it is written to the database  if( entity.Properties.Contains(numberField)) {     entity.Properties.Remove(numberField); }  var prop = new StringProperty(numberField, newNumber); entity.Properties.Add(prop);
So far so good. This will work in any Pre-Create pipeline!
You can create a Quote in a few ways.
  • Sales -> Quotes -> New
  • (open an Account) -> Quotes -> New Quote
  • Sales -> Opportunities (open an opportunity) -> Quotes -> New Quote
Do you think that Creating a Quote always happens in the same pipeline?
Since you are an efficient plugin developer and are using the ICrmService and dynamic entities to access CRM data because it is pre-authenticated and fast. You retrieve some information to help create the number.
ICrmService service = context.CreateCrmService(true); retrieved = (RetrieveMultipleResponse)service.Execute(retrieve);
You register your plugin using the handy plugin registration tool for the Quote entity with the following settings:
  • Create
  • Pre Stage
  • Synchronous
  • Parent Pipeline
 CreateQuoteParent
You create your Quote from Sales -> Quotes -> New and it works!
However, in many business processes the user will create a Quote from an opportunity so it will inherit opportunityproduct information.
Now you create your quote from Sales -> Opportunities (open an opportunity) -> Quotes -> New Quote and for some reason your plugin did not fire. That is because this quote was created in a child pipeline.
The entire QOI chain also occurs in a child pipeline. If you create an order from a quote or invoice from an order it is happening in a child pipeline. There are other places that this occurs as well like creation of an account or contact from a lead.

You are in a child pipeline, now what ?

The first thing that you might try is to take your existing plugin and register it against the child pipeline, but it won't work. The ICrmService is not available to you in a child pipeline.
If you downloaded the plug-in template for CRM, you have probably seen the following method, which is what you need to use in a child pipeline.
/// <summary> /// Creates a CrmService proxy for plug-ins that execute in the child pipeline. /// </summary> /// <param name="context">The execution context that was passed to the plug-ins Execute method.</param> /// <param name="flag">Set to True to use impersontation.</param> /// <returns>A CrmServce instance.</returns> private static CrmService CreateCrmService(IPluginExecutionContext context, Boolean flag) {     var authToken = new CrmAuthenticationToken { AuthenticationType = 0, OrganizationName = context.OrganizationName, CallerId = (flag ? context.UserId : context.InitiatingUserId) };      var corToken = new CorrelationToken { CorrelationId = context.CorrelationId, CorrelationUpdatedTime = context.CorrelationUpdatedTime, Depth = context.Depth };      var regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\MSCRM", false);      var service = new CrmService     {         CrmAuthenticationTokenValue = authToken,         UseDefaultCredentials = true,         Url = String.Concat(regkey.GetValue("ServerUrl").ToString(), "/2007/crmservice.asmx"),         CorrelationTokenValue = corToken     };      return service; }
You may find another method called GetCrmProxyUsingEndpointUrlInChildPipeline. It is essentially the same.
There is a comment in the plugin template that doesn't tell the whole story.
// For a plug-in running in the child pipeline, use this statement. // CrmService crmService = CreateCrmService(context, true);
What it doesn't mention is that what you are allowed to do with that service depends on what your execution mode is.
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 very unsupported. (ie. direct SQL access)

How to add configuration parameters to plugins in CRM 2011



How to add configuration parameters to plugins in CRM 2011


When you design plugins, you often need an input parameter or a configuration for the plugin execution which can be easily updated without having to re-compile and/or re-register the plugin. For example, I have a plugin that sends a request to a SharePoint web service and I would like the endpoint URL for the web service to be configurable. In that case you have the following options:

1. Use a "Configuration" custom entity
This is perhaps the most popular method but it can be expensive to maintain. You can create a custom entity containing the configuration information so the plugin will read the data in the custom entity by retrieving the record each time it executes.

PROS:

  • Easy to update the value (can be done using the CRM UI).
  • Can configure privileges to control who has access to the configuration entity.
CONS:
  • Configuration is data instead of metadata, therefore, the configuration data cannot be transported with the solution. You will need to create the configuration record in each environment.
  • You might need to control that only one configuration entity can be created.


2. Use the plugin step "Configuration"
When you register a plugin step, there is a field where you can specify some configuration parameters for the plugin execution:
image
Then in the Constructor of your plugin class you will get the configuration value which you can use later in the Execute method:
public abstract class BasePlugin : IPlugin
{
    private string _secureConfig = null;
    private string _unsecureConfig = null;

    public BasePlugin(string unsecureConfig, string secureConfig)
    {
        _secureConfig = secureConfig;
        _unsecureConfig = unsecureConfig;
    }

    public void Execute()
    {
        // Use the configuration here
    }
}

PROS:
  • The step configuration is solution-aware so it will be automatically transported with the plugin step.
CONS:
  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).
  • the configuration is just an attribute of the plugin step so you cannot control privileges on the configuration independently from privileges on plugin step entity.


3. Use the plugin step "Secure Configuration"
This is similar to the step Configuration except that the configuration data is stored in a separate entity which can be secured.
PROS:
  • The configuration data can be secured as any other entity using the CRM security model. This is useful when the configuration contains sensitive information such as passwords.
CONS:
  • Secure configuration is not solution aware so you will need to configure it for each environment.
  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).


4. Use a Web Resource
You can store configuration information in web resources, for example you might have some XML configuration stored in a web resource and have your plugin read the web resource each time it executes.

PROS:
  • Web resources are solution aware and the GUID is preserved across environments so you can hardcode the web resource GUID in your plugin code. You can transport the web resource and the plugin in the same solution.
  • Can be easily updated using the CRM UI.
CONS:
  • You cannot secure the configuration since it depends on the web resource access privileges and most users will need at least read access to web resources.

How to add configuration parameters to plugins in CRM 2011


 
How to add configuration parameters to plugins in CRM 2011

When you design plugins, you often need an input parameter or a configuration for the plugin execution which can be easily updated without having to re-compile and/or re-register the plugin. For example, I have a plugin that sends a request to a SharePoint web service and I would like the endpoint URL for the web service to be configurable. In that case you have the following options:

1. Use a "Configuration" custom entity
This is perhaps the most popular method but it can be expensive to maintain. You can create a custom entity containing the configuration information so the plugin will read the data in the custom entity by retrieving the record each time it executes.

PROS:

  • Easy to update the value (can be done using the CRM UI).
  • Can configure privileges to control who has access to the configuration entity.
CONS:
  • Configuration is data instead of metadata, therefore, the configuration data cannot be transported with the solution. You will need to create the configuration record in each environment.
  • You might need to control that only one configuration entity can be created.


2. Use the plugin step "Configuration"
When you register a plugin step, there is a field where you can specify some configuration parameters for the plugin execution:
image
Then in the Constructor of your plugin class you will get the configuration value which you can use later in the Execute method:
public abstract class BasePlugin : IPlugin
{
    private string _secureConfig = null;
    private string _unsecureConfig = null;

    public BasePlugin(string unsecureConfig, string secureConfig)
    {
        _secureConfig = secureConfig;
        _unsecureConfig = unsecureConfig;
    }

    public void Execute()
    {
        // Use the configuration here
    }
}

PROS:
  • The step configuration is solution-aware so it will be automatically transported with the plugin step.
CONS:
  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).
  • the configuration is just an attribute of the plugin step so you cannot control privileges on the configuration independently from privileges on plugin step entity.


3. Use the plugin step "Secure Configuration"
This is similar to the step Configuration except that the configuration data is stored in a separate entity which can be secured.
PROS:
  • The configuration data can be secured as any other entity using the CRM security model. This is useful when the configuration contains sensitive information such as passwords.
CONS:
  • Secure configuration is not solution aware so you will need to configure it for each environment.
  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).


4. Use a Web Resource
You can store configuration information in web resources, for example you might have some XML configuration stored in a web resource and have your plugin read the web resource each time it executes.

PROS:
  • Web resources are solution aware and the GUID is preserved across environments so you can hardcode the web resource GUID in your plugin code. You can transport the web resource and the plugin in the same solution.
  • Can be easily updated using the CRM UI.
CONS:
  • You cannot secure the configuration since it depends on the web resource access privileges and most users will need at least read access to web resources.