How to display record counts on a stacked bar chart in CRM

TL;DR export the chart, find the line of xml which reads as follows, and add IsValueShownAsLabel="True"

If you'd like a step-by-step, read on!

Why use a stacked bar chart?

Stacked bar charts are useful for grouping data that are easily categorised. Take for example the statuses of Leads and Opportunities: Qualified, Disqualified, Open, Won and Lost. Each entity only has a few statuses, which makes for a clean chart.

The following example displays opportunities created per day, grouped by their status:

The view itself is visually very informative, with each opportunity category displayed as a different colour. Clicking each individual bar drills down to display records of the chosen status in a separate view.

One enhancement, however, which is not customisable through the chart editor, could be the addition of a record count for each bars groups. In that way we'd be able to see how many open, won and lost opportunities we have per day at a glance without having to select each column.

To achieve this, we'll need to export the chart, edit its underlying xml code, and reimport the chart.

Step-by-step:

  • Step 1: Export the chart
  • Step 2: Edit the xml
  • Open the xml file with a text editor such as Notepad, Notepad++ or Visual Studio Code. Locate the line which begins Series ChartType= .. then add IsValueShownAsLabel="True"

  • Step 3: Import the chart

That's it! Observe that the complete version displays a number on each bars groups, showing how many records are won, lost and open:

How to Pass your Microsoft Exams

Watching videos on PartnerSource and reading notes are great ways to learn the material you need to pass your exams. But it can be boring. For certain exams there are days of videos to watch, rather than hours (see MB2-718).

I recently passed 3 exams on Microsoft Dynamics 365. I learnt a lot about the software, and I learnt a lot about how to revise. Here's how I did it.

Step by step

Step 1 read through the skills measured section of the exam page. This bullet points exactly what you need to know.

Step 2 find your sources. These should be videos from PartnerSource and blog posts. Neil Parkhurst's blog is a fantastic example of someone who's documented their learning for your benefit.

Step 3 take notes. This stops your mind from wandering and keeps you engaged with the material you're watching and reading.

Step 4 create your own practice exam.

If you turn your notes into multiple choice questions, they can be fed into an exam simulator. This has the benefits of:
  • being in the same format as the exam itself
  • allowing you to learn visually
  • being interactive and responsive

I've written a very basic exam console which you can download from GitHub. Here it is in action:

It works by feeding in a .json file, which you can simply create from your notes. The file should be formatted as follows:

As an alternative, you may consider Florian Krönert's certification trainer: a well-documented, graphically stunning certification trainer. It too reads in a .json file and provides you with a multiple choice interface and feedback on your answers.

Best of luck with your exams

Unit test your client-side customisations even faster

Last month I released this post detailing how you can unit test your JavaScript customisations for Dynamics 365.

In summary, xrm-mock is an npm package which you can install to mock the Xrm object in your client-side code. By mocking Xrm, you can write tests to assert the state of your CRM forms after JavaScript functions are called, such as onLoad() and onChange() for a field.

xrm-mock has been used across several projects both by myself and others, and has subsequently received some useful feedback. Namely:

"mocking Xrm is hard"

...and not to mention time consuming.

Enter: xrm-mock-generator. This project drastically reduces the time it takes to mock your CRM form's Xrm object. A usage guide is available on the project's GitHub page (link here), but here it is again:

  • Step 1: install via npm install xrm-mock-generator
  • Step 2: import var XrmMockGenerator = require("xrm-mock-generator");
  • Step 3: initialise a global Xrm object var Xrm = XrmMockGenerator.initialise();
You now have a global Xrm object, as if you had loaded a form in CRM.

Here's an example:

This example showcases a contact form that changes the contact's firstname from Joe to Bob when the form is loaded.

src/contact.js

test/contact.test.js

You'll notice the line: XrmMockGenerator.createString("firstname", "Joe"); - that's how you add an attribute to Xrm. You can also add date attributes, option sets etc. which is all detailed on the GitHub usage guide.

The next primary goal of the project is to automate attribute metadata. That is: connect to a CRM organisation and automatically download the metadata for a form. If you feel like you can contribute or offer a suggestion, please message me on GitHub.

Unit test your client-side customisations

If you regularly write client-side customisations for Dynamics 365 forms, you should strongly consider writing tests for them.

To do so, you will require a mock implementation of Dynamics' Xrm namespace object: the object you use to manipulate the form with functions such as getAttribute and setRequired. This is because though your code knows about the Xrm object when it's running on a Dynamics form in the browser, your tests won't know about it when running locally on your machine.

