Featured image of post What is Unsecure/Secure Configuration on a Dynamics CRM/365 for Enterprise Plugin?

What is Unsecure/Secure Configuration on a Dynamics CRM/365 for Enterprise Plugin?

When working with applications day in, day out, you sometimes overlook something that is sitting there, staring at you in the face. It may be an important feature or an inconsequential piece of functionality, but you never really take the time to fully understand either way just what it is and whether it can offer any distinct benefits or assistance. I realised a great example of this when recently deploying some new Plug-ins into Dynamics CRM/Dynamics 365 for Enterprise (CRM/D365E). When you are setting up a new Step for your Plug-in, you are given the option of specifying anĀ Unsecure ConfigurationĀ andĀ Secure Configuration via a multi-line text box to the right of the window:

I was curious about just what these are and why it is not something that you ever really come across when you are first learning about Plug-in development with the application. I took a closer look at what these text boxes do and, as part of this week’s blog post, I wanted to share my findings and provide a demonstration of how they work in practice.

The Theoretical Bit: Unsecure/Secure Configuration Overview

Typically, when we want to get some juicy information relating to a piece of CRM/D365E functionality, we would turn to our good friends TechNet or MSDN. In this instance, however, there is no dedicated page that covers this topic in-depth. We must instead navigate to theĀ Write a Plug-in Constructor page to find dedicated information about how these work:

The Microsoft Dynamics 365 platform supports an optional plug-in constructor that accepts either one or two string parameters. If you write a constructor like this, you can pass any strings of information to the plug-in at run time.

These “one or two” parameters are the multi-line text boxes indicated above. Information is exposed as string objects within you C# code and you enable this feature within your code by specifying the following, SDK adapted constructor within your Plug-in class:

public MyPlugin(string unsecureString, string secureString)
{
  if (String.IsNullOrWhiteSpace(unsecureString) ||
      String.IsNullOrWhiteSpace(secureString))
  {
    throw new InvalidPluginExecutionException("Unsecure and secure strings are required for this plugin to execute.");
  }
  _unsecureString = unsecureString;
  _secureString = secureString;
}

As with anything, there are a number of important caveats to bear in mind with this feature. These can be gleaned via additional online sources:

In terms of use cases, the above articles highlight some potential scenarios that they are best utilised within. Perhaps the best example is for an ISV solution that requires integration with external web services to retrieve data that is then consumed by CRM/D365E. Credentials for these web services can be stored securely when the Plug-in is deployed via the use of Secure configuration parameters. Other than that, if you are developing a Plug-in for internal use, that is unlikely to be deployed/managed across multiple environments, then it is probably not worthwhile to look at utilising configuration parameters when you can just as easily specify these within your code.

Practice Makes (for) Perfect (Understanding)!

The best way to see how something works is by getting hands-on and seeing how it works in action. Let’s assume you wish to deploy a plugin that executes whenever a record is opened/viewed by any user across the platform. The plugin should update the First Name (firstname) and Last NameĀ (lastname) fields to match the value(s) in the Unsecure and Secure Configuration properties accordingly. The below plugin code will achieve these requirements:

using System;
using Microsoft.Xrm.Sdk;

namespace D365.BlogDemoAssets.Plugins
{
  public class PostContactRetrieve_PluginConfigurationTest : IPlugin
  {
    private readonly string _unsecureString;
    private readonly string _secureString;
    public PostContactRetrieve_PluginConfigurationTest(string unsecureString, string secureString)
    {
      if (String.IsNullOrWhiteSpace(unsecureString) ||
          String.IsNullOrWhiteSpace(secureString))
      {
        throw new InvalidPluginExecutionException("Unsecure and secure strings are required for this plugin to execute.");
      }
      
      _unsecureString = unsecureString;
      _secureString = secureString;
    }
    public void Execute(IServiceProvider serviceProvider)
    {
      // Obtain the execution context from the service provider.
      
      IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
      
      // Obtain the organization service reference.
      IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
      IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
      
      // The InputParameters collection contains all the data passed in the message request.
      if (context.InputParameters.Contains("Target") &&
          context.InputParameters["Target"] is EntityReference)
      {
        Entity contact = new Entity("contact", ((EntityReference)context.InputParameters["Target"]).Id);
        
        contact["firstname"] = _unsecureString;
        contact["lastname"] = _secureString;
        service.Update(contact);
      }
    }
  }
}

When deploying the plug-in using the Plugin Registration Tool, we specify the step to execute on theĀ Retrieve message and to execute in the Pre-Operation Stage (otherwise the form will need to be refreshed to see the updated values!). We also need to specify our desired values for the First Name and Last Name fields in the appropriate Configuration fields. The Register New Step window should look similar to the below if configured correctly:

When we navigate into theĀ Jim Glynn (sample) ContactĀ record within CRM/D365E, we can see that the Plug-in has triggered successfully and updated the fields to match against the values specified on Step above:

We can also confirm that the appropriate error is thrown when one of the configuration properties is missing a value, by modifying our Plug-in step and attempting to reload our sample Contact record:

Can you spot what’s missing? šŸ™‚
Can you spot whatā€™s missing? šŸ™‚

By clickingĀ Download Log File, we can view the error message specified as part of the InvalidPluginExecutionException call. Below is a modified excerpt of the ErrorDetails XML that is generated:

<InnerFault>
  <ActivityId>ed4a2021-9c87-4f06-a493-6d804676bf96</ActivityId>
  <ErrorCode>-2147220891</ErrorCode>
  <ErrorDetails xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>Unsecure and secure strings are required for this plugin to execute.</Message>
  <ExceptionSource i:nil="true" />
  <InnerFault i:nil="true" />
  <OriginalException i:nil="true" />
  <TraceText i:nil="true" />
</InnerFault>

Conclusions or Wot I Think

It is impossible to become what I would like to term a “pub quiz champion” in CRM/D365E; what I mean by this is that I would defy anyone to rattle off every little detail and fact about the entire platform. As with any pub-quiz, those that do may more than likely end up cheating by having their phone out. With this metaphor in mind, I think Plug-in configuration properties would be an excellent topic for a quiz of this nature. As mentioned previously, it is not something that I was ever made aware of when starting to learn about Plug-in development and is not a feature touted regularly within the online community. Perhaps this is because of its very specific and limited application - although it is handy to have at our disposal, I think its usage is really only targeted towards those who are developing solutions that are deployed across multiple environments AND require the need to store configuration properties for external URL’s/web services in a compact and secure manner. Therefore, if you are currently having to use a custom entity within the application to store this type of information, it would make sense to reduce the footprint of your solution within the application itself and make the appropriate changes to use Secure configuration parameters instead. Using a bit of ingenuity (such as XML configuration parameters), you can achieve the same requirements without the need to customise the application unnecessarily.

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy