Application Explorer filtering

Application Explorer in AX 7 allows easy filtering, which is extremely useful, because trying to locate something in AOT is what we do all the time (I really missed this feature for many years). It looks simple, but it’s very powerful, if you know how to use it.

First of all, you can simply put a string in the search box on the top of Application Explorer and press enter. In AOT, it will show only elements with names containing the given string.


You can also click the little drop-down arrow on the right and choose additional filtering options, such as filtering by element type or model name.


Using filtering by type:”form”, I’m now getting only forms with names containing ListPage.


But what if you need some more advanced filtering, such as you want to find elements with names ending with a given text? Here is where it starts to be interesting. You can actually use regular expressions for filtering, therefore you can easily easily achieve that with ListPage$.

The dollar sign means the end of the string, therefore only names that satisfy this patter are those containing ListPage immediately followed by the end of the string.

Here is my result:


Similarly, you can use ^ character to match the beginning of a string. If you use them together to create a pattern like ^ListPage$, it will find only elements that are called ListPage. No characters before or after ListPage are allowed.

Only a single element satisfy this patter: the ListPage class.


We don’t have to stop there. What if you’re looking for a form with name starting with Cust and ending with ListPage, with any number of characters in between? Here we go:


The dot means that there may be any character and * means that there may be any number of such characters.

In most cases, this is all you need to know about regular expressions to compose really powerful filtering patterns. It’s surely no problem for any software developer.

But regular expressions offer much more, if needed. Just to give you one more example, you might want to look for element names ending with numbers, such as Class1. Simple \d$ pattern will do the job.


When writing more complicated regular expressions, you may find Quick Reference on MSDN very helpful.

I said that I missed this feature for many years and indeed, I now use it all the time. I simply love it!

Expression builder in AX 7

If you want to allow users configure certain conditions by themselves, considering using the Expression Builder control.

This is how it looks like:


It exists already in AX 2012, where you can add it through the ManagedHost control. AX 7 doesn’t support managed controls anymore, but the Expression Builder has been redesigned and it’s now available as a native AX control.

Add control

The control allows you to add and remove conditions and combine them with AND and OR operators.

You can select fields, possibly from several tables.


Then you choose an operator – which operators are available depends on field’s data type.


And finally you select a value. It will give you a lookup for available values, if applicable.

Some data types are handled in a special way.  For instance, fields with data types extending Money gets an additional field for currency, and the amount is converted to the right currency for comparison at runtime.


Dealing with dates is even more complex. You can either pick a fixed date:


or define a date relatively to the current date or the current month:


In addition, Expression Builder understands surrogate keys, expands financial dimension fields to individual dimensions and has a support for hierarchies.

If you want to see an example in the standard AX application, look at Organization administration > Workflow > Work item queue assignment rules.

A bit of technical details

To be able to use your own tables in Expression Builder, you have to define an AOT query (that’s where fields are taken from) and a class (“document”) inhering from WorkflowDocument.

If you want to add Expression Builder to your own form, you have to add a little bit of code, most importantly to indicate which document class (and – indirectly – which query) it will use. Expression Builder has ExpressionDocumentClass() method for that. Then you also need some logic for loading and saving expressions – look at an existing implementation for details.

The document class can have a few useful attributes and it can also define calculated values, which are then displayed in the list among normal fields. Calculated fields are important – not only they allow you to do any kind of calculation, but you can also use them to work around limitations of what expression you can write.

Consider this scenario: You want to define a condition for ShippingDate > Deadline. How can you put the Deadline field on the right side of an expression in expression builder? You can’t (or at least I haven’t figured out how), but you can create a calculated field, such as DaysToShipDeadline, defined as Deadline – ShippingDate. Then it’s trivial to configure the condition as DaysToShipDeadline < 0.

When your expression is defined and saved, you can call Expression::evaluate() to see if the condition it true or false for a given record:

