Best Practices: Coding Guidelines

Microsoft Dynamics AX 2012

Developer’s checklist when creating report solutions for Microsoft Dynamics AX 2012. The goal of this article is to promote coding guidelines that have been applied by the product development team to ensure consistency in the reporting solutions across the application. Many of the suggestions here stem from the hundreds of developer hours invested when migrating >1000 legacy production reports into Microsoft Dynamics AX 2012. Applying these strategies will help to ensure that your reports are robust and scale appropriately when deployed to production environments.

DO USE…. identifierStr to specify identifiers like parameter names

As explained in the MSDN article here, the identifierStr() method is used to convert an identifier into a string. Even though the article says that this method validates its argument in the AOT, the only check it seems to make is that its argument would be a valid identifier. The main benefit of using this method is that we don’t need to put the string in quotes like ‘BookId’; instead we can simply use identifierStr(BookId).

This method is mainly used in the contract class, for the parm methods. For example, the parm method can be decorated with the DataMemberAttribute attribute which specifies the parameter name. 

This can be specified using the identifierStr() method as follows:

  • DataMemberAttribute(identifierStr(DocumentDate)) <-- Correct
  • DataMemberAttribute (‘DocumentDate') <-- Incorrect

DO USE…. literalStr when specifying labels

As explained in the MSDN article here, the literalStr() method is used to validate a string at compile time. The parameter can either be a hard coded string (in which case, BP error for hard coded string will be thrown) or, as is more often the case, a label ID. The main benefit of using this method is that it validates the label ID passed to it at compile time and throws a BP error if an invalid label ID is passed to it.

This method is also often used in the contract class, for the parm methods. For example, the parm method can be decorated with SysOperationLabelAttribute attribute which specifies the label for the parameter.

This can be specified using the literalStr() method as follows:

  • SysOperationLabelAttribute (literalStr ("@SYS95927")) <-- Correct
  • SysOperationLabelAttribute ("@SYS95927") <-- Incorrect

DO USE…. ssrsReportStr to specify the report to be run by a Controller Class

Similar to the identifierStr and literalStr methods, the ssrsReportStr() method parses the 2 values passed to it – the report name and the design name – to validate whether it represents a valid report or not. The report name needs to be set when a menu item points to a controller so that the controller knows which report-design combination must be invoked. Using ssrsReportStr() method provides the benefit of compile time validation for the report and design name. The report name can be specified using this method like this:

Reports are identified using the ssrsReportStr() method as follows:

  • controller.parmReportName(ssrsReportStr(ReportName, DesignName));

DO SET…. the menu item’s RunOn property to ‘Called from

The menu item which invokes the report should always have its RunOn property set to Called from. By default, this property of the menu item is set to Client. However, if the report run by the menu item is part of a batch process, it will not work unless the menu item is set to RunOn = Called from.

DO USE…. a Report Data Provider class if business logic is necessary to fulfill the query driving the report

DO USE…. the built in RunningValue function (in Visual Studio) instead of temp table fields to generate running totals

DO ADD…. relations to RDP temp table fields to get automatic drill through on reports

DO PREFER…. a query based report over an RDP based report where possible

DO SET…. set Allow blank = true and Nullable = true for optional report parameters