·
3 min read

Storing Configuration Data for Microsoft Dynamics CRM Plug-ins

CRM MVP Mitch Milam returns as a guest blogger. 

One of the benefits to the plug-in architecture of CRM 4.0 is the ability to store plug-ins in the CRM database so they may be used by multiple CRM servers. This introduces a slight complication regarding the storage of configuration information. Because the plug-in assembly doesn’t reside on the disk the normal method of using a .config file located with the assembly no longer works.

Luckily, the plug-in architecture solves this issue by allowing the developer to supply configuration information for each step executed by the plug-in.

Plug-in Configuration Architecture

As noted in the CRM SDK article, Writing the Plug-in Constructor, when creating your plug-in, you may define a constructor that passes two parameters to your plug-in: unsecure configuration and secure configuration:

   1: public class SamplePlugin : IPlugin
   2: {
   3:   public SamplePlugin(string unsecureConfig, string secureConfig)
   4:   {
   5:   }
   6: }

Both parameters are strings and may contain any configuration data, in any format, that you wish. For the purposes of this discussion, we will only be concerned with the unsecure configuration parameter.

Creating a Configuration Structure

Since most of us are familiar with the XML configuration provided by the standard Properties.Settings structure, I thought it would be a great idea to retain as much of that experience as possible so we can move code from a stand-alone test application to a plug-in with little difficulty.

Using an XML fragment that closely resembles the Settings section found in the .config file of a .Net assembly, we can create a similarly functional system for storing configuration data. Consider the following XML:

   1: <Settings>
   2:     <setting name="RetryCount">
   3:         <value>5</value>
   4:     </setting>
   5:     <setting name="TaskPrefix">
   6:         <value>This task was created on {0}.</value>
   7:     </setting>
   8:     <setting name="FirstRun">
   9:         <value>false</value>
  10:     </setting>
  11: </Settings>

As you can see, we have three settings which contain values that we would normally find in our .config file and which are used to configure our assembly. Using the Plug-in Registration Tool, we can add this information to the Unsecure Configuration field when registering a new step, as show by the figure below:

MitchCode

Plug-in Configuration Class

I created a simple class to extract values from an XML document for simple data types such as Guids, strings, Booleans, and integers, given the structure we discussed above:

   1: class PluginConfiguration
   2: {
   3:     private static string GetValueNode(XmlDocument doc, string key)
   4:     {
   5:         XmlNode node = doc.SelectSingleNode(String.Format("Settings/setting[@name='{0}']", key));
   6:
   7:         if (node != null)
   8:         {
   9:             return node.SelectSingleNode("value").InnerText;
  10:         }
  11:         return string.Empty;
  12:     }
  13:
  14:     public static Guid GetConfigDataGuid(XmlDocument doc, string label)
  15:     {
  16:         string tempString = GetValueNode(doc, label);
  17:
  18:         if (tempString != string.Empty)
  19:         {
  20:             return new Guid(tempString);
  21:         }
  22:         return Guid.Empty;
  23:     }
  24:
  25:     public static bool GetConfigDataBool(XmlDocument doc, string label)
  26:     {
  27:         bool retVar;
  28:
  29:         if (bool.TryParse(GetValueNode(doc, label), out retVar))
  30:         {
  31:             return retVar;
  32:         }
  33:         else
  34:         {
  35:             return false;
  36:         }
  37:     }
  38:
  39:     public static int GetConfigDataInt(XmlDocument doc, string label)
  40:     {
  41:         int retVar;
  42:
  43:         if (int.TryParse(GetValueNode(doc, label), out retVar))
  44:         {
  45:             return retVar;
  46:         }
  47:         else
  48:         {
  49:             return -1;
  50:         }
  51:     }
  52:
  53:     public static string GetConfigDataString(XmlDocument doc, string label)
  54:     {
  55:         return GetValueNode(doc, label);
  56:     }
  57: }

Putting PluginConfiguration to Work

Once we have our PluginConfiguration class added to our project, we need to modify the plug-in constructor to extract the values from our configuration string:

   1: public SamplePlugin(string unsecureConfig, string secureConfig)
   2: {
   3:     XmlDocument doc = new XmlDocument();
   4:     doc.LoadXml(unsecureConfig);
   5:
   6:     string TaskPrefix = PluginConfiguration.GetConfigDataString(doc, "TaskPrefix");
   7:     bool FirstRun = PluginConfiguration.GetConfigDataBool(doc, "FirstRun");
   8:     int RetryCount = PluginConfiguration.GetConfigDataInt(doc, "RetryCount");
   9: }

There is no automatic determination of data types so you will need to know which method to use to extract a specific value from the configuration data.

Conclusion

Today we’ve covered how to store configuration information used by a CRM plug-in within the CRM database itself. One of the items you may wish to remember is that each step executed by a plug-in has its own configuration information. If you are using the same configuration data for multiple steps, you will need to set the configuration values to be the same between steps or just insert configuration data that is necessary for a particular step to complete successfully.