Consistent Y-Axis in Model-Driven App Charts

This week I faced a very old school problem with model-driven apps from the days of working on-premise with Dynamics CRM, I needed to show two different series on the same graph, but every time I would view the chart it would show me two different scales on the same Y-Axis!

As this chart was for the purpose of comparing values, this makes the out-of-the-box chart meaningless as in some respects, smaller numbers look bigger than their counter part as shown below with test data in my development environment.

A screenshot of a model-driven app chart with two different Y-Axis scales for the same type of data.
Note that the y-axis reference on the left has a higher increment for each bar in comparison to the right y-axis.

We can resolve this with a few steps by editing code, and here’s how.

Step 1: Back up your environment

Before we get started, please note that Microsoft have gone a very long way to make solutions a no-code option for deploying components and that it is not recommended to edit solution files unless the requirement cannot be fulfilled any other way, and you are absolutely confident in how solutions are composed and deployed.

Always back up your database before significant operations, and seek support from peers if you are uncertain. It’s also worth considering how impactful this change is, and whether the effort vs. benefit stacks up in the correct way.

Step 2: Create a temporary solution file

In order to make sure that our changes persist from development to production, we will need to re-import our code changes back into the source environment once complete. This is so that the changes are recognised every time we export from source and deploy to target in the future, otherwise you would need to make this change every time you deploy to a new environment in the future which carries risk due to the frequency of this activity.

A screenshot of a user creating a new temporary solution file.
This helps us to target the components that we need to change that otherwise live in another solution, and therefore reduces risk considerably.

Step 2: Add your chart(s)

When we add existing components, we’ll need to locate the Table and its associated Chart components for change.

A screenshot of a user selecting multiple existing charts to add to their solution.

Again, let’s make sure that we only add what we need here.

Step 3: Export an unmanaged copy of the solution

As we need to edit the code that sits within the solution, we must export it so that we can make the changes and re-import it here later.

A screenshot of a user selecting the Unmanaged option for the solution export.

By selecting Unmanaged, we retain full control over the customisations once the solution is re-imported, which is important as we probably want to keep the changes but remove the solution file later on.

Step 4: Unzip your file and make the change

Solution files download as .zip files, so we need to extract the files before we can work on them. When you extract the files, you’ll see three files:

  • [Content_Types].xml
  • customizations.xml
  • solutions.xml

We now need to open up customizations.xml in our favourite code editor, preferably Notepad++ or Visual Studio Code. Search for the word ‘Secondary’ within your code, and remove the YAxisType variable. You will have one of these tags for each chart that you’ve added with multiple Y-Axis, and in this instance I have two due to the two chart components that I selected earlier.

A screenshot of a user editing the customizations.xml file in Visual Studio Code.

Original code:

<Series ChartType="Line" IsValueShownAsLabel="True" BorderWidth="3" MarkerStyle="Square" MarkerSize="9" MarkerColor="37, 128, 153" MarkerBorderColor="37, 128, 153" YAxisType="Secondary" />

Amended code:

<Series ChartType=”Line” IsValueShownAsLabel=”True” BorderWidth=”3″ MarkerStyle=”Square” MarkerSize=”9″ MarkerColor=”37, 128, 153″ MarkerBorderColor=”37, 128, 153″ />

Step 5: Zip up the files and re-import

Now this is where we need to be extremely careful, we need to select the three extracted files and compress into a .zip file.

At this point in time, your Windows device will ask for a name for the .zip file. You should make sure that the name of your file within this folder is exactly the same as the original file name exported from your PC. As long as you zip these files up anywhere other than the same location that you downloaded the .zip file too, you will have no problems doing this, and you’ll then be able to go back to your browser to import the newly compressed .zip file.

A screenshot of the newly modified .zip file being uploaded to the environment.

And there you have it! I have mentioned this just a few times before, but remember that this is a relatively complex and risky operation that should be executed with focus and confidence. I have the luxury of working on on-premise versions of Dynamics “CRM” well before some Power Apps developers were out of secondary school, but if you aren’t so sure, please do reach out to me or to someone else who may be able to help with the more technical elements of this activity.

A screenshot of the final result, showing one y-axis for both lines in the graph.

Now that you’ve seen the results, you are safe to carefully remove each component from your temporary solution, before finally removing the solution itself.

Expect Dataverse Deployments To Fail First Time

Whilst the process of deployment hasn’t changed too much since the days of Dynamics CRM, one thing that has changed significantly is the volume of possible components that can be included in a solution file.

Not only is this due to an increase of readily-available functionality from Microsoft, but also by the ability for end users to install their own components, which in turn creates more dependencies on (what we think) is our small solution of configuration changes to be deployed from one environment to another. This can increase the number of failures that can occur during delivery, and often, the end user error isn’t very helpful.

A generic error provided by the Power Platform when trying to deploy a solution.

Solution deployment failures don’t have to be a problem, in fact, we should expect them.

In this blog post I will help you understand how to troubleshoot a failed deployment so that you can solve the issue in an informed way.

Step 1: Download A Code Editor

We want to ensure that the output from the failure is in a readable format, and for this we need a code editor that recognises XML formatted files. My preference as a functional consultant who needs to open the occasional file is Notepad++. It’s free, and it has an XML Tools plugin which allows you to ‘pretty format’ any XML files. You can also use Visual Studio or Visual Studio Code – I suspect some of you reading this will already have one of these installed!

Step 2: Download The Solution’s Log File

