I am publishing a new XrmToolBox plugin in a few days called the Alternate Key Manager. This plugin is pretty self explanatory: administrators can manage their Alternate Keys across Entities in one place. I pulled this plugin together over a few days for a deployment but I took this as an opportunity to test my approach to reusable toolbox components and refine my overall XrmToolBox development process.
The need for this plugin arose during a recent customer deployment. This is a Dynamics CRM 2016 On Premises solution leveraging Alternate Keys because of heavy external systems integration. When deploying to downstream environments, we’ve run into issues importing solutions that contain Alternate Key definitions. The error usually revolved around permissions creating an index on the Alternate Key definitions and we need to attempt to republish the key, or in some cases, have the DBA drop the index and then we can recreate the Alternate Key definition.
The solution includes nearly 40 entities with Alternate Keys, so checking each individual key for errors is a bit tedious. We could review the System Jobs for failures but I was looking for something a bit more comprehensive and interactive. I wanted the ability to manage all of the Alternate Keys in one spot, such as Create new keys, and Delete, Activate, and Deactivate existing keys. If we have a failure, just click and reactivate.
So I created the Alternate Key Manager plugin that allows administrative users to view the list of Alternate Keys across multiple selected Entities, activate them if they are in a failed state, or delete a key if necessary. You can also create new Alternate Keys for an Entity.
This area of the plugin provides a similar interface to the Dynamics CRM web interface where you provide the schema and display name for your new Alternate Key. You can choose from the list of available publisher prefixes when selecting the Entity Attributes for the new key. For now, the plugin supports the same Entity Attributes as allowed by Dynamics CRM v9.0. The next Dynamics 365 release will allow more attribute types, so I will be making an update soon. This article defines the list of Attribute types that will be supported: Define alternate keys for an entity.
Building the plugin
This plugin is somewhat limited in its audience, only being useful to those leveraging Alternate Keys within their solution. But I took creating this plugin as a chance to use my Shared XrmToolBox Controls. This plugin required displaying a list of Entities so I went right to my first shared Entity List View Control. I wanted to find out just how useful is a shared control going to be for other developers.
When I first developed the code for the Entity List View Control, it was part of my New XrmToolBox plugin: TypeScript Helper Class Utility plugin. I would guess that it took me a solid 6-8 hours to build out the functionality of binding a list of Entities to a ListView, implementing sorting, and providing the selected
EntityMetadata in different contexts. From there, I made several updates to make things work as planned. During the conversion to a standalone control library, I worked on more features like filtering, grouping, changing views, and additional public properties and methods. All said and done, I would estimate 30 hours of work on the control over these iterations.
So when I starting building the Alternate Key Manager plugin, I added the reference to my project, placed the control on the form, and added a few lines to initialize the control. Within minutes, my new plugin had the ability to load a list of Entities from my CRM instance, filter, sort, and provide access to the
EntityMetadata SDK objects. A few days worth of development, troubleshooting, and testing boiled down to a few minutes of adding a control to my project. That is a big time saver, especially since I only had a few days to have a functioning version of the plugin for our weekend deployment!
If I have this method for loading all Entity metadata in the system readily available in my shared Entity List View Control, why the secondary list and step to load the Alternate Keys for a subset of the list? This decision is due to a limitation of the data available from my Entity List View Control. The control makes a list of
EntityMetadata objects available as part of the public interface. The SDK call used to load the Entity Metadata is the
RetrieveAllEntitiesRequestand when calling this method, the default options return the basic Entity information only. If we want the extended
EntityMetadata details, such as Attribute metadata, relations, and Alternate Keys, we need to retrieve the full
EntityMetadata object using the
EntityFilters value of
EntityFilters.All. As you can imagine, this is pretty slow lo load all that data by default!
I could have made an update to my shared control and returned full
EntityMetadata but this would have made the control almost unusable for most developers. Instead, I added an additional property on the control that will allow developers to change the filters.
I ended up not using this option in the Alternate Key Manager and went the route of the secondary list since it allowed me to show the Alternate Keys in a single ListView, grouped by Entity. But this was a good example of a chance to revise or extend a design based in different use cases. The Entity List View Control still saved me a lot of time in development, and by using the control in new plugins, I am able to highlight limitations and address them as needed.
With this new plugin, I wanted to provide the ability to add Alternate Keys to an Entity. I thought about a modal dialog that for adding a new Alternate Key to the selected item in the main Entity List View Control, but I thought the context might be a bit confusing given the two ListView controls on the form. So decided on a simple pane to the right in which you select the Entity, show the list of Attributes, and create the new Alternate Key. This also gave me an excuse to create a new control, the Entity Dropdown Control. As I mentioned in my last post , this is a pretty common control you see across XrmToolBox plugins.
This control relatively simple but I was able to implement the
IXrmToolboxControl interface and leverage existing shared methods in my control library. Having this predefined interface provided a familiar template of methods and events that I knew how to implement. For example, I knew that I needed to implement an
Initialize method that ensures my new control has a reference to the CRM service instance and the parent control. I also used and expanded some shared methods from my control library around
EntityMetadata, such as the method to retrieve all Entities used by the Entity List View Control. Of course, I made a few revisions as I was using them in a different context, so this developing this plugin also forced me to tighten up that code a bit. Although I had to create a new control for the Alternate Key Manager plugin, I saved myself time by leveraging existing code and patterns. The end result is time saved in my new plugin development and a new control that will hopefully save other developers some time!
It’s not news that sharing code and providing common methods for development can help reduce time and error. The XrmToolBox itself is a prime example of this approach to development. I’m pretty happy that the shared controls saved me time in building the Alternate Key Manager and that I was able to add a bit more to the shared library. This was a fun exercise that produced a new plugin that I hope will help some CRM administrators and some new and updated controls that will help out other XrmToolBox plugin developers.