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()'

 

Or

 

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.

https://www.youtube.com/watch?v=Td7Bk3IXJ9s

The code in the video is as follows:

public static async Task Auth()
{
    string api = "https://org.crm11.dynamics.com/api/data/v9.0";

    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

Conclusion

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 = formContext.data.entity.attributes.get<Xrm.Page.LookupAttribute>("parentcustomerid");
    const usePhone =
        formContext.data.entity.attributes.get<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 => {
                formContext.data.entity.attributes.get("telephone1").setValue(result["telephone1"]);
            });
    }
}

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
    parent.Xrm.Page.getAttribute("name").getValue()

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:


Xrm.Utility.getEntitySetName("contact")

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!