Skip to content

X++ Syntactic Sugar – Public Interfaces and the Dangers of Refactoring Code

One of the features that was included in the latest release, 1.7.0.0 as of writing, of the D365 Admin Toolkit, was my telemetry messages when adding or removing the SysAdmin role for users featue. Microsoft recently released a new way of creating telemetry messages using X++, that makes it a lot easier adding attributes to the telemetry messages, so I thought that I should use that to provide an implementation example. More about the new telemetry interface coming soon….

Johan Persson suddenly began to receive strange errors when adding system administrator roles to users after updating to 10.0.41.

Method not found: 'Dynamics.AX.Application.SysApplicationInsightsEventTelemetry Dynamics.AX.Application.SysApplicationInsightsEventTelemetry.addProperty(Dynamics.AX.Application.SysApplicationInsightsProperty)'.

Looking at the changes, it was identified relatively quickly that my change had caused the error.
Link to issue here if you want to tag along.

Okay, we all make mistakes… So, I asked him to turn off the feature. No change!

Deep Dive

Okay, that kind of confused me. So, I spun up a new onebox environment to test it out. As expected, after updating to 10.0.41, it began to throw errors.
Expecting some interface changes or removed methods, I started a compilation of the Admin Toolkit.
No compilation errors!
I added the system administrator role to the same user again, and there was no error! It can find the addProperty method.

That confused me a bit, so I looked at the telemetry code.
The code in the preview version of 10.0.41 related to telemetry had been refactored! The SysApplicationInsightsEventTelemetry now extends from a new class, SysApplicationInsightsTelemetryContractBase, that contains the addProperty. The addProperty no longer existed in the SysApplicationInsightsEventTelemetry class.

It’s somewhat problematic that we have to release on 10.0.41, so I developed a quick work-around that further encapsulates the offending code, so it’s at least possible to disable the telemetry feature.

A Little Bit of Decompilation

The refactoring explained why it broke, but my curiosity still peaked. So I decided to disassemble the binaries and compare the latest release to a release built on 10.0.41.

I highly recommend ILSPY if you like to snoop around. Let me know if you want to learn how to use it for debugging

So, looking at the old code, it’s calling addProperty on SysApplicationInsightsEventTelemetry.

XXX
SysApplicationInsightsTelemetryLogger.instance().trackEvent(SysApplicationInsightsEventTelemetry.newFromEventIdName(_id, _name).addProperty
XXX

Link to original code: 1.7.0.0 Release – sendTelemetryAssignedExpiredRevoked

After compiling it on 10.0.0.41, it now uses the type SysApplicationInsightsTelemetryContractBase when instantiating the SysApplicationInsightsEventTelemetry object. No wonder it’s not happy…

XXX
SysApplicationInsightsTelemetryLogger.instance().trackEvent((SysApplicationInsightsEventTelemetry)((SysApplicationInsightsTelemetryContractBase)SysApplicationInsightsEventTelemetry.newFromEventIdName(_id, _name)).addProperty
XXX

Link to original code: 1.7.0.0 Release built on 10.0.0.41 – sendTelemetryAssignedExpiredRevoked

Conclusion

So the conclusion is that refactoring code can be dangerous, and no good deed never goes unpunished… Even while architectural sound, remember that if you can call it, then it’s a public interface.

Another conclusion we can make is that it’s not enough that you encapsulate the offending lines of code. If the code exists in the method, it will fail.

ISVs, partners, and customers need to remember that interfaces might change and binary compatibility is not guaranteed – Not only when new versions of F&O get released but also own developed code or ISV solutions.

Leave a Reply

Your email address will not be published. Required fields are marked *