Thursday, August 2, 2018

Design Principles in AX 2012


This section describes several design principles to be employed when you design a Microsoft Dynamics AX application.


Keep Business and User Interface Logic Separate

Where to Place the Code

Always Use Field Groups in Tables

Using Global Variables

Use Auto Property Settings

Best Practices for Designing Reports

-----------------------------------------------------------------------------

Keep Business and User Interface Logic Separate
It is very important to have a clear interface between the presentation logic (user interface) and the business logic. Do not mix these two types of logic.
Business logic must be implemented in classes and on tables.
Never design your business logic so that it has direct references to controls on forms or reports. The design of the business logic must enable any relevant form or report to use it.
Remember that the business logic in Microsoft Dynamics AX can be used though COM from other applications. For example, an X++ script can access the business logic that creates a sales quotation. This underscores the importance of not letting the business logic be dependent on a specific Microsoft Dynamics AX form or report.

Where to Place the Code
http://rahulmsdax.blogspot.com/2018/08/where-to-place-code-in-ax.html

Always Use Field Groups in Tables

When designing tables, it is very important to use field groups. You should also add fields to a field group if you are adding fields to existing tables. Add them to an existing field group, if possible.
When you use field groups, IntelliMorph can automatically update the layout of all related forms and reports whenever a modification is made to the field groups.
If you create new forms or reports based on the field groups defined in the standard tables, you will not have to manually update the custom object when the standard tables are modified by an upgrade.
The sequence of the fields in the field groups on tables can be used to determine the sequence of the fields in forms. To do this, use the AutoDataGroup property on the Groups controls in the form design.
This means that the order in which the fields appear in the field group is significant.
Using Global Variables
Global variables are often needed because of flawed implementation designs. However, if used for caching purposes, global variables can provide increases in performance. This topic describes how you can implement a global variable with zero maintenance during an upgrade.

How to Set the Variable

Get the globalCache variable located on the ClassFactory class:
SysGlobalCache globalCache = ClassFactory.globalCache();
Call the set method:
globalCache.set(str  owner , anytype  key , anytype  value );
Parameters
Description
owner
A unique name that identifies you as the user. Use classIdGet(this) or classStr(myClass).
key
Identifies your variable. This is useful if you need more than one global variable from the same location.
value
The actual value of your variable.

Get the Variable

Get the globalCache variable, located on the ClassFactory class:
SysGlobalCache globalCache = ClassFactory.globalCache();
Call the get method:
value = globalCache.get(str  owner , anytype  key , anytype  returnValue  = '');
Parameters
Description
owner
Must be a unique name that identifies you as the user.
key
Identifies your variable.
returnValue
The value you want if the global variable has not been set. This is useful for caching purposes. See the following example.

Example

void new(Integer _width  = Imagelist::smallIconWidth(),
         Integer _height = Imagelist::smallIconHeight())
{
    SysGlobalCache globalCache;
    Container      packedData;
    ClassName      className;
    ;
 
    if (this.keepInMemory())
    {
        globalCache = ClassFactory.globalCache();
        className   = classId2Name(ClassIdGet(this));
        packedData  = globalCache.get(className, 0, connull());
        imageList  = globalCache.get(className+classStr(imagelist), 
                                     0, 
                                     null);
    }
    if (!imageList)
    {
        imagelist = new Imagelist(_width,_height);
        this.build();
        if (this.keepInMemory())
        {
            globalCache.set(className, 0, this.pack());
            globalCache.set(className+classStr(imagelist), 
                            0, 
                            imagelist);
        }
    }
    else
    {
        this.unpack(packedData);
    }
}

Client/Server Considerations

Because of the duality of ClassFactory, global variables can exist either on the client or the server. This could mean less network traffic because it is possible to have the global variable on both sides—set it twice.
To share your global variable across the network and accept the performance penalty of a client/server call, use the infolog variable (Info class) or appl variable (Application class) instead of ClassFactory. They reside on the client and on the server, respectively.

Use Auto Property Settings

