Posted on 8. March 2018

Adding Global Command Buttons to the Unified Interface

If you've used the new Version 9 Unified Interface so far then you'll know that there is no advanced find button yet. I am sure that it won't be long until this feature is added in some form and indeed much of the time the Relevance Search finds what you need quickly.

That said, I thought I'd demonstrate how to add command buttons to the top bar in the Unified Interface by using the example of adding an Advanced Find button similar to the Web Client.

What is the Global Command Bar?

The Unified Client has a similar looking top bar to the Web Client except it doesn't include the site map since it's moved to the left-hand navigation.

We can now add command buttons to this top bar, to the right of the + button.

How to add a Global Command Button

1. Create a new solution and add the Application Ribbon using

2. Add a new JavaScript web resource containing the following code:

var UCIAdvancedFind = {
	open: function(){
		var advFindUrl = Xrm.Utility.getGlobalContext().getClientUrl() + "/main.aspx?pagetype=advancedfind";
	isDesktop: function() {
		return Xrm.Utility.getGlobalContext().client.getFormFactor()==1;

The isDesktop function is used on an EnableRule to ensure that the Advanced Find button doesn't show on the phone/tablet client because it will not work.

3. Add a new SVG icon to the solution to be used on the Global Command Button.

4. Load up the new solution in the Ribbon Workbench and locate the Mscrm.GlobalTab group in the Home Command Bar:

5. Drag a button into the Mscrm.GlobalTab isv area:

6. Create an Enable Rule that calls some custom JavaScript:

7. Create a command that is linked to the button that calls some JavaScript and has the Enable Rule:

Once this is published it'll show up in the top bar:

You can also add flyout menus to this bar. If there isn't enough room the Global Command Bar will show the overflow drop down menu like a flyout button.

Remember – this is only available on the UCI – which is awesome by the way!

You can download the managed solution for this button: (3.60 kb)

Posted on 21. December 2017

Method not found: '!!0[] System.Array.Empty()'.

I recently found an issue with Dynamics 365 Version 9 where a call to ITracingService.Trace(message) from inside a plugin caused the following exception:


System.MissingMethodException: Method not found: '!!0[] System.Array.Empty()'




System.MissingMethodException: Method not found:
'System.String System.String.Format(System.IFormatProvider, System.String, System.Object)'.



I simply needed to replace it with TracingService.Trace(message,null);

UPDATE: This issue is caused by compiling the Plugin using the 4.6.2 version of the .NET framework!

Hope this helps!


Posted on 20. December 2017

OAuth Server to Server Application User Authentication

Recently I've been getting asked a great deal about how to perform non-interactive authentication with the Dynamics 365 WebApi in a server to server authentication scenario. The most common scenario is that you have an external server application that needs to access the Dynamics 365 WebApi.

The good news is that it's easy using Application Users. Here is a short video showing you how.

The code in the video is as follows:

public static async Task Auth()
    string api = "";

    AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(
                new Uri(api)).Result;

    var creds = new ClientCredential("ApplicationID", "ClientSecret");

    AuthenticationContext authContext = new AuthenticationContext(ap.Authority);
    var token = authContext.AcquireTokenAsync(ap.Resource, creds).Result.AccessToken;

    using (HttpClient httpClient = new HttpClient())
        httpClient.Timeout = new TimeSpan(0, 2, 0);
        httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", token);

        HttpResponseMessage response = await httpClient.GetAsync(api + "/contacts?$top=1");


Hope this helps!  

Posted on 27. November 2017

Ribbon Dependencies in Version 9 – isNaN is no more!

I recently blogged about the introduction of the script dependancies dialog in Version 9 where you can define the scripts that are needed by another. Although it does not solve the asynchronous loading issue for forms, it makes it simpler to add scripts to form since the dependencies will automatically be added for us.

Up until now, there has been a common pattern when adding script to Ribbon Commands where the dependancies were added with a function of 'isNaN'. It didn't have to be isNaN, but that is the most popular 'no operation' function call.

With the introduction of the script dependencies, you only need to include the reference to ClientCommands.js and the ClientCommon.js will be loaded automatically for you first before the command is called.

Awesome – we no longer need the isNaN approach that always felt like a 'hack'.

Posted on 25. November 2017

Script Load Dependencies in Version 9

A long time ago, Dynamics CRM introduced the concept of asynchronous loading of form web resources – this created a challenge when scripts depend on other scripts to be loaded first (e.g. inheritance or using a common type system library during script loading).

Version 9 has introduced an interesting feature where you can define the dependencies that a specific script has on other scripts.

Imagine you had 3 scripts

  • C.js requires B.js to load
  • B.js requires A.js to load

You can now define these dependencies in the web resources dialog:

I was hoping that by defining this dependency graph, the runtime would load them in the correct order like a module loader would – but having run some test the execution order still depending on the download speed and size of the script.

Script load execution order C - B - A

Script load execution order A - B - C


The Web resource dependency feature is awesome when you have many resources that are required during form events at runtime (e.g. onload, onchange etc.) You can simply add the single script into the form and the other dependencies will be loaded for you.

At this time, it's not a solution for where you need those dependencies during script load execution.

Posted on 11. November 2017

executionContext hits the big time!

You've seen the executionContext in the event registration dialog and you might even have used it on occasion. Well with the release of Dynamic 365 Customer Engagement Version 9, it has been elevated to be the replacement for Xrm.Page.

The document describing the replacement for Xrm.Page details it as ExecutionContext.getFormContext – due to the capitalisation of ExecutionContext it implies that this is a global object, when in fact it must be passed as a parameter to the event handler by checking 'Pass execution context as first parameter' checkbox.

Oddly - It's still unchecked by default given its importance!

So why the change?

Imagine that we want to create a client side event on the Contact entity that picks up the parent account's telephone number and populates the contact's telephone when 'Use Account Phone' is set to Yes. We add the event code to both the form field on change and the editable grid on change for the 'Use Account Phone' field.

If we were to use the 'old' Xrm.Page.getAttribute method –it would work on the form but it wouldn't work within the grid on change event handler.

This is where the executionContext shines – it can provide a consistent way of getting to the current entity context irrespective of where the event is being fired from (form or grid).

Show me the code!

The following event handler is written using typescript – but it's essentially the same in JavaScript without the type declarations.

The important bit is that the executionContext is defined an argument to the event handler and attribute values are retrieved from the context returned by it's getFormContext() method.

static onUseCompanyPhoneOnChanged(executionContext: Xrm.Page.EventContext) {
    var formContext = executionContext.getFormContext();
    const company =<Xrm.Page.LookupAttribute>("parentcustomerid");
    const usePhone =<Xrm.Page.BooleanAttribute>(dev1_useaccounttelephone);
    const parentcustomeridValue = company.getValue();

    // If usePhone then set the phone from the parent customer
    if (usePhone.getValue() &&
        parentcustomeridValue != null &&
        parentcustomeridValue[0].entityType === "account") {
        const accountid = parentcustomeridValue[0].id;
        Xrm.WebApi.retrieveRecord("account", accountid, "?$select=telephone1")
            .then(result => {

Some Additional Notes:

  1. All the attributes that are used in the event must be in the subgrid row (parent customer attribute in this case).
  2. You can access the parent form container attributes using

Xrm.Page still works in Version 9 but it's a good idea to start thinking about giving executionContext the attention it deserves!

Hope this helps!

Posted on 16. October 2017

Counting Sheeps

One of the strangest part of the Dynamics CRM WebApi is the pluralisation of the entity names.

In the old OData endpoint, the entity set name was <EntityLogicalName>Set – however in the OData 4.0 endpoing, the Logical Name is pluralised by using a simplistic set of rules which often results in the incorrect plural name being picked.

This introduced a conundrum – Performance vs. correctness. Do we query the metadata for the Entity Set name at runtime – or use a duplicate set of over simplified rules in our JavaScript?

The New Version 9 Client Side API

The good news is that with version 9, the Xrm Api now supports:


This will return "contacts" and so we can safely use this without worrying if the plural name is correct or not or indeed if it changes in the future.

Hope this helps!



Posted on 15. September 2017

Folders are back!

It's a long time since I've used the old SharePoint list component and for the most part, I've not missed it. Server to Server integration is slick and just works.

That said, the one thing that I do miss is support for folders - but whilst testing the new 9.0 Enterprise Edition I've noticed that folder support has been added in this latest release!

I was so excited I just had to share a little video of what it looks like

Fodlers are back

Maybe in the release after this, we'll get support for content types and metadata properties!


Posted on 11. August 2017

Solution Packager and global optionset enum support in spkl Task Runner

I’ve published version 1.0.9 of spkl to NuGet - this adds the following new features:

  1. Global optionset enum generation for early bound classes.
  2. Solution Packager support

Global Optionset enum generation

This was a tricky one due to the CrmSvcUtil not making it easy to prevent multiple enums being output where a global optionset is used, but you can now add the following to your spkl.json early bound section to generate global optionset enums.

  "earlyboundtypes": [
      "generateOptionsetEnums": true,

In a future update, I’ll add the ability to filter out the enums to only those used.

Solution Packager Support

The solution packager allows you to manage your Dynamics metadata inside a Visual Studio project by extracting the solution into separate xml files. When you need to combine multiple updates from code comments, you can then use the packager to re-combine and import into Dynamics. To configure the solution packager task you can add the following to your spkl.json

  The solutions section defines a solution that can be extracted to individual xml files to make
  versioning of Dynamics metadata (entities, attributes etc) easier
  "solutions": [
      "profile": "default,debug",
      The unique name of the solution to extract, unpack, pack and import
      "solution_uniquename": "spkltestsolution",
      The relative folder path to store the extracted solution metadata xml files
      "packagepath": "package",
      Set to 'true' to increment the minor version number before importing from the xml files
      "increment_on_import": false

There are two .bat files provided that will call:

spkl unpack

This will extract the solution specifed in the spkl.json into the packagepath as multiple xml files

spkl import

This will re-pack the xml files and import into Dynamics - optionally increasing the version number of the solution to account for the new build.

Posted on 24. June 2017

Not all Business Process Flow entities are created equal

As you probably know by now, when you create Business Process Flows in 8.2+ you'll get a new custom entity that is used to store running instances (if not then read my post on the new Business Process Flow entities).

When your orgs are upgraded to 8.2 from a previous version then the business process flow entities will be created automatically for you during the upgrade. They are named according to the format:


Notice that the prefix is new_. This bothered me when I first saw it because if you create a Business Process Flow as part of a solution then the format will be:


Here lies the problem. If you import a pre-8.2 solution into an 8.2 org, then the Business Process Flows will be prefixed with the solution prefix – but if the solution is in-place upgraded then they will be prefixed with new.

Why is this a problem?

Once you've upgraded the pre-8.2 org to 8.2 then the Business Process Flows will stay named as new_ and included in the solution. When you then import an update to the target org – the names will conflict with each other and you'll get the error:

"This process cannot be imported because it cannot be updated or does not have a unique name."

Source 8.1 Org
Solution with myprefix_

Empty 8.2 Org




BPF entity created - myprefix_BPF_xxx

Upgraded to 8.2

BPF entity created - new_BPF_xxx





"This process cannot be imported because it cannot be updated or does not have a unique name."

new_BPF_xxx conflicts with myprefix_BPF_xxx


How to solve

Unfortunately, there isn't an easy way out of this situation. There are two choices:

  1. If you have data in the target org that you want to keep – you'll need to recreate the BPFs in the source org so that they have the myprefix_ - you can do this by following the steps here -
  2. If you are not worried about data in the target org you can delete those BPFs and re-import the solution exported from the upgraded 8.2 source org.

The good news is that this will only happen to those of you who have source and target orgs upgraded at different times – if you upgrade your DEV/UAT/PROD at the same time you'll get BPFs entities all prefixed with new_