Mock the Xrm object

I've begun creating a mock implementation of Xrm here on my GitHub page. It's usage is straightforward, and you can follow my examples if you're using TypeScript to write your client-side customisations.

First, clone the repository using npm install xrm-mock.

Then, create a file for your entity's form. Here's an example for the contact entity:

Note: To use this script on a Dynamics form, just add Company.Contact.MainForm.onLoad as one of the form's onLoad() event handlers.

Then, create a second file to test your contact script. The below example is using jasmine.

Now run your tests

You'll now need to configure a test runner. If you've followed my example, you can install jasmine by running the following command in your terminal: npm install jasmine --save-dev. This assumes you have node installed on your machine.

Combined with jasmine, I use wallaby.js to visualise my tests as I'm writing my code. Here it is in action:

Validate Multiple Fields in JavaScript

CRM forms can often have multiple fields marked as business required. Mandatory validation is sometimes even added dynamically via JavaScript, for example based off the value of an option set. If you have a large CRM form, it's not always possible to see all of the red (*) asterisks; users will have to try and save the form over and over to be prompted and receive focus of each missing field individually.

You can instead program all of your business required fields into an array in JavaScript, and present all of the missing information in one popup box. This is more user-friendly.

First, setup your array of fields as objects where each object holds the schema name, label and value of the field:

Then iterate through all of your fields to determine which, if any, don't contain a value (which they should because they're business required):

Note: I've chosen to use Array.prototype.forEach() in this example because it's supported in IE9 and above. If your CRM user base is using a more modern browser, consider using let:

More information on array iteration and JavaScript browser compatibility here.

Anyway, we finally need to format the labels of our fields which are missing information into a readable message to be presented as an alert. The following code splits the array of field labels each with a comma, except the last element where an 'and' is placed:

You can then present your alert with alert(message);:

As an alternate message formatting, you could use the • unicode character and the \n escape character to mock bulletpoints. Unfortunately, html tags can't be passed to alert boxes, otherwise we'd use ul:

Note: the example above only uses three fields. The solution presented should probably only be used for a requirement involving 10+ fields. Adding JavaScript adds complexity to the system and makes it harder to maintain and should therefore be avoided where possible.

Post Data from a Dynamics CRM Form to an iFrame

HTML web resources can be embedded into a CRM form within an iFrame. Often you'll need to send data to and from the embedded HTML page. Here's how.

If you need to send data from an HTML page to a CRM form, you can use window.parent to access the Xrm namespace. For example, a user may enter a value into an input field on your embedded HTML page which could then update a value on a CRM form automatically by using:

Sending data the other way (from a CRM form to an HTML resource) is slightly more complicated.

Firstly, when customising your form and adding the embedded HTML resource, ensure that cross-frame scripting is not disabled (which it is by default). If this option is left checked you'll receive a sandboxed script cross-origin error message in the browser console, and the script won't load on the form.

Secondly, set up the data you want to send from your CRM form in JavaScript. This example sends a contact's first and last name in their respective onChange() events:

More on window.postMessage() can be found on MDN here.

Finally, configure your HTML page to accept and process messages from your CRM form. Place the following script tag in your HTML's body:

Here's the finished example:

Retrieve Money Value from an an Aliased Value in a LinkEntity with C#

When you query an entity you can link another entity to it. You might want to do this to:
  • add additional conditions to your query with pertain to a related entity
  • return columns from two entities within only one query (which is more efficient)

Here's a scenario:

You have a Product lookup on the Lead entity titled 'Product of Interest' and the Product entity has an option set called 'Product Type'. A query could therefore be to retrieve all Leads that have a Product of Interest where the Product has a 'Product Type' of 'Equipment'.

In C#, your QueryExpression would utilise a LinkEntity and read as follows:

The query above retrieves all active Leads in CRM and links their Product of Interest, returning no columns from the Lead and the 'Price' column from the Product.

When retrieving the linked Product's 'Price' from a returned Lead, you might expect to be able to use GetAttributeValue, but unfortunately you can't. You must first use GetAttributeValue, then cast the object's Value property to Money, and then retrieve the Money's Value property... phew.

Here's the final code to retrieve a linked entity's Money value:

Note that the attribute you're retrieving from the Lead is "Product.price" not just "price". This is because LinkEntity attributes are prefixed with the EntityAlias property of the LinkEntity object passed to the QueryExpression (see the first code block above).