A general design rule is to keep as many property settings set to Auto as possible. The benefit of doing this is that the application objects will automatically adjust to any changes of the kernel’s interpretation the application object’s behavior, such as how a form or report should be displayed.

Best Practices for Designing Reports

This section provides best practices and guidance for creating Microsoft Dynamics AX reports, including how to make a sequence of decisions on the data access, controls, and design for the report.

Elements of Report Design

Data access determines the source of the report’s data set. The data access options for a report include:
  • AX Query – A modeled solution for data access.
  • X++ Business logic – Use Report Data Provider (RDP) classes to produce a data set.
Controls determine how inputs (parameters) are passed to the report. Controls include:
  • Query Ranges – data set filters defined on the AX Query.
  • Data Contract – filters for data sets generated from X++ Business logic.
  • UI Builder – fully customizable dialogs
Design determines the document layout template of the report. Options for the design include:
  • Auto Design – modeled solution for basic layouts
  • Precision Design – flexible solution for advanced layout
Elements of a report

Sequence of Report Design

A report’s data access type determines which controls can be used, and the controls chosen affect the layout of a report, so the elements of a report should be chosen in this sequence.
  1. Data Access
  2. Controls
  3. Design
Report Development Sequence

General Best Practices

The following table provides additional general best practices for developing Microsoft Dynamics AX reports.
Best practice
Additional information
Use query based reports when possible, for best performance.
A query to access data has the following advantages:
  • A query with a display method has no code that needs to run. You can query for data directly from a table. The filter of data occurs in SQL which is faster.
  • There are no X++ classes to develop. You define a query in the AOT.
Return a TempDB based temporary table when appropriate.
In-Memory tables are not a SQL based concept so the performance is slower than when you return a TmpDB temporary table. This is especially true for large datasets.
For calculated fields, use a view wrapped in a query.
Views provide the ability to add calculations. For more information, see View Overview.
Keep business logic as close to the data as possible.
This promotes reuse of business logic. When the business logic filters data, less data is moved through the system and demands fewer resources.
Use a precision design for all reports. An auto design is a good start point to create a precision design for a report. An auto design will not create medium or complex reports.
Do not define a sort or a group in a Microsoft Dynamics AX query.
The dataset returned to SQL Server Reporting Services will be flattened. Use sort and group in the Reporting Services report definition. For more information, see Working with Data Regions.
Use RDP class based reports when calculated fields in a view perform poorly.
In reports where there is reuse of one or more expensive calculated fields, performance might improve when you use temporary tables to cache data.
Avoid using RDP classes when the data for the report is in a table and the report dataset can use the table.
RDP classes provide extra flexibility but also introduce complexity and potential performance degradation.
Use an RDP class when the report data needs to be calculated and complex business logic is required to define the data for a report.
When the report data is accessibly in Microsoft Dynamics AX tables, then use a query and display methods or use a view.

Where to Place the Code in AX

orrect code placement is essential for good application performance (especially in the client/server environment) and to make the application easy to customize, reuse, navigate, and maintain.

3-tier Design

Optimize your programs to utilize the 3-tier architecture that is supported by Microsoft Dynamics AX.
Tier
Objects and code belonging to the tier
Client
Presentation layer. This is where forms are stored. Place client-specific classes and methods here.
Object server
The location of business application logic. Transaction-oriented database update jobs should be placed to run here, close to the database.
Database server
Utilize the power of the database server by using aggregate functions, joins, and other calculating features of the database management system.

Classes

Put code in the classes that are:
  • Related to many tables, such as update jobs
    –or–
  • Not related to tables, for example, various supporting activities
Create class instance methods:
  • When working on the instance variables of the class (objects of)
    –or–
  • When overriding is potentially useful
Create class static methods when:
  • Access to the class instance members is not needed
  • Overriding is not necessary
  • The functionality of the method is related to the class it is defined on
  • The method might be able to execute on a different tier than the method's

Tables

