Calling an X++ method on a Data Entity through OData

Today I learned of a documented but little-known (well, to me) way to put an X++ method on a data entity, and make it available via an OData call. This is a great way to build more powerful integrations through Flow or other external tools and programs.

I won’t belabor it since it is documented, but something like this:

[SysODataActionAttribute("CalcMaintenanceDuration", true)]
public int CalculateMaintenanceDuration()
{
 //do something
 return 0;
}

…will let you make a method available through an OData call. You’d use a URL that looks something like this to call the method:

https://MYCOMPANY.operations.dynamics.com/data/MYDATAENTITY.CalculateMaintenanceDuration

This needs to be done as a POST request, so you can’t easily test it in Internet Explorer like you can just getting the data entity (which sends you a JSON file full of data). Calling and using OData from outside Dynamics 365 for Finance and Operations is outside the scope of this blog post… and, honestly, outside the scope of my expertise at this point. You’ll want to look at the OData standards (where the methods you can call are usually called “actions”) and/or documentation for your language. Tools like Flow can handle all this in the background for you, just letting you browse available “actions.”

Advertisements

Checking in references to other models

As you might be aware, sometimes you need to add a reference to other models in your own models. You do this by going to Dynamics 365 > Model Management > Update model parameters, selecting your model, and checking the box for the model you want to reference.

Addinf references to a model

For example, here you see references added for FiscalBooks, GeneralLedger, Ledger, and Measurement. (A full discussion of references is too much for this blog post, though!)

I discovered, to my surprise, that even experienced developers sometimes don’t know how to check in these changes. If code that requires the reference is checked in, but the new reference is not, the build breaks with potentially mysterious and hard-to-diagnose errors!

How do you check in changes to references? You need to check in the DESCRIPTOR file for the model. It will be an XML file named after the model, and it will be in \AOSService\PackagesLocalDirectory\<ModelName>\Descriptor; it might excluded by default, and you need to make sure to include it in your changes. For example, if you add a reference to a model named “Czar Extensions Model,” you want to see something like this in your pending changes for the check-in:

Pending changes with Descriptor file

I hope this helps. May all your builds be “green”!

 

Resolving X++ and metadata conflicts when merging code

In the near future, Microsoft will seal off customizations/overlayering in Dynamics 365 for Operations. Once that happens, and VAR/ISVs catch up, you won’t have the same problems with conflicts while merging code from various sources (including Microsoft’s own X++ hotfixes). Until then, though… I found the process of properly resolving conflicts to be not completely intuitive, and ended up doing unnecessary manual work and comparison for a while. Here’s how to do it the right way (also the easier way), with a little-known secret or two to help.

You probably already know that after merging in new models, you need to go to Dynamics 365 > Addins > Create project from conflicts in Visual Studio to check for conflicts.

Resolve Conflicts 0a

After doing so, you need to select which model to look for conflicts in. Yes, you need to do them one at a time. Yes, the dialog disappears after each check, making it a hassle to use if you are juggling models from a bunch of different ISVs.

Resolve Conflicts 0b

To save time, be smart about which models you check. You only need to check third party “customization” models, not “extension” models. (Comment if you know of a way conflicts can appear in extension models!) If you’re savvy, you might be able to limit it further, if you know who is changing which objects. But play it safe; you don’t want to miss any conflicts!

Assuming you actually hit a conflict… it’s going to need to create a project. I like to use a naming scheme like ModelNameConflicts_YYYYMMDD to make it easy to clean up later.

The project will be created, and it will contain any and all objects that have conflicts. Here’s where it got confusing for me; intuitively, I thought I’d want to right-click the object and choose “Compare and Merge Code” or something. Nope! Start out by just opening the object.

Resolve Conflicts 1

Once you open it, it won’t be obvious where the conflicts are. They’re marked, but if it’s a big complex object, it might be hard to find them.

The secret?… put “cf:” in the search bar and hit enter.

Resolve Conflicts 2

The object will be filtered to show you the conflicts. (See the little red double arrows icon?)

What you do next depends on whether the conflict is in metadata or in code. It’s not that different, though. One at a time, right click each object, and choose either “Resolve property conflicts” or “Resolve code conflicts.”

If it’s a property conflict:

Resolve Conflicts 3

If you are resolving a property conflict, you’ll get a GUI that you hopefully find intuitive.

Resolve Conflicts 4

If it’s a code conflict:

Resolve Conflicts 5

If you are resolving a code conflict, you’ll be given a DIFF tool to do the merge. This post is not meant to fully explain code merges, but it might be intuitive for you anyway, even if you aren’t already familiar with the concept.

Resolve Conflicts 6

Whether you’ve done a property merge or a code merge, you’ll be able to mark the conflict as resolved, so it won’t come up if you do another check for conflicts.

However, re-merging models might cause the conflict to pop up again, if your ISVs (or whomever you are merging from) do not integrate the merged changes. So, be prepared to re-check in the future, and possibly correct the same conflicts repeatedly!

Catch CLR errors in X++ in Dynamics 365 for Operations

Although there are useful posts out there on catching CLR errors in X++ for older versions of Dynamics AX, as of this writing, I couldn’t find one that address the current version. It took me a little experimentation and trial-and-error to figure out how to do it; in particular, to actually return a useful error message, instead of just a generic CLR error. Below is the pattern I use. For simplicity, I’m leaving out some of the other types of CATCH you might use, as well as other detail irrelevant to the pattern.

As usual, I would greatly appreciate comments on whether this works for you, and if you know of any improvements.