ExpressionResultType result = Expression::evaluate(
    'usmf',            // Company
    tableNum(MyTable), // Table where is the record to check
    5637144576,        // ID of a record in MyTable
    expressionId,      // From ExpressionTable

This indicates a problem with how conditions are evaluated. Because you always provide only TableId and RecId, the evaluation logic must always make a query to database. If you need to run it once, it’s not a big deal, but if you’re evaluation many expressions, it may become a problem. To make it worse, methods for computed fields and the currency convertor also get only TableId and RecId, making additional DB queries. Caching helps a bit, but it’s still all quite expensive. I consider making a child expression class accepting a temporary buffer (or buffers) instead of just a record ID; the first prototype suggests it’s feasible and worth the effort.

If you’re interested in inner workings of the evaluation, let me give you a brief overview:

  • AX executes the query defined in the document class, filtered by RecId provided by the caller.
  • Data returned by the query (plus calculated values) are put into a XML document.
  • When you save your rule in Expression Builder, the condition is converted to an XPath query and saved to ExpressionTable.XPathQuery field. For evaluation, AX simply runs the XPath query against the XML document and returns the result.
  • XPath syntax there has a few extra functions, such as ConvertAmountValue() calling X++ class ExpressionCurrencyDefaultProvider.

If you want more details, you can look at source code, because most of it is available to you.

  • Expression Builder control is built in the same way that you can use to build your own controls. The runtime class is SysExpressionBuilderControl, its HTML code is in SysExpressionBuilderControlHTM resource, and so on.
  • A lot of logic of logic regarding saving and loading expressions is directly on ExpressionTable table. saveExpression() is a good example.
  • The evaluation is done mainly in SysExpression class (which unfortunately isn’t designed to be easily extensible).

Some logic is also contained in Microsoft.Dynamics.AX.Framework.Model.dll.

It looks useful, doesn’t it?

Certification booster packs

If you’re considering taking a Microsoft exam, you might be interested in Microsoft Certification Booster Packs. They give you a practice test and/or four extra retakes in case you fail, which may be very helpful if you’re not sure what to expect from the exam, or if it’s quite hard.

The offer expires on 30th September 2016, therefore you shouldn’t hesitate for too long. Then you get six months to actually take the exams.

It’s applicable to Dynamics certifications, nevertheless people in comments complained that practice tests aren’t available for Dynamics AX exams. If you consider buying a booster pack for a Dynamics AX exam, it may be safer to take the one with four retakes rather than practice tests.

Class extensions

The new Dynamics AX (AX 7) attempts to minimize overlayering (“customization”) and promote extensions, which allow adding functionality without modifying source code of the original object. For example, you now can attach a field to a table without changing the definition of the table itself. It has many benefits – no changes in existing objects mean no code conflicts and much easier upgrades, it’s not necessary to recompile the original object and so on.

AX 7 RTW introduced extension methods – if you’re not familiar with them, look at my description and an example in New X++ features in AX 7. In short, extension methods are static method defined in a completely different class, yet they can be called in the same way at if they were instance methods of the “extended” class, table or so.

Update 1 added something called class extensions, which allows adding not only methods, but also class variables, both instance and static, constructors and static methods.

For example, the following piece of code augments the standard Dialog class with a variable and methods working with the variable:

final class MyDialog_Extension
    private int x;
    public void setX(int _x)
        x = _x;
    public int getX()
        return x;

You can use these methods directly on the Dialog class:

Dialog d = new Dialog();
int x = d.getX();

As you would expect, the value set by setX() is stored in the variable and you can retrieve it by calling getX().

But how does it really work? How Dialog class knows about these new methods and where is the value actually stored, if it’s all defined in a completely different class?

You might think that MyDialog_Extension inherits from Dialog and replaces the Dialog class, it’s a partial class or something like that, but it’s not the case.

The methods are actually extension methods as we know them from AX 7 RTW. Don’t get confused by the fact that we declare them as instance methods; they’re converted to normal static extension methods under the hood. For example:

// This instance method in the extension class…
public void setX(int _x) {}
// …is converted to a static extension method like this:
public static void setX(Dialog _dialog, int _x) {}
// As usual, the first argument is object to which the extension methods applies.

The conversion happens when X++ is compiled to CIL and you normally don’t have to bother about it; I’m mentioning it to demonstrate that it’s really just a normal extension method.

Generating different CIL than what you see in X++ might look weird, but it’s a common way to extend CLI (“.NET”) languages without changing the Common Language Runtime (CLR). For example, if you use async keyword in C#, C# compiler uses standard CLR constructs to generate a whole state machine that handles asynchronous processing. Because CLR receives normal CIL code, it doesn’t need to know anything about X++ class extensions nor C# async/await.

All right, so methods in class extensions are just common extension methods, which explains how methods are “attached” to the augmented class. But where AX stores the variables? How can static methods of the extension class access instance variables?

Again, the solution isn’t too complicated. Under the hood, the extension class has a static variable which maintains references between instances of the augmented class and instances of the extension class. In my case, it maps instances of Dialog and MyDialog_Extension.

When I call a method of my MyDialog_Extension, it gets a Dialog instance as the first argument. It looks into the static map, obtains the corresponding MyDialog_Extension instance (it might have to create it first if it doesn’t yet exist) and then it accesses its fields.

The following code is a simplified demonstration of how it works.

// A demonstration - not the real implementation
final class MyDialog_Extension
    private int x;
    private static Map mapDialogToExtension;
    public static void setX(Dialog _dialog, int _x)
        MyDialog_Extension extension = mapDialogToExtension.lookup(_dialog);
        if (!extension)
            extension = new MyDialog_Extension();
            mapDialogToExtension.insert(dialog, extension);
        // Here we're accessing the instance variable
        extension.x = _x;

Now it’s clear that extension classes don’t modify their augmented classes in any way. All variables declared in an extension class are stored in its instances – it’s rather similar to joining two separate tables.

Because extension classes merely get instances of augmented classes by references, they can’t access its internal state or call private methods.

You can also attach static methods and class fields (variables and constants).

Using static methods in class extensions is useful because it’s easier to find static methods on the corresponding class rather in some utility classes. It also allows you to add methods to the Global class and call them without specifying any class name.

Using static fields can also be very useful. The following example shows adding a new operator (implemented as a public constant) to DimensionCriteriaOperators class.

final static class MyDimOperators_Extension
    public const str MyNewOperator = '!';

As with methods, the new constant seems to be a part of the augmented class, although it’s declared somewhere else.


In some cases, such a static class with public constants can be a natural replacement of extensible enums.

If you use a static method or a static variable, CIL generated by X++ compiler directly refers to the extension class.  For example, DimensionCriteriaOperators::MyNewOperator is translated to exactly the same CIL code as MyDimOperators_Extension::MyNewOperator. The fact that X++ presents it in a different way is purely for developers’ convenience.

As you see, class extensions are really an evolution of extension methods. Instance methods in class extensions are based on extension methods; they “merely” add a the option to work with instance variables. And there a few other useful features, namely constructors and static members.

The main purpose of class extensions is to help with getting rid of overlayering, but that’s not the only use. They have potential to change how we traditionally design certain things in AX, especially if somebody comes with a common framework based on extensions, as LINQ revolutionized how we work with collections in C#.

For example, are you aware of that you can write extension methods working with all table buffers by extending Common? Like this:

final class Common_Extension
    public List getSelectedRecords()
        List selectedRecs = new List(Types::Record);
        if (this.isFormDataSource())
            MultiSelectionHelper helper = MultiSelectionHelper::construct();
            Common rec = helper.getFirst();
            while (rec)
                rec = helper.getNext();
        return selectedRecs;

The possibilities are unlimited.

I hope I didn’t overwhelm you with technical details – it may be challenging especially if you’re not familiar with C#, where we use things like static members and extension methods for years. But I believe that understanding the inner workings is often very helpful for using language features correctly and debugging code if it doesn’t work as expected.

Label ID fix

I recently saw an interesting problem with labels in AX 2012 – two customizations created different labels with the same IDs, therefore the newer won and the older one showed completely wrong texts in GUI.

For example, one customization created a form with caption @XYZ1 = “Customers”. Another customization created a label with the same ID, @XYZ1, with text “This is an error” and used the label for an error message. The latter change effective replaced the text of @XYZ1 from “Customers” to “This is an error” and therefore the form caption becomes a nonsense.

The cause (I believe) was that two developers used different primary language when putting code to TFS and not all labels existed in all languages. Anyway, the main question was how to fix it.

There is no way how @XYZ1 could mean both “Customers” and “This is an error” at the same time, therefore it was necessary to create a new label for one of the cases and update all code using the label. And repeat it for more than a hundred times.

I didn’t know how difficult it would be to automate it – fortunately I found it rather easy. First of all, I extracted original labels from an older version of the .ald (version control systems can’t prevent all problems, but at least you have all data so you can recover from failures). Then I parsed this list of labels to objects containing label ID, label text and description. (Note that I didn’t have to deal with translations in this case.) You can see it in getParsedLines() method below.

Next step was to create a new label ID for the given text and description and maintain a mapping between the old and the new label ID.

Finally, I used some existing methods to replace original labels IDs with new ones in code and properties. This was potentially the most complicated part, but it turned out to be a piece of cake. :-)

