CRM2011 Plugin InputParameter and OutputParameter Helper

Download: CRM 2011 Plugin Parameter Wrapper Generator (1.0.1.412)

Every time I am asked to write a plugin using one of the less common plugin messages, I silently wish that I didn’t have to trawl through the SDK and then access the InputParameters and OutputParameters collection through a DataCollection<string, object> collection. I usually end up deploying the plugin several times due to casting parameters to the wrong type or accessing parameters that just don’t exist. I know that there are several sources I could use to avoid this but lets face it – intelli-sense made us lazy.

So, the other day I’d had enough and created a tool that generates a helper file for plugin entity messages that gives me strongly typed access to all parameters in each plugin’s InputParameters and OutputParameters collection in C# or VB.Net.

The generated helper file includes a namespace for each plugin message and a class for each of the InputParameters and OutputParameters collection. Every parameter in the collection has a Contains<ParameterName> and a Get<ParameterName> method that both expect the Microsoft.Xrm.Sdk.IPluginExecutionContext passed to them. The Contains<ParameterName> method returns a boolean value indicating whether the parameter exists and the Get<ParameterName> method gets the strongly typed value of the parameter.

AccountPreCreate.cs (below) shows the use of the Xrm.Core.Helpers.Plugins.Create helper class. Because there is a namespace per message type, I can include the relevant namespace in the using statements in my plugin class and then simply call the Contains and Get methods on the InputParameters and OutputParameters classes.

namespace Client.Plugins
{
    using System;
    using Microsoft.Xrm.Sdk;
    using Xrm.Core.Helpers.Plugins.Create;

    /// <summary>
    /// AccountPreCreate Plugin.
    /// </summary>
    public class AccountPreCreate : Plugin
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AccountPreCreate"/> class.
        /// </summary>
        public AccountPreCreate() : base(typeof(AccountPreCreate))
        {
            this.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Create", "account", new Action<LocalPluginContext>(this.ExecuteAccountPreCreate)));
        }

        /// <summary>
        /// Executes the plug-in.
        /// </summary>
        /// <param name="localContext">The <see cref="LocalPluginContext"/></param>
        protected void ExecuteAccountPreCreate(LocalPluginContext localContext)
        {
            IPluginExecutionContext context = localContext.PluginExecutionContext;
            if (InputParameters.ContainsTarget(context))
            {
                Entity target = InputParameters.GetTarget(context);
                //Do something with the target
            }
        }
    }
}

In order to generate the helper classes, I needed to get the list of plugin parameters for all messages. The SDK was not very helpful there and while I was able to find a complete list for CRM4 here, no such thing seems to exist for CRM2011. Eventually, I decided to generate my own list using the following SQL statements in the CRM database and used them in the generator to generate the helper classes.

SELECT DISTINCT REPLACE(mreq.Name, '{Entity.PrimaryEntityName}', ''), mrf.Name, mrf.ClrParser, ISNULL(mreq.PrimaryObjectTypeCode, 0)
FROM SdkMessageRequestField mrf
INNER JOIN SdkMessageRequest mreq ON mrf.SdkMessageRequestId = mreq.SdkMessageRequestId
WHERE NOT mrf.ClrParser LIKE '%Microsoft.Crm.Sdk%'
AND NOT mrf.ClrParser LIKE '%Microsoft.Crm.Sdk.Reserved%'
ORDER BY 1, 2, 4 DESC
SELECT DISTINCT REPLACE(mreq.Name, '{Entity.PrimaryEntityName}', ''), mrf.Value, mrf.ClrFormatter, ISNULL(mreq.PrimaryObjectTypeCode, 0)
FROM SdkMessageResponseField mrf
INNER JOIN SdkMessageResponse mres ON mrf.SdkMessageResponseId = mres.SdkMessageResponseId
INNER JOIN SdkMessageRequest mreq ON mres.SdkMessageRequestId = mreq.SdkMessageRequestId
WHERE NOT mrf.ClrFormatter LIKE '%Microsoft.Crm.Sdk%'
AND NOT mrf.ClrFormatter LIKE '%Microsoft.Crm.Sdk.Reserved%'
ORDER BY 1, 2, 4 DESC

Where the statements above select more than one instance of a message (one with a primary object type code and the other without), the tools assume that the one with the primary object type code is the correct one.

I have obviously not tested every single plugin message input/output parameter so please let me know if there is a message/parameter missing, an extra message/parameter or a parameter with the incorrect data type etc.