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.




10 comments:

  1. So which one would you prefer to use in a given project? don't answer "it depends :)"..

    I have been using the secure/unsecure config approach to all my plugins. It's not impossible to train the op team to maintain the value, but it would be easier to lock down the config entity and only them can go into crm and modify the values.

    ReplyDelete
  2. I personally always favor the unsecure configuration because it is solution aware. If I have security constraints I would use a custom entity or the secure config. I don't usually like the idea of defining an entity just to store plugin configuration, but I have done before though!

    ReplyDelete
  3. wow, you are the first one working sharepoint and crm integration in this way.

    I am wondering if you tried to send a web service call to sharepoint from within your plugin in a dynamics crm online 2011 version?

    thanks,

    ReplyDelete
  4. Yeah, there was a reason why the Out Of The Box Sharepoint integration was not good enough for me. I haven't tried it using CRM Online, but there should be no differences if your SharePoint web service is exposed to the internet.

    ReplyDelete
  5. Thanks for post. I think, Registery Entries should be a good alternative to that. What do u think ?

    ReplyDelete
  6. I'm agains registry entries because they depend on the server, what happens when you migrate servers? What if you have your deployment load-balanced with multiple servers? etc...
    Additionally, registry settings are not solution aware so deploying those can be a pain.

    ReplyDelete
  7. could you post some code to make sharepoint web service call in the execute method? I tried: I got - System.Net.WebException: The request failed with HTTP status 401: Unauthorized.

    at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall). My sharepoint site is https.

    using (Lists spLists = new Lists())
    {
    NetworkCredential networkCredential = new NetworkCredential();

    networkCredential.Domain = "{mydomain}";
    networkCredential.UserName = "{myaccount}";
    networkCredential.Password = "{mypassword}";

    spLists.Credentials = networkCredential;

    XmlNode getListResults = spLists.GetListCollection();

    listsCount = getListResults.ChildNodes.Count;
    }

    ReplyDelete
  8. Very informative thanks for summarizing. Have anyone tried to transform crmregister file?

    ReplyDelete