Put code that is strictly related to a table as methods on that table.
Create table instance methods for handling one record at a time. Create table static methods when handling none, some, or all records.
Split code to be executed on separate tiers into separate methods.
NoteNote
Do not create instance methods when no instance is needed.
Code in static methods can technically be created anywhere—on any table or class—because it has no physical binding to the instance. Create it either on the table or on the class where it logically belongs.

The Global Class

Place methods in the Global class if they cannot be placed more logically on another class (or table).
Methods on Global should have the same character as the system functions. They should be general-purpose, tool-extending, and application-neutral.
Do not use the Global:: prefix when calling Global methods—methods on this class do not need a variable declaration.

Forms and Reports

Do not put any code in forms or reports except for calls to the classes and table methods that handle complex layout and business logic.
Do not to place edit and display methods on forms and reports if they can be placed on a table.
If code cannot be avoided in the form:
  • Place the code at the data source/data source field level and not at the control level.
  • Call classes from buttons on forms by using menu items (for example, by not using code).

Maps

Use maps for a limited number of connected fields. For example, for the Address fields, code should be placed on AddressMap.

Views

Views are limited select statements used on read-only tables. Do not place much code on views, unless, for example, you have a display method on the parent table.

Wednesday, August 1, 2018

Debugging in AX 7 / Dynamics 365 Operations

This purpose of this blog is to show how you can get quickly get started with debuggingin AX7, specifically by showing how you can debug an error message issued from AX.
So, let’s begin !
Imagine you are posting a Bank journal and you get the following error message upon posting ‘Currency EUR not allowed for account USMF OPER’
You would like to know the logic behind this error message, but need to trace in the code where it was issued from
Blog1
We will use a classic debugging technique known from AX 2012 to demonstrate how this can be done quickly and easily, by inserting a breakpoint on the Info class to enable the debugger to track down in the code where the error is generated from.
These are the steps
  1. Start Visual Studio as ‘Administrator’
Blog2
2.  Go to the Application explorer, go to the ‘Code’ node, select ‘Classes’ and locate the ‘Info’ class
Blog3
On the ‘Info’ class rightclick and select ‘View code’
Blog4
In the window that opens up, select the ‘Add’ method
Blog5
3. Insert your breakpoint on the ‘Add’ method by pressing ‘F9’
Blog6

4. Press ‘Debug’ from the toolbar and select ‘Attach to process’
Blog7

In the ‘Attach to process’ screen mark ‘Show processes from all users’ and then browse to
the process ‘w3wp.exe’
Blog8


If you can't see w3wp.exe process to attach for debugging, please refer the below blog.
http://rahulmsdax.blogspot.com/2018/08/cant-see-w3wpexe-process-to-attach-for.html

Wait for the Symbols to load
Blog9

5. Once the symbols have loaded repeat the application procedure, eg. in this case we will post the journal again to generate the error message
Blog10

And note that almost immediately the debugger starts executing in Visual Studio
Blog11
I copy the call stack into Notepad and here I note especially the highlighted line as this is the line that is triggered just before the call to the Infolog code
Blog12
I can see that the error is triggered on the BankAccountTable, checkCurrency method on line 225 and I stop debugging
Blog13
I go to this code to study the method
 I open up the BankAccountTable and similar to as on the ‘Info’ class I select ‘View Code’ and open the method I am interested in
Blog14
Here naturally ‘checkCurrency’
Blog15

And  we can study the code that generated the error message
Naturally, you can use the same technique to insert breakpoints in other places of the code such as on ‘init’, ‘update’ and ‘insert’ methods etc

Can't see w3wp.exe process to attach for debugging in AX 7 / D365 Operations


If you are unbale to find the w3wp.exe process that we attach our VS debugger to inorder to step through X++ on D365. Chances are the windows logging service is not running. The service name to check is W3C Logging Service start this service by going to services.msc and reopen/refresh the process list.

Then Click on "Show process from all users"
P.s Also make sure your World Wide Web Publishing service is running. Without which your D365 client wont be hosted as well.

What is the primary purpose of using a Solution in Microsoft Power Platform & ALM?

As organizations embrace low-code development with Microsoft Power Platform , it becomes essential to manage and govern apps, flows, and dat...