Monday, September 26, 2011

Problems with plugins on connection entity in CRM 2011

If you have registered a plugin on the connection entity, you might have experience some odd behaviour, such as the plugin getting called twice or the plugin to run under the SYSTEM user always. These are probably side effects of how connections are designed. Let me explain what happens behind the scenes when you create a connection so the problem will be more evident. Assume I create a connection between an opportunity and a user and I have a plugin that triggers on “Create” and “Update” of connection. The first thing to note is that when you “connect” two records you are in fact creating two connection records (one in each direction) so this happens sequentially inside the same transaction:
  1. The connection from the opportunity to the user is created (your plugin triggers here as expected). Temporarily the “relatedconnectionid” attribute is set to the id of the connection getting created.
  2. A reciprocal (corresponding) connection is created from the user to the opportunity which uses the corresponding connection role if available (your plugin triggers again because of the create, but the primary entity here is a different connection record)
  3. Once the second connection is created then the system updates the first connection record to set the RelatedConnectionId to the connection created in step 2 (your plugin triggers again because of the update)
In the previous example, my plugin ends up triggering 3 times, but I would like it to trigger only once since I am just connecting a user with an opportunity. In order to solve your problem, you need to first restrict your “update step” of the plugin to trigger only when selected attributes change in the connection, so you can make use of the Filtering Attributes from the plugin registration tool and you must as a minimum ensure that the RelatedConnectionId, modifiedon, modifiedby, modifiedonbehalfof and connectionid attributes are not checked so your plugin will not trigger in step 3 above. As a best practice, only select the attributes you really care about that must trigger the plugin when updated. This will prevent your plugin from triggering on step 3 above.

Now depending on your business logic you might want to avoid the plugin from triggering in step2 (or maybe not). If you do, you can use this trick inside your plugin to make sure that the plugin executes only for step1:

Entity creatingConnection = (Entity)context.InputParameters["Target"];
EntityReference relatedConnection = creatingConnection["relatedconnectionid"] as EntityReference;
if (relatedConnection != null && creatingConnection.Id != relatedConnection.Id)
{
    // Creating reciprocal connection
    // Return here if the plugin should not execute in step2.
}

The other tricky aspect of plugins with connections is that sometimes your plugin gets called in the context of the SYSTEM user (even if you specify Calling User or another user in the Plugin Registration Tool). This happens at least every time you have a plugin registered on “Delete” of connection. The only workaround that you have, is that from your plugin, when you create the CRM service you impersonate back the initiating user:

IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.InitiatingUserId);

I hope you find this helpful!

Monday, September 19, 2011

How to qualify a lead to a contact, account and/or opportunity using CRM 2011 process (workflow or dialog) ?

The CRM 2011 process designer has limited amount of functionality that it supports (create / update / set status), but if you wanted to add a workflow step to qualify a lead you would have to register your own plugin that implements the logic.

Fortunately, there is a solution that already implements this for you. I have extended the CRM 2011 Workflow Utilities to include a step to qualify leads. All you need to do is to download the managed solution from Codeplex and install it in your CRM organization (only supported in On Premise for now). Once you install the solution, you can go to your process designer and you will notice a “QualifyLead” step is now available:

image

When you insert the Qualify Lead step to your process you have to click the “Set Properties” button to configure how you want to qualify your lead. You have the following parameters:

  • Lead (the lead that you want to qualify).
  • Status of the lead after qualifying it (by default it will set the status to “Qualified”).
  • Create Contact (whether you wand to generate a contact for the qualified lead or not).
  • Create Account (whether you wand to generate an account for the qualified lead or not).
  • Create Opportunity (whether you wand to generate an opportunity for the qualified lead or not). If you specify “True” then you must also specify the opportunity customer and currency.
  • Opportunity Currency (use only if creating an opportunity).
  • Parent Account of Opportunity (use only if creating an opportunity).
  • Parent Contact of Opportunity (use only if creating an opportunity and no parent account is specified).

This is an example of how the step might be configured:

qualifyStep

 

The cool thing is that the custom step will output the entities that were generated by the qualification process so you can edit the generated entities in later steps of your process. For example, if I am qualifying a lead to an opportunity and then I need to edit the opportunity that was created I can just insert an update step after:

qualifyStep2

I hope you find this useful!

Wednesday, September 14, 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.