Microsoft Dynamics 365 has a flexible and extendable architecture, and can be integrated with other platforms. In integrations, it is common for data entered in Dynamics 365 to be shared with other platforms. Although Dynamics 365 text fields are flexible to save special characters, other platforms, that integrate with Dynamics 365, may not be as flexible. For example, when you integrate Dynamics 365 with SharePoint or One Drive, you may want to use the record’s name in Dynamics 365 to create the record’s document set or folder in SharePoint or One Drive . In such a case, Dynamics 365 fields being used by SharePoint or One Drive have to adhere to those platforms’ more restrictive special characters restrictions. The the invalid characters for OneDrive, OneDrive for Business on Office 365, and SharePoint Online are ” * : < > ? / \ | and for OneDrive for Business on SharePoint Server 2013 they are ~ . ” # % & * : < > ? / \ { | }.
The plugin in this post addresses this integration challenge by preventing users from saving restricted special characters in the text field(s) enabled text validation. When creating or updating a record in Dynamics 365, the plugin will check the text field(s), enabled for text validation, and strip out the characters that are not part of the permitted list characters.
To demonstrate this plugin’s functionality, we enabled text validation on the Account Name field for the Account entity. The validation rule applied by the plugin is: the Account Name field is only permitted to take in alphanumeric characters, space and 2 special characters i.e. underscore and hyphen. If a user enters any characters in the field, other than the permitted list of characters, they will be stripped out when they save the record. In the image below, a user entered both valid and invalid characters. Before Save:
When saving the record, the plugin stripped out the invalid characters from the text field, leaving only the permitted characters (i.e. alphanumeric characters, space and 2 special characters i.e. underscore and hyphen). After Save:
The Plugin
using System; using System.Text.RegularExpressions; using Microsoft.Xrm.Sdk; namespace ItsFascinating.Plugins.D365 { ////// This plugin removes non-approved special characters from the Account Name field of the Account entity /// public class AccountNameCharactersRemover : IPlugin { public void Execute(IServiceProvider serviceProvider) { string pluginMessageCreate = "create"; string pluginMessageUpdate = "update"; Entity primaryEntity = new Entity(); if (serviceProvider == null) { throw new ArgumentNullException("localContext"); } #region Plugin Setup Variables IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); #endregion #region Validation Prior Execution //Exist if plugin if it's not called at stage 20 of the excution pipeline if (context.Stage != 20) { tracingService.Trace("Invalid Stage: Stage = {0}", context.Stage); return; } //Only execute plugin if plugin message is Create or Update if (!(context.MessageName.ToLower().Equals(pluginMessageCreate) || context.MessageName.ToLower().Equals(pluginMessageUpdate))) { tracingService.Trace("Invalid Message: MessageName = {0}", context.MessageName); return; } #endregion #region Plugin Logic if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { try { primaryEntity = context.InputParameters["Target"] as Entity; // Display Name: "Account Name" | Database Name: "name" string accountNameFieldLogicalName = "name"; Object accountNameObj; string accountName, updatedAccountName; //Regex pattern for alphanumeric characters, space and 2 special characters i.e. underscore and hyphen string permittedCharacters = "[^0-9a-zA-Z_ -]+"; //Check if the specified attribute is contained in the internal dictionary before you you try to Get its value if (primaryEntity.Attributes.TryGetValue(accountNameFieldLogicalName, out accountNameObj)) { //Get value of that has been entered in the text field accountName = Convert.ToString(accountNameObj); //Remove remove unpermitted characters updatedAccountName = Regex.Replace(accountName, permittedCharacters, ""); //Update the value of the text field, after removing the restricted characters primaryEntity.Attributes[accountNameFieldLogicalName] = updatedAccountName; } } catch (Exception ex) { throw new InvalidPluginExecutionException(string.Format("Error occured in the PreUpdateAccount plugin: {0}", ex.Message)); } } #endregion } } }