I also had to identify and checked out all objects where labels should have been be replaced, because the replacement works only with checked-out objects. It wasn’t too difficult thanks to version control; I simply took all objects included in the original changeset.

The complete code is below; maybe somebody will run into a similar problem and will find this useful.

class DevLabelFix
    private List getParsedLines()
        str fileName = @'D:\oldLabelsFromTFS.txt';
        System.Collections.IEnumerable lines;
        System.Collections.IEnumerator enumerator;
        str line;
        DevLabelDef labelDef;
        List parsedLines = new List(Types::Class);
        int spacePos;
            lines = System.IO.File::ReadAllLines(fileName);
            enumerator = lines.GetEnumerator();
            while (enumerator.MoveNext())
                line = enumerator.get_Current();
                if (strStartsWith(line, '@'))
                    labelDef = new DevLabelDef();
                    spacePos = strFind(line, ' ', 1, 10);
                    labelDef.parmId(subStr(line, 0, spacePos-1));
                    labelDef.parmLabel(subStr(line, spacePos+1, strLen(line)));
                else if (line != '')
                    Debug::assert(labelDef != null);
        catch (Exception::CLRError)
            throw error(AifUtil::getClrErrorMessage());
        return parsedLines;
    public void run()
        ListEnumerator enumerator = this.getParsedLines().getEnumerator();
        DevLabelDef labelDef;
        SysLabelEdit sysLabelEdit = new SysLabelEdit();
        str newLabelId;
        Map labelMap = new Map(Types::String, Types::String);
        while (enumerator.moveNext())
            labelDef = enumerator.current();
            newLabelId = sysLabelEdit.labelInsert(  'en-us',
            info(strFmt("%1|%2", labelDef.parmId(), newLabelId));
            labelMap.insert(labelDef.parmId(), newLabelId);
        // These methods are normally private; I made them temporarily public to allow these calls.
    public static void main(Args args)
        new DevLabelFix().run();
// The DevLabelDef class merely holds ID, label text and description together.
class DevLabelDef
    str id;
    str label;
    str description;
    public str parmDescription(str _description = description)
        description = _description;
        return description;
    public str parmId(str _id = id)
        id = _id;
        return id;
    public str parmLabel(str _label = label)
        label = _label;
        return label;