Prevent AX Reports from Auto-Sending via Outlook Email

Requirement: When choosing email as the report destination in, allow the user to edit the email contents in Outlook rather than automatically sending.

A number of users have been concerned that outlook automatically sends email destination reports, rather than allowing them to first modify or verify the email, subject and addresses in a “new email” window.

Solution: To fix this you can modify the “SRSReportRunMailer.emailReport” method. Depending on your version of AX, modify the section around line 41 as below.

result = inetMailer.sendMailAttach(_emailContract.parmTo(),
                                   true, /* Ensure dialog is shown */
                                  //original false, /* do not show dialog*/



Allow non editable table fields to be modified via AIF.

Requirement: Allow requests made via AIF to modify fields with the table field property “AllowEdit” set to NO to be modified. By default if you modify a field in a service call that is non editable no errors occur but the field is not updated.

Solution: On your AXD service contract class, right click on the class , click “Override method” choose method “initFieldAccessOverrides” to override. Append the following line to the method

this.overRideFieldAccess(tableNum([YourTable]), fieldNum([YourTable], [YourField]), AxdFieldAccess::AllowEdit, NoYes::Yes);

Note: This can also be used to override the “editOnCreate” property of a table field for AIF usage.

AX Database Restore Scripts (List)

sqlserver (1)
A  common task in the administration of a Dynamics AX installation is restoring databases from a live application to a development environment or quality assurance (QA) environment. However when doing so one needs to be very careful to re-configure the database so that it behaves correctly in its new context. For example you would need to re-configure your SSRS servers to point to the correct DEV/QA SSRS instance. Many of these changes can be done via the front-end, but it is very useful to script these in SQL so that nothing is missed and alot of effort is saved.

microsoft-dynamics-ax-iconThe following post aims to list as many of the potential data items that need to be changed when doing a DB restore. I will in the following days be posting the relevant SQL alongside the front-end equivalent and ultimately a full DB restore script that you can use when doing such a restore. Some of these may need to be adapted for your specific configurations and you may need to add your own based on customization etc.

Infrastructure setups

  • SSRS Servers – Re-point or recreate your SSRS (SQL Server Reporting services) instances (View Details)
  • SSAS Servers – Re-point or recreate your SSAS (SQL Server Analysis services) instances (View Details)
  • Configure AX AOSs and batch AOSs – Live environments may typically have multiple AOS’ and batch servers. Cleaning up and reconfiguring these references will assist in getting new batch jobs and SSRS setups up and running. (View Details)
  • Batch Jobs/Batch Groups (View Details)
    • Reconfigure batch jobs and batch groups to use the new server configurations as soon as the AOS is started up (e.g. Workflow processing)
    • Disable certain critical batch jobs – This is especially important if there are batch jobs that should NOT run in a DEV/QA environment. E.G. Automatic placement of orders etc… These jobs should typically never be run outside of live so we want to disable them before the AOS even starts up.
  • Service accounts (Optional) Reset your AX service accounts (workflow execution and business connector proxy) if live and DEV/QA differ. (View Details)
  • Help server(Optional) Re-point your help server URL if necessary if live and DEV/QA differ. (View Details)
  • Reset outgoing email server (Optional) if live and DEV/QA differ. (View Details)
  • Reset Data Migration Framework’s shared folder (View Details)
  • Enterprise portal websites – Re-point your enterprise portal website urls to the DEV/QA instances.

Data safe guards (Optional)

  • Reset all email templates to have a sender name and address that clearly shows that they originate from a DEV/QA system. (View Details)
  • Reset Customer/Vendor/User email addresses – We may not want to inadvertently send out mails to clients, vendors or users while performing tests. These may include alert or workflow emails. (View Details)
  • Disable users – You may require that only certain users have access to DEV/QA databases for testing, scripting the disabling of the users in bulk will help prevent the wrong people from accessing the environment and save you having to do this manually. (View Details)
  • Clean up sensitive data if needed – E.G. Bank accounts, credit cards etc.
  • Set user status bar options – It is sometimes useful to set your users status bar options in DEV/QA so that you can easily identify critical bits of information relating to their sessions. (View Details)

Clean Ups

  • Clean up SYSServerSessions
  • Clean up SYSClientSessions

Beware the “Catch”

Recently while debugging some legacy code I came across the following interesting observation regarding transaction scopes (ttsbegin, ttscommit) and the exception handling surrounding it. While walking the legacy code was observing very strange and unexpected behaviour and after some online investigation i found the following statement from Microsoft:

“When an exception is thrown inside a ttsBeginttsCommit transaction block, no catch statement inside that transaction block can process the exception. Instead, the innermost catch statements that are outside the transaction block are the first catch statements to be tested.”

In its simplest form this means that for the following code:

            throw error("Thrown Error");
        catch (Exception::Error)
            error("Inside Error");
    catch (Exception::Error)
        error("Outside Error");

Prints the following results:

Now when it comes to a simple block of code like above one may say “Well that is simply silly coding”, however it becomes harder to anticipate results when that inner try…catch is within a method somewhere deeper inside the call stack (perhaps in standard code somewhere) e.g.

    void innerFunction()
            throw error("Thrown Error");
        catch (Exception::Error)
            error("Inside Error");
    catch (Exception::Error)
        error("Outside Error");

Further more if your inner exception does cleanups or logging of information this will not happen by carelessly adding ttsBegins and ttsCommits around the calling code E.G. “writeErrorLog” will never be called in the following function regardless of what the writer of “innerFunction” does if the writer of the caller adds TTSBEGIN AND COMMIT

static void testTransactions(Args _args)
    void innerFunction()
        while forUpdate select myTable
                if (someCondition)
                    throw error("Throw Error");
                    myTable.myField = "update";
            catch (Exception::Error)
                writeErrorLog(strFmt("Failed on record %1", myTable.RecId));
                error("Inside Error");
    catch (Exception::Error)
        error("Outside Error");

I thought I would just paste these observations for anyone who like me has experienced this type of “strange behavior” in the past and didn’t know the exact reason and also as a warning to beware of the “Catch”.

Feel free to share your comments, observations and thoughts.





Setup DB Logging in X++ (Updating events)

Setting up AX Database logging via the user interface wizard can at times be a bit of a cumbersome and slow task, especially for tables that are not very common. The job below will simply set database logging for all fields on a specific table. Simply replace “InventSalesSetup” with the table name of your own choosing. As always, test this in a non-production environment to confirm that it performs suits your own needs.

static void setDBLogOnTable(Args _args)
    TableId tableId = tableNum(InventItemSalesSetup);
    DatabaseLog log;
    SysDictTable dictT = new SysDictTable(tableId);
    SysDictField dictF;
    Set fields;
    SetEnumerator   se;

    log.logType = DatabaseLogType::Update;
    log.logTable = tableId;
    fields = dictT.fields(false,false,true);
    se = fields.getEnumerator();
    while (se.moveNext())
        dictF = se.current();

        log.logField =;
        info(strFmt("Adding field %1",;


Advanced AOT searching

Its always a great opportunity to interact with other AX developers and have the opportunity to learn from each other. A few weeks ago I published a blog post on searching the AX AOT in code for objects with specific properties, after the post went out I got a comment on the post of a much easier way to search the AOT from the frontend, that for some reason I have never really noticed before. So here is a quick way to do an advanced search of the AOT using a real situation I encountered this morning.

Example: Find all privileges in the AOT that have a specific menuitem as an entry point. e.g. “PurchFormLetter_PackingSlip”

1. Open an AOT and select the section of the AOT that you wish to search. Obviously the narrower the search the quicker it will be. I selected Security->Privileges.
2. Right click on the object. Click Find
3. Select “All Nodes” in the search dropdown
4. Select properties tab.
5. Right click on any field in the “Property” Column, Click filter by field.
6. Enter the name of the property you wish to search on. In my case I’m looking for all entry points that points that have the ObjectName set to PurchFormLetter_PackingSlip, so i enter “ObjectName”
7. Click Ok.
8. Click the “Selected” checkbox
9. Enter the value you want to search for under “Range” e.g. “PurchFormLetter_PackingSlip”
SelectProperty210. Repeat steps 5-9 if you want to search for multiple properties.
11. Click Find now
12. You will now have a list of all the subobjects of whatever you selected in step 1 containing a specific property with a specific value.


Note 1: You can also do some pretty neat searches using both the date and advanced tabs on this form so be sure to check them out too.

I hope this helps somebody who like me has just overlooked this for years.

Thanks Martin for the tip!


Disclaimer: For my specific example it may have been easier to use either the Security development tool or right click on the menu-item in AX -> Add-ins -> Security Tools -> View related security objects. But I needed an example for this post 🙂

10. My checklist for debugging X++ code

As part of my series on “Things new X++ Developers Should know”. I have been writing a few basic howtos and checklists for new X++ Developers. These are really meant to be simple step by step guides to get new developers more productive by exposing the little secrets of the AX development that sometimes take years before discovering.

Today’s post is a checklist of things you need to have in place to ensure that you can debug X++ code.

  1. Enable debugging for your user. In an AX development window click on the tools menu item, then click options. Click on the development fast tab. Under debug mode set the option to “When Breakpoint”Enable_AX_Debugging
  2. Ensure your user is part of the local “Microsoft Dynamics AX Debugging Users” user group. On the machine which you are running the debugger on Edit your users and groups.
    Expand the “Groups” section and double click on “Microsoft Dynamics AX Debugging Users”. Click “Add” and enter your domain name and click ok.
    2015-05-25_1546You will need to restart your user session by logging off and back on again
  3. Ensure the server is enabled for debugging (needed for serverside code). Open up the Microsoft Dynamics AX Server configuration console from Windows administrative tools. On the “Application Object Server” tab enable “Enable breakpoints to debug X++ code running on this server” and “Enable global breakpoints”
    Enable server breakpoints
  4. Enable client debugging options (optional/advanced for business connector debugging). In the Microsoft Dynamics Client configuration console in Windows administrative tools enable the following: “Enable user breakpoints to debug code in the Business Connector and Enable global breakpoints to debug code running in the Business Connector or client.
  5. Ensure the debugger is installed on the client machine. Run the Microsoft Dynamics AX installer and ensure the “Debugger” (found under development tools is installed)
  6. If your code is running in CIL:  You can either follow the steps listed on MSDN or for simple debugging (i.e. logic errors) set your user to not run business logic in CIL via your user options form:
  7. Finally and most obviously you need to create breakpoints. You can do this in three ways.
    1. Navigate to the line of code that you want to debug. Press F9
    2. Navigate to the line of code and press the “Red circle” on your toolbar.2015-05-26_1502
    3. Finally you can physically type “debug” in your code to create a breakpoint. However this will enable it for all users in the system, not just for yourself.

I hope this checklist will help somebody stuggling with their debugging in AX. Please let me know if there are additional tips for debugging that this list may be missing.

For some additional details on debugging see MSDN:

Find all Menuitems Linked to a Form

For diagnostics purposes it is often useful to search the AOT for all objects matching cetain properties. For example you may want to find all display menutitems that are pointing to a specific form. The below job illustrates how to simply traverse the Display Menuitems node in the AOT to locate all items who’s “ObjectType” is “Form” and object is a specific form name. E.G. “PurchReqTable”.

static void FindMenuItemsForForm(Args _args)
 str find = "PurchReqTable";
 TreeNode root = TreeNode::findNode(#MenuItemsDisplayPath);
 TreeNode current;
 TreeNodeTraverser trav = new TreeNodeTraverser(root,false);
 current =;
 while (current)
 if ((current.AOTgetProperty('ObjectType') == "Form") && (current.AOTgetProperty('Object') == find))
 info(strFmt("Found menuitem %1",current.AOTname()));
 current =;



Adapting this to search other nodes is as simple as changing the original node instantiation to search a different path as well as changing the AOTgetProperty() method to search through the properties relevant to you.

Happy Daxing

Original community post:

14. Using Alt+[Up/Down] to rearrange the order of elements in the AOT.

As part of my series on “Things new X++ Developers Should know”. I have been writing a few basic howtos for new X++ Developers. These are really meant to be simple instructions to get new developers more productive by exposing the little secrets of the AX development that sometimes take years before discovering.

Today is the simple trick of moving elements up and down in list in the AOT using your keyboard. E.G. Re-arranging fields in a grid control or field group. Sometimes the mouse re-arranging produces unexpeded results and is quite frankly much slower.

  • Simply highlight (click on) an element of an object that makes sense to re-order e.g. a column in a form grid.
  • While holding in the “ALT” key use the up and down arrow keys of your keyboard to move the object up and down in the list


Notes on this functionality:

  • This functionality only works where it actually makes sense i.e. where where order actually matter like on grids and field groups. E.G. Moving your control above “methods” (in the screenshot) will have no effect and will automatically move it back down to directly below “methods” on re-opening the aot element.
  • This functionaly will do nothing on set elements in an Object e.g. “Methods”, “Datasources”, “Designs”, “Parts” etc…
  • If you’re a little OCD like myself and would like to re-arrange the fields (in the fields node) on a table object they will move when using Alt+[Up/down], but the change will not be permenant, even after saving. Field order doesn’t really make much difference in AX, apart from readability in the AOT. So if you want the primary key to be at the top of the list, then you must create it first (I haven’t found a workaround yet).
  • The same applies for ordering of methods in classes. The methods physically move but the change is not permenant
  • As above, even though you are physically able to, reordering the tables in the AOT makes no difference. They will always be revert to being alphabetical after re-opening the AOT.
  • Re-ordering objects in an AX development project does work! The elements will stay in the order that you arrange them.



8. Locate specific AOT object without scrolling

As part of my series on “Things new X++ Developers Should know”. I have been writing a few basic howtos for new X++ Developers.

Today’s post relates to quickly navigating to specific objects in the AOT without endless scrolling.

So often when working over the should of new developers or consultants exploring the AOT I see them scrolling endlessly or dragging the scrollbar back and forth for a while before finding the object they are looking for.

A common technique to navigate through lists in both Windows (e.g. My computer etc) and windows based environments (SQL management studio etc..) is to simply start typing the name of the object you are looking for. Windows automatically moves to the first object matching the sequence typed.

AX is by no means an exception to this rule. Simply click and expand the main node of the object you are looking for e.g. “Forms”
AOT Navigation Forms
and start typing E.G. “PurchReqT…..”
As you type AX will move to the first object found matching what you have typed so far..
E.G. P moves to PartitionAdministration,  Pu to PurchArgreement etc….

There are some bonus features when using this in AX:
1. You can always see what you have typed so far by looking at the bottom left of your screenAOT_Navigation_Status_Bar
2. The typing timeout is long compared to applications like SQL etc where you need to have taken a speed typing course to get this right. As long as you still see the search term in the bottom you can just continue typing (this normally takes around 7 seconds or until you use your keyboard arrows or mouse to do something different

I know this may be a very obvious tip, but I’ve witnessed too many people taking forever to find objects by scrolling to not include this in the “Things new X++ Developers Should know” series.



4. Drill through to code from Info log

As part of my series on “Things new X++ Developers Should know”. I have been writing a few basic howtos for new X++ Developers.

Today’s post relates to quickly navigating to the source code from where an info log error, warning or information message is called from.  It took me a while to figure out that for many info log messsages you can simply double click on the message in the info log window and the code that called the message will be displayed for you.

E.G. If you see the normal error log icon or warning icons with a small arrow in the bottom left corner, you are normally able to double click the message to see the code behind it. These icons look like this:


Error Log

Infolog Info

Info Message

Warning Message

Warning Message





Simply Double click the message as below


To be presented with the code that called it.



NOTE 1: If you have your “Execute business operations in CIL” user option enabled, a lot of business logic like postings etc will not allow you to drill down.

NOTE 2: If the code calling the info message makes use of the SysInfoAction parameter, you will be taken to an alternate form specified by the developer and not the source code. (See Axaptapedia Article)

3. Drilling down to the parent type of an object in the AOT.

As part of my series on “Things new X++ Developers Should know”. I have been writing a few basic howtos for new X++ Developers.

Today’s post relates to quickly navigating to the source or parent type of an object in the AOT. This is often useful to drill through to a parent object to discover, debug or modify properties and code. The following are some examples of drill-downs you can perform

1. Open the Data Dictionary Table from a Form’s datasource
2. Open the Data Dictionary Enum used from a table field
3. Open the Extended Data Type used by a table field
4. Open the AOT Form object (or class, report etc) from a Menu-item object
5. Open the Data Dictionary Table object from a Query datasource
6. Open a parent EDT from an extended EDT
7. Open a parent class from an extending class.


1. Open the object in question e.g. a Table field.
2. Right click on the field.
3. Select “Add-ins”
4. Select Open new Window
5. Click “Open used Extended Data Type”

6. The parent type is now displayed in a new window. In this example the ProjId EDT is displayed

7. Determine Field name of control on an AX Form

As part of my series on “Things new X++ Developers Should know”. I have been writing a few basic howtos for new X++ Developers.

With some of the more complex forms in AX 2012 it can sometimes be quite tricky to navigate through the form hierarchy in the AOT to debug which table and field certain controls on your form are bound to. So today I’ll cover how to determine the Table and Field name or the name of a control directly from an AX Client form. A quick and easy way to do so is to simply use the “personalise” function in AX.

NOTE: This requires you to have system administrator privileges (which you probably have if you are a developer)

1. From any form in AX. Right click on the form control or field that you would like to diagnose.
2. Click “personalise”


3. From the personalise screen you can now view the following:



#1. The location in the Design node of the AOT where the control resides
#2. The name of the Control in the AOT
#3. The name of the AOT Table name that the control is bound to
#4. The name of the datasource on the form that the control is bound to (normally the same as the Table Name)
#5. The name of the field on the table that the control is bound to




2. Drilling down to the AOT from an open form

As part of my series on “Things new X++ Developers Should know”. I have been writing a few basic howtos for new X++ Developers.

Today we cover how to determine the AOT name of the current form that you are accessing and edit it directly without having to go through the tedious process of navigating/searching in the AOT. This can be very useful in increasing productivity as well as debugging functionality

1. From any form in AX right click on an control.
2. Click “Personalise”.



3. Select the “Information” tab.
4. The AOT name of the form is visible under “Form name”.
5. Click Edit to acess the form in the AOT.

Note: This won’t work for forms created in code like dialogs etc..

Things new X++ Developers should know

developer-iconSince my start in X++ development over 6 years ago there are many small things that I have learnt that I wish I had known from the start. Small things that won’t necessarily help you post a stock journal from code or perform complex integration tasks, but none the less makes your day ever so much more productive. If you are a seasoned developer you will most probably already know most of these, but I thought I’d put them all down in a neat list for new guys to go through. Here are some of my favourites along with links to short articles on how to do them. (I will hopefully add some more over time).

1. Keyboard Shortcut to view properties of an AOT element: Simply Hit “Alt+Enter” on any AOT element to view its’ properties list. Much quicker than fumbling with right clicking on the mouse. (view more shortcuts)
2. Drilling down to the AOT from an open form: Instead of reverse engineering forms from menu structures or navigating in the AOT to edit a specific form, simply right click on any form, click “Personalise”, select the “Information” tab, click on the “Edit” button next to the form name. (view details)
3. Drilling down to the dictionary type of an object in the AOT. E.G. Edit enum or EDT being used by a field on a table. Navigate to an element in the AOT e.g. A enum field on a table. Right click on the element, click “add-ins”, click “Open in new Window”, click “Open used Enum” etc…. (view details)
4. Drill through to code from Info log – Quite often the info log will allow you to drill down into the code the called the error message. If you notice a small arrow on the error icon you can simply double click on the line to take you to the code. (view details)
5. Infolog code drill down does not work if code is running in CIL. As an addition to the above you will not be able to drill down to code if it is running in CIL. For DEVELOPMENT/DEBUGGING purposes only you can simply disable code from running in CIL in your User Options.
6. Run AX as an alternative user. For debugging security or processing workflow it is often needed to run AX as an alternative user. Simply press Shift and right click on the AX icon on your desktop. You can then select “Run as different user”. (view more)
7. Determine Field name from control on Form. Sometimes you need to quickly find out the database table and field that is shown on a form without navigating through the complex AOT form. Simply right click on the field, click “personalise”. Under “System Name” you will see the following: Control name, Datasource Name, Table Name and finally Field Name. (view details)
8. Locate specific AOT object without scrolling. This may be an obvious one as Windows uses this technique in many other applications. Open the AOT and expand and click on the main node of the object you are looking for e.g. Classes. Then simply type the name to navigate to the specific object. (view details)
9. Creating an Development Environment shortcutAs a developer you don’t necessarily want to login to the Dynamics AX front end whenever accessing the AX shortcut, but rather want to open a development workspace directly. To do so right click on the AX shortcut on your desktop, click properties, on the shortcut tab in the “target” field add “-development” after the path to the Ax32.exe file. (View step by step)
10. Enabling breakpoints / debugger. One of the most important tools in a developers toolbag is the debugger. There are a few items on the checklist that you should ensure before you can successfully debug code: View them here.
11. Enabling viewing of Layer and Models. In a complex AX environment it is very useful to know what model and layer an object forms part of in order to search for patches or fix yourself. You can easily enable the AOT to display these by navigating to: File -> Tools -> Options -> Development -> Application Object Tree -> Application Object layer -> Select “Show All layers” and Application Object Model -> “show on All elements”.
12. AX Layer Config files. Create AX shortcut files to allow you to easily logon to the layer of your choice. View how here. (link available soon)
13. Profiler / SQL Trace. You can easily make use SQL Tracing or profiler to see the exact SQL being executed behind the scenes. This can be very useful for debugging purposes. (link available soon)
14. Using Alt+[Up/Down] keys to reorder AOT elements. To rearrange object elements like controls on a form grid simply hold in ALT and press the Up and Down keys to rearrange its order in the parent. (view details)

Anyway thats my list for now. Please let me know of any other quick tips and tricks that you think new developers (or old) should know about!

Keep a lookout for some more detailed explainations on some of these coming up in the follow days.

For some more advanced tips, tricks and coding patterns please also checkout the knowledge base at


Environment based Dynamics AX Color coding

Before I start: As a disclaimer, I’m posting this to show a potential way to solve this issue or similar issues, and to spark thought not necessarily as a production recommended solution.

I have had the requirement in the past to ensure that our environments (DEV, UAT and PROD) are reliably color coded to reflect the true environment that is currently open. This should not be application dependent (code only existing in individual environements) or database dependent (settings residing in the database) as these may change, be restored or be overwritten.

The best solution out there on how to physically color forms is Palle Agermarks’ solution. I would recommend you look at his code to get started as this is not the primary purpose of this post.

This solution however relies on a database table with the required color settings. This means that if a database is restored the color settings in UAT may reflect the color settings in Prod. For some purposes this may be ok or indeed what is needed, but we want to be able to clearly and confidently differentiate between our environments without having to remember restore scripts etc.

To do this I took Palle Agermarks‘ color coding code and modified it to look (in code) at what the current database is and color code my environment accordingly. Unfortunately this does require a bit of hard-coding a set of database names, but the colors will change correctly regardless of database or application loaded.

The key to this is to use SysSQLSystemInfo::construct().getLoginServer(); to determine the current database server you are connecting to.

public void setFormStatusBarColor()
 int a,r,g,b;
 Color color;
 str serverName = SysSQLSystemInfo::construct().getLoginServer();
 if (formRun)
 switch (serverName)
 case "MYDEVSERVER" : color = "33CC33"; //green
 case "MYPRODSERVER" : color = "FF9933"; //red
 case "MYUATSERVER" : color = "0066FF"; //blue
if (color)
 a = 254;
 [b,g,r] = WinAPI::RGBint2Con(hex2Int(color));


Some variations on this, depending on your setup, would include looking for keywords in your server names instead of the whole name to determine what environement is being used. E.G. Does servername contain “DEV”. This may make it a bit more flexible and re-usable.

Creating a Custom Workflow Due Date Provider

Although not often needed within workflow, one sometimes has the requirement to set due dates, escalation dates etc based on some sort of custom criteria E.G Complete by My Birthday or Complete at least one day before the documents requested date. Recently on the Dynamics AX forum this question was raised ( so I thought I’d write up a “short” post on how to create a custom WorkflowDueDate provider.

1. Create a new class in the AOT that implements “WorkflowDueDateProvider” e.g. MyCustomDueDateProvider
public class MyCustomDueDateProvider implements WorkflowDueDateProvider

2. Create method getCalendarTokens

The getCalendarTokens method will return a list of items that will display in the Time Limit’s Calendar option in your workflow configuration.
You can return any list of items here that you would like to allow the user to select for resolution. For example in the standard Calendar Due Date provider a list of all the configured calendars in the system. However you could customise this to return an entirely personal list of options such as “My Birthday” and “My Anniversary” that will set the workitem’s due date to my next birthday (26th of June 2015) or next anniversary (24 of March 2016). You could also provide an option that is document specific such as “1 Day Before Requested Date”. For this example I am going to use these options to illustrate the true arbitrary nature of the tokens.

public WorkflowCalendarTokenList getCalendarTokens()
    WorkflowCalendarTokenList tokens = WorkflowCalendarTokenList::construct();
    tokens.add(“MYBIRTHDAY”, “My Birthday”);
    tokens.add(“MYANNIVERSARY”, “My Anniversary”);
    tokens.add(“1DAYBEFOREREQ”, “1 Day Before Requested Date”);
    return tokens;

3. Create the resolve and resolveNonUser methods

After creating the tokens list we need to create a way to resolve the specific option that the user has selected in his configuration. I’ve kept my code very simple (and hardcoded) to illustrate how this works.

public WorkflowDateTime resolve(WorkflowContext _context, WorkflowCalendarToken calendarToken, WorkflowTimeSpanMinutes _timeSpanMinutes, WorkflowUser _userId)
    Date tmpDate;
    WorkflowDateTime ret;
    PurchReqTable req;
    if (!_calendarToken)
        throw error(“@SYS105450”);

    if (_calendarToken == “MYBIRTHDAY”)
        tmpDate = str2DateDMY(“26062010”); //specific date
        ret = DateTimeUtil::newDateTime(tmpDate, 0);
        ret = MyCustomDueDateProvider::nextDate(ret);
    else if (_calendarToken == “MYANNIVERSARY”)
        tmpDate = str2DateDMY(“24032010”); //specific date
        ret = DateTimeUtil::newDateTime(tmpDate, 0);
        //next date is a custom method that simply finds the next occurance of my birthday by adding years to the provided date until it is greater than today.
        ret = MyCustomDueDateProvider::nextDate(ret);
    else if (_calendarToken == “1DAYBEFOREREQ”)
        if (_context.parmTableId() == tableNum(PurchReqTable))
            //retrieve original document form WorkflowContext
            req = PurchReqTable::find(_context.parmRecId());
            ret = DateTimeUtil::newDateTime(req.RequiredDate,0);
            ret = DateTimeUtil::addDays(ret, -1);
            throw error(“Cannot use 1DAYBEFOREREQ with any document except PurchReqTable”);

return ret;

For this example we are not going to use user specific resolution, so the resolveNonUser and resolve methods will return the same values

public WorkflowDateTime resolveNonUser(WorkflowContext _context,
WorkflowCalendarToken _calendarToken,
WorkflowTimeSpanMinutes _timeSpanMinutes)
return this.resolve(_context, _calendarToken, _timeSpanMinutes, ”);

4. Create new and construct methods

protected void new()

public static MyCustomDueDateProvider construct()
return new MyCustomDueDateProvider();

5. Create a due Date provider in the AOT.

1. Navigate to Workflow -> Providers -> Due Date Calculation
2. Right click, click “new Due Date Calculation Provider”
3. Right click on your new provider and click properties.
4. Provide an appropriate name e.g. “MyCustomDueDateProvider”
5. Provide a relevant label. This will appear in your workflow configuration under “Calendar Name”
6. Depending on how you have coded your provider you may need to select an Association Type of company and AvailableForAllWorkflowTypes as “no” if you rely on company specific information or on record specific information.
7. Most importantly: Select the the class that you have created under “ProviderClass”

6. Perform CIL Compile and restart your client
7. Configure your workflow:
 Open your workflow configuration and navigate to the place where you would like to make use of your new functionality. E.G. Any Assignment’s “Time Limit” tabYou should now be able to select your provider under the “Calendar Name” option and select the resolution type under the “Calendar” option. Note our code didnt make use of the “_timespanInMinutes” parameter so the Duration option can be set to anything. We could have used this parameter to increase the flexibility on the “Before Requested Date” option if necessary.

I hope this assists someone sometime! Happy Daxing

Workflow Notifications to Custom list of Users

Problem statement: It is quite frequent in workflow in Dynamics AX that one would like to notify users when certain approvals have occurred, tasks have been completed or when errors occur. This is pretty easy to accomplish out of the box with Dynamics AX by using the notifications on approvals, tasks or on the workflow as a whole. However the options are pretty limited and not very dynamic (especially in AX 2009) and up until AX2012 you have only really been allowed to assign to specific users (i.e. by user id). This means that it is very difficult to accomplish complex notifications such as notify the following people when a document has been approved: Document Creator, Project Manager for the document’s project and all users assigned to the “Accountants” security role in AX.

AX 2012 however has now allowed you the ability to make use of “Participant Providers” as an assignment option in notifications.

This means that you can create a Custom “notification” participant provider for your system that can resolve any number of personalised lists of users as above.

For example we created a particpant provider with a couple these lists. In our custom participant provider we returned a unique token per list e.g. “Originator, Project Manager, Requester and CEO” and “Originator, Project Manager, Financial Manager and CEO”.

In the resolve method of the participant provider we then retrieved the workflow document out of the workflow context object and returned the “Created by” user,  looked up the project on the document and returned the associated Project manager and finally looked up the Financial Manager and CEO from a custom parameters table in AX and returned them as well.

The actual creation of a custom participant provider is beyond the scope of this article but you can find some more resources over here:

I hope this sparks some thought and is useful to some:

Inspired by:

Finding orphaned Records in tables using RefRecId

Dynamics AX makes us the RefRecId, RefTable and RefCompany data pattern in a number of tables the system to provide flexible linking from a common/generic table such as WorkflowWorkitemTable to a variety of specific tables such as PurchReq or PurchTable.

Examples of this include Workflowtables, DocuRef, SpecTrans,  etc…

From time to time you may want to identify which of the records in these tables have become “orphaned” i.e. the documents that they refer to no longer exist. To do this in a fairly generic way you can make use SysDictTable’s makeRecord functionality as below (Using DocuRef as an example)

static void Check_Orphans(Args _args)
SpecTrans specTrans;
DocuRef docuref;
counter i;
Common record;
SysDictTable table;

while select forupdate * from docuref// where SpecTrans.RefTableId == 865 && SpecTrans.RefCompany==’an’// 866 for Debtors
table = new SysDictTable(docuref.RefTableId);
record = table.makeRecord();
select firstonly * from record where record.RecId == docuref.RefRecId;
info(strFmt(“Record %1 has been orphaned”, docuref.caption()));
//Delete if necessary over here…
info(strFmt(“%1 orphaned records found”,i));

I hope you find this a useful trick in your AX wanderings.

Workflow: User Selectable Approver

A question that has come across on a number of occassions on the Dynamics Community forum is how can one allow the creator of a document to select an approver to approve the document. We did do a variation on this request for a client a couple of years ago, so here is one way to do it.


1. Create a custom field to store the approver on the record you are workflowing
2. Allow the user to populate this field (either directly on the record’s form, or via a pop-up request) on submission.
3. Create a custom participant provider that can resolve the user selected in #2
4. Modify your configuration to use this participant provider.

For this example I will make use of the PurchReqTable and its workflows

1. Create Custom Approver field

  1. Open the AOT, Data Dictionary, expand Tables, locate PurchReqTable. Expand the node and expand the fields node.
  2. Right Click on fields, click new -> String
  3. Rename your field (e.g. ChosenApprover) and provide a suitable Label


2. Allow the user to populate this field
Option A – Allow modification directly on the form:

  1. Open the AOT, expand the forms node, locate and expand the PurchReqTable node.
  2. Right click on data sources, click “open in new window”
  3. Expand the PurchReqTable datasource, expand the fields node
  4. Drag the “Chosen Approver” field to a relevant place on your form E.G. Designs->Design->Tabl->TabPageDetails->TabDetails->TabPageheader->TabHeader->TabPageHeaderGeneral->HeaderAdministration


Option B:

  1. Locate the Class behind your workflow’s Submit button. E.G. PurchReqWorkflow.
  2. Before the code line “if (ret && purchReqWorkflow.dialogOk())’ add code to prompt the submitter to enter a user.
  3. Save the selected user to the PurchReqTable


3. Create a custom participant provider to resolve the ChosenApprover

  1. Open the AOT, right click on Classes, click “New Class”
  2. Rename Your class to “ChosenApproverParticipantProvider”
  3. Edit the class declarationand implement the “WorkflowParticipantProvider” interface
    E.g. class ChosenApproverParticipantProvider implements WorkflowParticipantProvider
  4. Create a new method called “getParticipantToken” with the following code to present a single resolution option to the users…
    public WorkflowParticipantTokenList getParticipantTokens()
    WorkflowParticipantTokenList tokens = WorkflowParticipantTokenList::construct();
    tokens.add(“CHOSENAPPROVER”, “User selected Approver”);
    return tokens;
  5. Create a new method to resolve the token above called “resolve” with the following code (this code assumes that the provider will only be used from a purchase requisition and will not have resolution options other than “chosenApprover”, also it assumes that all requisitions will have the ChosenApprover field filled in:
    public WorkflowUserList resolve(WorkflowContext _context,
    WorkflowParticipantToken _participantTokenName)
    PurchReqTable purchReqTable;
    WorkflowUserList userList = WorkflowUserList::construct(); //Retrieve the requisition from the workflow context
    purchReqTable = PurchReqTable::find(_context.parmRecId());
    userList.add(PurchReqTable.ChosenApprover); return userList;
  6. Save your class.
  7. Expand the Workflow node in the AOT, expand “providers”, right click on “participantProviders” and click “New Participant Assignment Provider”
  8. Rename the Provider to ChosenApproverParticipantProvider (similar to your class name)
  9. Right click on the provider, click properties.
  10. Provide a suitable label for the provider e.g. “Chosen approver provider”
  11. If your record is a cross company table select AssociationType of “Global”
  12. Choose “No” under “available for all workflow types” as this provider assumes that a PurchaseRequisition is being used.
  13. Under “ProviderClass” enter the name of your class created above. “ChosenApproverParticipantProvider”
  14. Associate your provider with the PurchReqWorkflow type: On expand your “ChosenApproverParticipantProvider” AOT node, right click on “workflow types”, click “new workflow type”. Right click on the newly created node, click properties, select the relevant workflow type under the “workflowType” Option. E.G. PurchReqReview
  15. Save the ParticipantProvider.

4. Modify your configuration to use this participant provider.

  1. Perform a CIL compile and close and open AX client for your changes to take effect.
  2. Navigate to your workflow configuration and click “edit”. E.G. Procurement and Sourcing -> Setup -> Procurement and sourcing workflows -> Select PurchReqReview configuration.
  3. Locate the node that you would like to assign to your Chosen User. Click assignment in the toolbar.
  4. On the assignment type tab, select Participant
  5. Click on the “Role Based” tab.
  6. Under type of participant select “Chosen Approver Provider”
  7. Under Participant select “User selected Approver”
  8. Save and close your workflow
  9. Ensure you activate the workflow version you just created!

All done! Test and enjoy!

Adding code templates/shortcuts in AX 2012

If you’ve got any blocks of code that you use frequently, e.g. specific comment blocks, you can very easily add code short cuts in AX 2012 to auto-insert the them in to your X++ code.

For example you can setup AX to automatically create surrounding comment such as

whenever you type “mycom” and press the tab key.

How do you accomplish this. Very easily!

Step1: Locate the class EditorScripts in the AOT.
Step2: Create a new method with the format public void template_flow_[shortcut](Editor editor)
Step3: User the editor parameter to add code the code that you would like inserted. e.g. editor.insertLines(“\\test comment”);
Step4: Add your method to the case statement in the isApplicableMethod method in the section relating to template “editor scripts that does not apply to Macros” 

Thats it, now if you type your shortcut into any editor in AX and press tab, the “\\test comment” code will be inserted.

Here’s a full example method

The above creates the following output:


Repost from my old blog:

Form Parts: Creating form method callbacks

Problem description: Form parts in Dynamics AX usually make use of linked data sources to activate changes. However there may the case that your form part does not have a direct datasource link to the parent form or simply needs to activate code to populate the info displayed. In this case one needs a mechanism to call code on the form part when the record on the parent form is changed.

Solution: To resolve the issue one needs to create method call-backs between the two forms. Two approaches need to be followed based on whether the form part has been added to a list page or to a normal form.

Standard forms

  1. Create your form and form parts.
  2. Add your form part to your main form
  3. On your main form create a reference to your form part in the class declaration e.g. Object _part;
  4. Create a method on your main form e.g. “registerForChange(Object _part); with the following code:
    public void registerForChange(Object _part)
        part = _part;
    This method will allow your form part to provide a reference of itself to the main form.
  5. On your form part’s init method. Call this method register call the above method passing itself as a reference. Note: you will need to perform step #4 on all forms that will use this form part.
    public void init()
        Object caller;
        caller= args.caller();
  6. On your form part create an doRefresh method, your main form will call this method whenever a form part refresh is needed. This method can have an parameter that your would like the main form to pass through. In this example we will pass the active record from the main form  E.G.
    publicvoid doRefresh(Common _record)
    //Do custom form part refresh.
  7. Finally, on your main form, call the the method in #6 at the appropriate time. In this example calling “part.doRefresh(myTable);” in the myTable datasource’s active method works well. You could also do your call from a button on the main form or on any other trigger.

ListPage variation

If you are planning on using the form part as part of a list page. You need to make the following adjustments.

  1. Create a reference to your part in the list page’s ListPageInteractionClass’ ClassDeclaration e.g. Object part;
  2. For step #4 add the “registerForChange” to your list page’s ListPageInteractionClass
  3. For step #5 detect whether your part is being called from a ListPage or a normal form: E.G.
    public void init()
        Object caller;
        SysSetupFormRun formRun;
        caller= this.args().caller();
    formRun = caller;
    if (formRun.pageInteraction())
    caller = formRun.pageInteraction();
            } else
  4. On the relevant method in your list page interaction class call the part’s doRefresh method. For this example use the selectionChanged method
    public void selectionChanged()
    ListPage listPage = this.listPage();
    if (listPage.activeRecord(“MyTable”))



Mass Reassign Workflows

Challenge/Problem: Many Dynamics AX Workflow work-items that need to be reassigned at once.

Description: At times we have had the request from clients to reassign many workitems from one person to another. My first reaction is why weren’t delegation parameters setup on the user so that one doesn’t need to manually reassign. However I have come to realise over time that there are a couple of good reasons to do so such as a person falling ill suddenly, a mistake in the workflow config, failure to set delegation parameters in time etc…

Solution: The following script/job designed for AX workflow will reassign workitems from one user to another. You can modify your query a bit to restrict the items to just the one that you want. The attached one simply reassigns all items currently assigned to user “123456” to user “654321”.

NOTE: This will not affect items in your workitem list as a result of queues

static void workflowMassReassign(Args _args)
    UserId fromUser = "123456"
    UserId toUser = "654321";
    //Comment for workflow history
    str comment = "Auto-Reassign 2014/11/26 08:00";
    WorkflowWorkItemTable workitems;
    int i;
    while select workitems where workitems.Status == WorkflowWorkItemStatus::Pending && workitems.UserId == fromUser 
        WorkflowWorkItem::delegateWorkItem(workitems.Id, toUser, comment);
    info(strFmt("Items re-assigned: %1",i));

Datasource Save, method execution order

Screen Shot 2014-11-17 at 4.10.15 PMWhen saving records in a form in Dynamics AX a lot of methods are fired off both on the form as well as on the table itself. I haven’t found another flow diagram describing what methods are fired and in what order, so I tested and found the results displayed in the diagram to the left:

  1. Form’s Validate() method on the datasource is called
  2. When super() is called with in the validate() method, the table’s validateField() method is called for each field
  3. Code placed after the super() in the form’s validate method is called
  4. Form’s validateWrite() method on the datasource is called
  5. When the super() is called in the validateWrite() method, the table’s validateWrite() method is called
  6. Code placed after the super() in the form’s validateWrite() method is called
  7. Form’s write() method is called.
  8. When the super() is called in the write() method, the table’s insert() method is called.
  9. Code placed after the super() in the form’s write() method is called.

Comment below if you have corrections or additions to this diagram.
Happy daxing.

Synchronize Dynamics AX DB in X++

Challenge/Problem: Synchronise Dynamics AX database from X++

Description: Previously I have written code to manipulate AX AOT objects via code (reflection) and found the need to kick off a database sync automatically from X++ code. I found the code snippets below to be useful for this operation.

The following two options allow you to perform the db syncronisation.

1. To synchronize a specific table: appl.dbSynchronize([tableid]);
2. To synchronize the whole app: appl.dbSynchronize(0);

Mass Resume Line Workflows

Challenge/Problem: Many line level workflows that need to be resumed.

Description: Sometimes due to data or setups one may have numerous line level workflows failing and entering a “Stopped” state. This may be a result of calendars that do not have enough dates created, users who have been disabled etc… If the workflows were header level, it is easy enough to select all in the Workflow History form and click resume, however on line level workflows one needs to view each line level workflow individually and resume them.

Solution: The following job can be used to perform mass resume on stopped workflows. You can adapt the SQL to limit to certain documents or document types of necessary.

static void resumeStoppedWorkflows(Args _args)
    WorkflowTrackinStatusTable tracking;
    int i, j;
    while select tracking where tracking.TrackingStatus == WorkflowTrackingStatus::Faulted
&& tracking.WorkflowType == WorkflowTrackingStatusWorkflowType::DependentSubworkflow
        try {
            Workflow::resumeWorkflow(tracking.CorrelationId, "Auto-resumed");
        catch (Exception::Error)
            //Some may not be able to be resumed but we dont want to stop the process
    info(strfmt("%1 workflows resumed, %2 workflows could not be resumed"));

Sync System Email Templates to all companies.

Challenge / Problem: Maintaining email templates across multiple companies.

Descritpion: Dynamics AX makes use of email templates for various bits of functionality in Dynamics AX, including workflow notifications and alert notifications. If you are using workflow in multiple companies and want to keep the same workflow template across the board, it can be quite frustrating to have to make the same changes in every company. The following script/job in X++ will help sync all (or some) system email templates and their respective languages into every company in Dynamics AX.

/// Copies All System Email Template to all companies
/// WARNING: Will create or overwrite existing templates in other companies
static void syncWorkflowTemplates(Args _args)
    DataArea  DataArea;
    SysEmailSystemTable email;
    SysEmailTable local;
    SysEmailMessageSystemTable message;
    SysEmailMessageTable localMess;
    WorkflowParameters params;

    void FindOrCreate()
        local = SysEmailTable::find(email.EmailId, true);
        if (local.RecId)
            info(strFmt("Deleting %1 (%2)", local.EmailId, curext()));
        local.DefaultLanguage = email.DefaultLanguage;
        local.Description       = email.Description;
        local.EmailId           = email.EmailId;
        local.Priority          = email.Priority;
        local.SenderAddr        = email.SenderAddr;
        local.SenderName        = email.SenderName;
        info(strFmt("Adding %1 (%2)", email.EmailId, curext()));

    void FindOrCreateMessage()
        localMess = SysEmailMessageTable::find(message.EmailId, message.LanguageId, true);
        if (localMess.RecId)
            info(strFmt("Deleting %1 %2 (%3)", localMess.EmailId, localMess.LanguageId, curext()));
        localMess.EmailId       = message.EmailId;
        localMess.LanguageId    = message.LanguageId;
        localMess.LayoutType    = message.LayoutType;
        localMess.Mail          = message.Mail;
        localMess.Subject       = message.Subject;
        localMess.XSLTMail      = message.XSLTMail;
        info(strFmt("Adding %1 %2 (%3)", localMess.EmailId, localMess.LanguageId, curext()));
    // Restrict to specific templates in a where clause if necessary
    while select email
        while select DataArea where !DataArea.isVirtual && != email.dataAreaId
            changecompany (DataArea.Id)
            while select message where message.EmailId == email.EmailId
                changecompany (DataArea.Id)


Model Management: Tools – Eventing II (validateWrite)

Following up on my previous post on the use of Eventing for model management today’s post will demonstrate how to use eventing effectively on the validateWrite method of tables. This can be very useful for additional model specific data validation without overshadowing the original method.

In this example I will use the validateWrite of the PurchReqLine table.


1. Create a new class e.g. MyPurchReqLineEventHandler

Screen Shot 2014-10-22 at 9.06.50 AM
2. Create a new static method in this class e.g. public static void validateWritePurchReqLine(XppPrePostArgs _args)
3. In the class retrieve the current boolean return value so that you can take it into account: boolean ret = _args.getReturnValue();
4. Get the original PurchReqLine Table record so that you can use it in your logic: PurchReqLine line = _args.getThis();
5. Add your logic to the method taking into account the current return value e.g.
if (ret)
ret = purchReqLine.myField != “”;
6. Set the return value (either at the end of your method or within the if (ret) statement: _args.setReturnValue(ret);

Screen Shot 2014-10-22 at 9.24.58 AM

7. Create the event subscription
7.1 Navigate to the PurchReqLine table in the AOT
7.2 Expand the methods section.
7.3 Right click on the validateWrite method. Click “New Event Handler Subscription
Screen Shot 2014-10-22 at 9.20.55 AM
7.4 Rename the Subscription to a name that reflects your model
7.5 Modify the CalledWhen property of the Subscription to “Post”
7.6 Modify the Class property of the Subscription to “MyPurchReqLineEventHandler”
7.7 Modify the Method property of the Subscription to “validateWritePurchReqLine”
Screen Shot 2014-10-22 at 9.33.41 AM
7.8 Save the class.

You’re all done. Now test and enjoy.
Please let me know if you have any comments or suggestions on the above. Keep an eye out some more samples like this in the next few days and weeks.

Model Management: Tools – Eventing

Since AX 2012 brought in the concept of models I have been very interested in utilising them to their full potential with our clients and our products. With certain things such as entirely new tables, classes, forms etc, the model concept works very well. It even works well when it comes to individual components on forms or new fields or methods as they are all regarded as individual objects in AX that can be plugged in and out of AX with models.

Where things start to become a bit harder is on shared objects such as standard methods etc. So how do we overcome some of these challenges. Hopefully over the next while I will post some useful design patterns and tools that one can use to keep one’s models clean and separated where at all possible. An added bonus of keeping your code separate is that it make performing Cumulative updates or 3rd party updates alot easier as there is less overshadowing.


One of the most useful tools for keeping models separate is the new Eventing functionality in Dynamics AX 2012. Eventing has a number of benefits, but in regards to model management eventing allows one to keep your code (the event handler method) in a separate model to calling class as well as keeping the event subscription that calls your code in your separate model.

Eventing on Table Methods e.g. initFrom

Using event handlers and subscriptions on table methods are one of the areas that are very useful for model management. For example you may have added new fields to a standard table such as PurchTable that you would like to initialise as part of the “initFromRFQTable” method without overshadowing standard AX code. Using event an event handler you could do the following;

1. Create New class e.g. MyEventHandler
2. Add a new static method to the class e.g. initFromRFQTable that accepts an XppPrePostArgs object as a parameter.
3. Get a reference to the calling object, in this case the PurchTable e.g. PurchTable purch = ppArgs.getThis();
4. Get a reference to the calling method’s parameter e.g. _purchRFQTable
5. Perform any initialisation that is necessary e.g. purch.MyField = rfq.MyField;

public static void initFromRFQTable(XppPrePostArgs ppArgs)
   PurchTable purch = ppArgs.getThis();
   PurchRFQTable rfq = ppArgs.getArg('_purchRFQTable');
   purch.MyField = rfq.MyField;

Note that this method has access to all the parameters of the PurchTable::initFromRFQTable as well as access to the PurchTable object itself, so you can perform close to anything that you would be able to perform in the method itself.

For a direct example look at how Microsoft has done this for localisations on the PurchTable’s initFromVendTableMethod.

In the next few weeks I’ll publish more model management tools, tricks and design patterns. If you have any of your own please let me know as well.


Active Directory Lookup in AX 2012

As you may be aware by now, AX allows one to create users of type “active directory group” which if setup will auto-create users who belong to that group when they try to login. Furthermore users (whether auto-created or manually created) who belong to these groups will inherit the security permissions assigned to these groups.

One challenge however is, to debug this. I.E. Finding out which users are members of specific groups or what groups a specific user belongs to. My previous post was about how to determine ownership via command line. After a bit of reflection I thought this may be better and more useful to have this functionality directly within AX. Using Attached is an XPO with the relevant code (use at your own risk).

Screen Shot 2014-09-08 at 12.37.46 PM


Basically it adds a class to AX as well as a lookup menu item to UserListPage form and the User form.

Please let me know your comments.

Here is a sample job if you don’t want to download the full project. It prints all groups for a user.

static void adGroups(Args _args)
    System.DirectoryServices.AccountManagement.PrincipalContext yourDomain;
    System.DirectoryServices.AccountManagement.UserPrincipal user;
    System.DirectoryServices.AccountManagement.GroupPrincipal p;
    CLRObject groups, enum;
    System.String domain, username1,groupName;
    str groupN;
    Userid userId = curUserId();
    InteropPermission permission;

    UserInfo userInfo;
        permission = new InteropPermission(InteropKind::CLRInterop);

        yourDomain = new System.DirectoryServices.AccountManagement.PrincipalContext(System.DirectoryServices.AccountManagement.ContextType::Domain);

        // find your user
        userInfo = xUserInfo::find(false, userId);
        domain = UserInfo.networkDomain;
        username1 = UserInfo.networkAlias;
        user = System.DirectoryServices.AccountManagement.UserPrincipal::FindByIdentity(yourDomain, username1);

        // if found - grab its groups

        if(user != null)
            groups = user.GetAuthorizationGroups();
            enum = groups.GetEnumerator();

            while (enum.MoveNext())
                p = enum.get_Current();
                groupName = p.get_Name();
                groupN = groupName;

     catch (Exception::CLRError)


The client cannot download the services metadata from…

Problem / Symptoms: You receive the following message whenever running code or services running in CIL:  The client cannot download the services metadata from http://[SERVERNAME]:8101/DynamicsAx/Services/AxClient?wsdl. The metadata address of the AOS services is incorrect or the AOS services are down. Please contact your system administrator.

Description: When running code in CIL (e.g. Services, batch jobs, Reports etc) you may receive the above error message. The cause of this problem could be multiple, but it basically means that the AOS or client cannot connect to the AX2012 services for one reason or another.

Screen Shot 2014-08-13 at 3.59.55 PM


Resolution: This could possibly be a DNS or some networking failure that you can test by trying to ping the the server that the services run on and resolving the issue as needed.

In our specific case, we experienced an issue that is probably very rare, we have a proxy server configured on the AOS server’s Internet options. However the “Bypass proxy server for local addresses” was not selected, therefore the server could not even access services located on itself. To resolve:

  1. Open Internet Explorer on the AOS.
  2. Click on the settings icon
  3. Click Internet Options
  4. Select Connections
  5. Click “Lan Settings”
  6. Ensure the “Bypass proxy server for local addresses” is checked
  7. Close all screens
  8. Restart AX client and run your code again.

Screen Shot 2014-08-14 at 11.05.52 AM

Using JSON in Dynamics AX

Repost from:

I’ve recently had a requirement to integrate an external system (Toggl with Dynamics AX 2012’s Timesheet system. However the external system only provided a JSON API which isn’t supported natively by the Dynamics AX AIF system.  After some research and trial and error (using various DLL’s) I eventually stumbled across some really useful classes provided by the Retail module in Dynamics AX2012. These classes (although named “Retail…”) provide a really easy and elegant JSON interaction for any use. Here is a very basic code sample of how to consume JSON using these classes in Dynamics AX 2012.


static void myJob(Args _args)
    RetailWebRequest request; 
    RetailWebResponse response; 
    str rawResponse, value; 
    Map data; 
    RetailCommonWebAPI webApi = RetailCommonWebAPI::construct(); 
    request = RetailWebRequest::newUrl(""); 
    response = webApi.getResponse(request); 
    rawResponse = response.parmData(); 
    data = RetailCommonWebAPI::getMapFromJsonString(rawResponse); 
    value = data.lookup("elementname"); 
    info(strFmt("Element name: %1",value)); 

If you are interested in some more advanced examples of using JSON in AX (e.g. using authentication, retrieving subsets of info or arrays)  or doing some of your own integration into Toggl timekeeping please let me know and I’ll post some more info.


SSRS Report and Viewer Not displaying in AX2012 R2.

Problem / Symptoms: SSRS Reports executed from code under limited security permissions are not displaying in AX2012 R2 or above.

Description: When running an SSRS Report that is being kicked off via code from a user role with limited security permissions, neither the report nor the report viewer is displayed. No error messages are presented. Under elevated (admin) permissions the reports are displayed. The same user is able to execute normal reports via menu-items.

The debugger will fail in class: SRSReportRun.constructReportSettings on the line settings.SetWebServiceUrl(serverConfig.serverId(), serverConfig.reportServerURL());

Solution: I wasn’t able to find any specific security permissions linked to this error that would fix the security role, however I did discover that AX seems to have deprecated the use of the SRSReportRun class in favour of the SRSReportRunController class.

Old Code:

SrsReportRun srsReportRun;
srsReportRun = new SrsReportRun (‘MyReport.ReportDesign1’);

New Code

SrsReportRunController controller;
controller = new SrsReportRunController();