I believe that you are experienced with the plugin registration and adding steps using plugin registration tool. But sometimes you may need to add/remove plugin steps programmatically.
Adding a plugin step means, creating a SdkMessageProcessingStep record in CRM.
Before creating a SdkMessageProcessingStep record you need to retrieve following.
- The message id.
/// <summary> /// Gets the message identifier. /// </summary> /// <param name="context">The context.</param> /// <param name="sdkMessageName">Name of the SDK message.</param> /// <returns> /// The message id. /// </returns> /// <exception cref="InvalidPluginExecutionException">No sdk messages found with the sdk message name.</exception> private static Guid GetMessageId(ServiceContext context, string sdkMessageName) { using (context) { // Gets the sdk message var sdkMessage = context.SdkMessageSet.Where(s => s.Name == sdkMessageName).FirstOrDefault(); // Throws an error if no sdk messages found. if (sdkMessage == null) { throw new InvalidPluginExecutionException(string.Format("No sdk messages found with the sdk message name '{0}'.", sdkMessageName)); } return sdkMessage.Id; } }
- The plugin type id.
/// <summary> /// Gets the plugin type identifier. /// </summary> /// <param name="context">The context.</param> /// <param name="assemblyName">Name of the assembly.</param> /// <param name="pluginTypeName">Name of the plugin type.</param> /// <returns> /// The plugin type id. /// </returns> /// <exception cref="InvalidPluginExecutionException">No plugin assemblies found with the assmbly name /// or /// No plugin types found with the plugin type and the assmbly name</exception> private static Guid GetPluginTypeId(ServiceContext context, string assemblyName, string pluginTypeName) { using (context) { // Gets the plugin assembly. var pluginAssembly = context.PluginAssemblySet.Where(p => p.Name == assemblyName).FirstOrDefault(); // Throws an error if no plugin assembly found with the name. if (pluginAssembly == null) { throw new InvalidPluginExecutionException(string.Format("No plugin assemblies found with the assmbly name '{0}'", assemblyName)); } var assemblyId = pluginAssembly.Id; // Gets the plugin type var pluginType = context.PluginTypeSet.Where(p => p.PluginAssemblyId.Id == assemblyId && p.TypeName == pluginTypeName).FirstOrDefault(); // Throws an error if no plugin types found. if (pluginType == null) { throw new InvalidPluginExecutionException(string.Format("No plugin types found with the plugin type '{0}' and the assmbly name '{1}'", pluginType.ToString(), assemblyName)); } return pluginType.Id; } }
- The sdk message filter id.
/// <summary> /// Gets the SDK message filter identifier. /// </summary> /// <param name="context">The context.</param> /// <param name="entityName">Name of the entity.</param> /// <returns> /// The message filter id. /// </returns> /// <exception cref="InvalidPluginExecutionException">No sdk message filters found for the entity.</exception> private static Guid GetSdkMessageFilterId(ServiceContext context, string entityName) { using (context) { // Gets the message id. Guid messageId = GetMessageId(context, ContextMessageName.Create); // Get the message filter. var sdkMessageFilter = context.SdkMessageFilterSet.Where(s => s.PrimaryObjectTypeCode == entityName && s.SdkMessageId.Id == messageId).FirstOrDefault(); // Throws an error if no message filters found. if (sdkMessageFilter == null) { throw new InvalidPluginExecutionException( string.Format("No sdk message filters found for the entity '{0}'", entityName)); } return sdkMessageFilter.Id; } }
Now we have the message id, plugin type id and the sdk message filter id.
We can define the assembly name and the plugin type name as properties.
/// <summary>
/// The assembly name
/// </summary>
private static string AssemblyName = "PluginSample.Plugins";
/// <summary>
/// The plugin type name
/// </summary>
private static string PluginTypeName = "PluginSample.Plugins.TestHandler";
With all the above things in hand, now following method can be used to add plugin steps programatically.
/// <summary>
/// Adds the plugin step.
/// </summary>
/// <param name="service">The service.</param>
/// <param name="entityLogicalName">The entity logical name.</param>
/// <param name="contextMessageName">Name of the context message.("Create", "Update", "Delete", "Associate", "Disassociate")</param>
public static void AddPluginStep(IOrganizationService service, string entityLogicalName, string contextMessageName)
{
using (var context = new ServiceContext(service))
{
var stepName = string.Format("PluginSample.Plugins.TestHandler: {0} of {1}", contextMessageName, entityLogicalName);
// Gets the message name.
var messageId = GetMessageId(context, contextMessageName);
// Gets the plugin type id.
var pluginTypeId = GetPluginTypeId(context, AssemblyName, PluginTypeName);
// Gets the sdk message filter id.
var sdkMessageFilterId = GetSdkMessageFilterId(context, entityLogicalName);
// Check the plugin step is already regiseterd and if not register the new step.
var sdkMessageProcessingStep = context.SdkMessageProcessingStepSet.Where(s => s.SdkMessageFilterId.Id == sdkMessageFilterId && s.EventHandler.Id == pluginTypeId).FirstOrDefault();
if (sdkMessageProcessingStep == null || sdkMessageProcessingStep.Id == Guid.Empty)
{
// Creates the sdk message processing step.
SdkMessageProcessingStep step = new SdkMessageProcessingStep
{
AsyncAutoDelete = false,
Mode = new OptionSetValue((int)SdkMessageProcessingStepMode.Synchronous),
Name = stepName,
EventHandler = new EntityReference(PluginType.EntityLogicalName, pluginTypeId),
Rank = 1,
SdkMessageId = new EntityReference(SdkMessage.EntityLogicalName, messageId),
Stage = new OptionSetValue((int)PipelineStage.PreOperation),
SupportedDeployment = new OptionSetValue((int)SdkMessageProcessingStepSupportedDeployment.ServerOnly),
SdkMessageFilterId = new EntityReference(SdkMessageFilter.EntityLogicalName, sdkMessageFilterId)
};
service.Create(step);
}
}
}
In the same manner we can remove the plugin step by deleting the SdkMessageProcessingStep record.
/// <summary>
/// Removes the plugin step.
/// </summary>
/// <param name="service">The service.</param>
/// <param name="entityLogicalName">The entity logical name.</param>
public static void RemovePluginStep(IOrganizationService service, string entityLogicalName)
{
using (var context = new ServiceContext(service))
{
// Gets the plugin type id.
var pluginTypeId = GetPluginTypeId(context, AssemblyName, PluginTypeName);
// Gets the message filter id.
var sdkMessageFilterId = GetSdkMessageFilterId(context, entityLogicalName);
// Filter the message processing step.
var sdkMessageProcessingStep = context.SdkMessageProcessingStepSet.Where(s => s.SdkMessageFilterId.Id == sdkMessageFilterId && s.EventHandler.Id == pluginTypeId).FirstOrDefault();
if (sdkMessageProcessingStep != null)
{
// Delete sdk message processing step.
service.Delete(SdkMessageProcessingStep.EntityLogicalName, sdkMessageProcessingStep.Id);
}
}
}
In above example I'm using the early bound classes. If you need late bound code examples, please let me know in comment section.