Whenever someone approaches me with a failed deployment, the first thing I ask them for is the log file. When you open this file in Notepad++, use ctrl+alt+shift+B, which will ‘pretty format’ your XML file. It’ll look something like this:

A screenshot of Notepad++ with XML Tools plugin installed. The file shown here is using 'pretty format' to make the code readable.

It looks difficult to decipher to the untrained eye, but we can quickly start to understand why the solution is failing with a few tips when we break down the file.

Step 3: Understand The Dependency

Let’s take a look at the first dependency, defined by the <MissingDependency> XML tags.

A snippet of code showing a missing dependency.

You’ll notice a <Required> line and a <Dependent> line which both include a Type. This, alongside the schema name, is the most important part of the dependency, as the two combined tell us what we’re looking for.

Fortunately we don’t need to remember all of the types as Microsoft provide a handy reference guide here.

We simply need to cross-reference the numbers in our dependency, and we now know that to complete the deployment we need to include the “Offering” entity (table) for the “Service” System Form.

Step 4: Modify Your Solution

We have two choices here:

  1. Remove the Service System Form from the solution, or,
  2. Add the Offering entity (table) into the solution.

In this particular instance it would make more sense to add the Offering into the solution, but sometimes you may challenge whether the component is really needed within your deployable solution, in which case, you’d remove the System Form.

Step 5: Rinse & Repeat

Not all dependencies will be resolved within one solution modification, but that’s ok, and you may need to repeat steps 3 & 4 multiple times before you have a solution file that can be successfully deployed. The key is to remember that failures can be expected, and that they don’t always have to be a problem!

How To Enable ModelDrivenFormIntegration for Existing Canvas Apps

Earlier this week I found myself trying to embed an existing Canvas app into a Model-Driven app to better present information relating to the record using the flexible UI controls, but as an infrequent user of such a feature, I struggled to understand how I could reference the current Model-Driven app record’s data within the Canvas app!

All over the web I could find resources pointing towards a special type of control called ModelDrivenFormIntegration and how it works, but I simply couldn’t see it within my solution. This is where it should be:

A screenshot of a Canvas app, highlighting the ModelDrivenFormIntegration control that appears after embedding within a Model-Driven app.

The new Power Platform interface has improved so many of the existing controls and added fantastic new features, but unfortunately at the time of writing, embedding a Canvas app via the new user interface needs a little more work, and it doesn’t quite complete the job in all circumstances. There are two reasons for this:

  1. You have to associate the control with a field on the Form, and when adding the Canvas app via the new User Interface, it doesn’t configure the field control automatically leading to errors when loading.
  2. The functionality available via the ‘Customize’ button is not available in the new User Interface, which is partly the reason for this blog post!

As some of you will be aware, sometimes it’s just better to head over to the classic user interface to complete your configuration, and although I’m finding myself using this user interface less these days. In this post I attempt to bridge the gap and I’ll explain how to get things working.

What is ModelDrivenFormIntegration?

As Microsoft have explained in detail here, this control allows us to bring contextual data from the Model-Driven app that the Canvas app is utilised in.

There are a significant number of benefits to doing this, primarily because it provides you with the ability to dynamically change your Canvas app content based upon the record you’re currently viewing in the Model-Driven app.

Enable ModelDrivenFormIntegration

Step 1: From https://make.powerapps.com, navigate to the correct environment and choose the relevant Table’s Form within your solution file. Use the ‘Switch to Classic‘ button from the navigation bar straight away.

A screenshot of a Dataverse Table's Form, highlighting the 'Switch To Classic' button.

Step 2: Navigate to the required field you’ve configured for your Canvas app control and double click. You’ll notice a pop up window which provides the ability to navigate to the Canvas app control configuration. Click on ‘Controls‘ and press the ‘Customize‘ button.

A screenshot of the classic user interface that was inherited from Dynamics CRM, showing the Properties of a Mandatory field on the Controls tab, highlighting the 'Customize' button.

Step 3: Your Canvas app will now open, and you’ll notice that ModelDrivenFormIntegration is now available as the first control on the list for the first time! We’re not done yet though, we need to tell the control which Table we are using within the Model-Driven app by editing the ‘DataSource‘ Property.

A screenshot of a Canvas app, highlighting the ModelDrivenFormIntegration control's Property called 'DataSource'.

And finally the ‘OnDataRefresh‘ Property.

A screenshot of a Canvas app, highlighting the ModelDrivenFormIntegration control's Property called 'OnDataRefresh'.

We can use the plural label/friendly name of the Table here, instead of having to look up the logical name, which is a great touch in a lot of Power FX’s abilities.

Conclusion

And we’re done!

The configuration for this isn’t difficult, but finding out why the issue exists can often be challenging, especially if you’re an infrequent user of this functionality.

Remember to ‘Save‘ and ‘Publish‘ your Canvas app changes when you’re ready, but you don’t need to publish your Model-Driven app as this was simply a route into enabling the functionality with no configuration changes.

There are a few pointers to be aware of when generally configuring embedding Canvas Apps:

  1. Microsoft advise that associating your embedded Canvas app control is tied to a mandatory field, so that you can guarantee the operation of the Canvas app.
  2. Remember to share your Canvas app or make other users Co-Owners as appropriate before releasing the functionality to end users.
  3. The classic user interface is due to be deprecated in an upcoming release nearer the end of the year. I suspect this feature will still work for a short period of time, but we will have to watch and wait until such a time, and I’ll update this post if/when this happens.

Power Apps ModelDrivenFormIntegration Control

Embedded Canvas App Guidelines & Troubleshooting