Code highlighting

Wednesday, November 09, 2011

Tutorial: Debugging AX while still using restricted roles (non-admin)

Saw this on our internal forum today, and thought it's a nice thing to share with all of you.


1.       Close All AX instances

2.       Open AX Development Environment (ax32.exe -development)

3.       Open AX Application (ax32.exe)

4.       Add Role that you would like to test to your UserId

a.       System Administration > Common > Users

b.      Find yourself and double click to get to the detail window

c.       Assign role that you want to test

5.       Close AX Application

6.       Set break points in AX Development Environment

7.       Create a job and add this line

             SecurityUtil::sysAdminMode(false);
 
8.       From the AX Development Environment “Ctrl W” to open the application

9.       You are now in a reduced permission user and have the ability to debug. J
 

To get your environment back to full admin, re-execute the job in step 7 with a true.


Note: This will not work for EP, Services, direct BC.NET and cases using runas(), as the SecurityUtil::sysAdminMode is limited to the current session.


Ed Budrys from our Security team deserves the credit for the above.

Let me know if you found this to be useful.
Thanks

Friday, October 28, 2011

Tutorial: AX 2012 - Invalid field access or Accessing unretrieved fields

Read the post all the way until the end - there's an ask for you guys there!

As many of you have already seen in the new AX 2012 release, there are a lot more tables present in the application, because we went through an exercise of normalizing the data model.
Another feature that was added at the same time was the Table Inheritance, allowing to sub-class tables and add additional fields reusing some of the behaviors of the base table.

All of it is great! The only problem with it is that it comes at a price - we now need to retrieve a lot more data and do a lot more joins between tables. So we tried to mitigate that by using field lists where possible and adding AdHoc query support, which basically eliminates unneccessary joins between tables from the hierarchy, if fields from these tables are not selected.

We have also implemented a number of things that allow us to clearly see if the field was selected in the user interface, the APIs needed for doing the same, as well as special handling for invalid field access.

This tutorial contains a form, which showcases the different aspects of data access in cases described above.
You can download the project with the tutorial from my SkyDrive.

On the first tab, we have the standard "On hand" view, which in the data model is a join between InventSum and InventDim, with group by clauses on selected fields, in this case, ItemId from InventSum and InventLocationId from InventDim, and aggregation on the AvailPhysical column.
As you can see from the screenshot below, the rest of the InventDim fields are shown as Unretrieved. So, naturally, accessing one of them from code, for example, should not be a legal operation.
To verify that statement, there are 2 buttons on the form, the Incorrect and the Correct was of accessing the field. Clicking on the first one simply tries to read the value out of the InventSiteId field, while the second one uses the API method TableBuffer.isFieldDataRetrieved() to first verify if the field can actually be accessed.

Note, that in the below example, both buttons will work, as in, there won't be any errors shown to the user. When accessing the field, even though it is not retrieved to the client, the value will be treated as the default value for that type, that is, an empty string.

In order to verify that we do not access fields in an invalid way like above, we have introduced a parameter, that will throw an exception if a field that was not retrieved is being accessed.

In order to enable this validation, you need to update the below shown parameter in the Server configuration form (Located under System administration \ Setup \ System). After changing the value (note, that it is per AOS) you need to restart the AOS for the changes to take effect.


Now, if you try to use the first button (under Incorrect) from above, you will get a stack trace, notifying you that the specified field was not retrieved.



We suggest that when testing your modifications in the application, you always have that flag enabled, so as to avoid unpleasant and hard-to-find bugs later on in the production environment.


On the second tab of the Tutorial form, the same type of information is presented, only this time the output is actually based on a new table inheritance structure I created.


The base table, GenericBall, contains 2 characteristics of any ball. SoccerBall is extending it and adding an additional characteristic (for the sake of the example, let's assume Brand is only relevant to soccer balls). This is basically a very simple table inheritance structure.

In the form, however, I am only selecting to view the Brand field from SoccerBall, not selecting the other 2 fields from the base table. As expected, they show up as Unretrieved in the user interface.
However, there is one difference in how Scsc tables are handled - and that is, they will always throw an exception when you try to access one of the unretrieved fields.
The two buttons above the grid demonstrate that. Try it out, enabling/disabling the server configuration parameter shown above.


That's pretty much all there's to it. Let me know if you have any questions.

Now, I have one thing to ask you all too.
We in the AX Test team have done our best to find invalid field access problems before the release, but if you find one using the approach above, please log it either through the standard Microsoft channels (partner/ MsConnect/ etc.), or as a comment directly under this blog post.

Thank you!

Monday, October 24, 2011

Tutorial: AX2012 - A new way of accessing the QueryBuildDataSource for a particular FormDataSource

When playing with some X++ code, I found an interesting addition that happened in AX 2012 related to form development.

There are 2 new methods that were added to the FormDataSource class, which allow you to very easily and error-free access the underlying QueryBuildDataSource, whether that is for the initial form query or for the queryRun that also contains user filters and sorting.

So, for example, instead of writing:

this.query().dataSourceTable(tableNum(InventTableModule), 2);
this.queryRun().query().dataSourceName(identifierStr(Purch));
....

you can use the 2 new methods:

this.queryBuildDataSource();
this.queryRunQueryBuildDataSource();


It might seem as a very minor improvement, but in reality it greatly simplifies maintenance of code on forms, when new datasources are added or existing ones removed/renamed.

That's all for today.

Sunday, October 09, 2011

Tool: Updating a field value for all selected records on a form

Update:
It looks like I was re-inventing the wheel here.
Turns out that a tool doing exactly the same (and even invoked from the same place on Record info form) already exists and is called "Fill Utility". The problem is that it's disabled by default in the License configuration, so it not available.
More information about how to get it and what it does can be found in this MSDN article


Problem statement:
During a recent customer visit we received a suggestion from the developers working on customizing the customer application to their needs. The suggestion was about being able to modify the value of a certain field on a form for multiple records at once.
As you know, in AX 2012, if we wanted to change a certain property for a number of entities (for example, update the default transfer order overdelivery allowence on a number of items at once), we would have to go through them one by one, which is time consuming and definitely not fun.

Solution:
Using the small example I created we can in a simple and intuitive manner update the selected field value for all the marked records.

It looks something like this:

1.    First, you multi-select the records where a certain field needs to be updated, and open the Record information for them


2.    Then, you click Update, select the field that needs to be updated and put in the new value


3.    After you confirm the changes, all the selected records will be updated with the new value.

Download:
Download the project from my SkyDrive


Issues:
These aren't really issues, just things I did not spend time on.
  1. I did not develop the idea of selecting multiple fields to update at once. Might be a good idea. I just did not want to add more code into this little project. There's however a nice UI for selecting 1 or more fields in the DEV_SysTableBrowser project (link)
  2. I did not spend enough time trying to figure out the validation that should be in place for this. I figured, if people are gonna use it, they know what they are doing.
  3. The project is based on AX 2012. There's only 1 method with code, the rest is form controls. I figured it should be pretty easy to port this to other versions if needed.
If people find this useful, I encourage them to add whatever else modifications. I can also re-post them here on request.


Thanks

Thursday, July 07, 2011

Help content for Microsoft Dynamics AX 2012 is now available on TechNet

As you might have heard, AX 2012 has RTM'ed recently.
Now, the question you might ask is - OK, I have read the What's new in AX 2012, but that's not enough. The changes are too vast and I need more detailed information about them.

Well, worry no more :)

The information about AX 2012 is now available on TechNet, with a lot of new content still being added each day. And, finally, it's actually interesting to read. We now have various graphs, diagrams and tables that should help you understand each feature area a bit better.

Hint: The description of the functional modules of the application is under section 5. Use Microsoft Dynamics AX.

Enjoy!

Microsoft Dynamics AX 2012 Technical Library
http://technet.microsoft.com/en-us/library/gg852966.aspx

Saturday, May 07, 2011

Tutorial: Table Relation properties in AX 2012

As many of you already know, Microsoft has put in a lot of effort into normalizing the tables in AX 2012 and consolidating all the data modeling tools in one place - the table itself. As part of this effort, a number of new properties have been introduced on Tables, and in this post I would like to cover some of them, namely the properties on Table Relations.

The new properties you will find on a Table Relation in AX 2012 are:
  • Cardinality
  • RelatedTableCardinality
  • RelationshipType
  • Role
  • RelatedTableRole
  • UseDefaultRoleNames
  • CreateNavigationPropertyMethods
  • NavigationPropertyMethodNameOverride

Hua Chu from the AX team has written a Guideline document, explaining how these properties should be set for Relations you add to Tables in AX. Note that in AX 2012 most of the above information is not actually used at runtime. This is something that will happen in future releases.
I have modified the document so that it contains the information relevant for partners and customers extending the standard application and have uploaded it to my OneDrive.

The document requires certain knowledge of Entity Relationship Modeling (ERM) and UML notation.

Disclaimer:
This document is intended as a guideline only, and should not be used as a Step-by-Step instruction.
Changes to any of the described functionality might still happen before AX 2012 RTM.


Your feedback and questions are, as always, welcome.

Thursday, May 05, 2011

Tutorial: lockWindowUpdate() vs. lock()/unlock()

There are two method pairs in X++, that are used throughout the application by everyone writing some processing on application forms. These are:

element.lock();
element.unLock();


and

element.lockWindowUpdate(true);
element.lockWindowUpdate(false);


Now, not that many people know the difference between the two methods, and only very few think about why and when should each of them be used.
I will try to describe the behavior of these methods and at the end give some recommendations on how to use them. I have done some kernel code reading (with help of kernel dev. Andy Stach, who I would like to mention here), so what I write below is more or less backed up by code.
If you disagree with some of the recommendations though, please share your experience in using these methods through comments for this post.

FormRun.lockWindowUpdate()

is basically a wrapper around the LockWindowUpdate Win32 function. What it does is pretty simple:
When a window is locked, all attempt to draw into it or its children fail. Instead of drawing, the window manager remembers which parts of the window the application tried to draw into, and when the window is unlocked, those areas are invalidated so that the application gets another WM_PAINT message, thereby bringing the screen contents back in sync with what the application believed to be on the screen.
See the link on MSDN for a detailed description.
Note, that according to MSDN, it should not be used for general purpose suppression of redraw operations, but only when dealing with drag&drop operations. This does not hold true for AX, where this method is used all over the place to prevent redraw of controls on the form.
Another interesting point is that only one window can be locked at the same time. So, any nested calls to lockWindowUpdate will be ignored, but when unlocking, only the outer-most unlock will actually invoke the Win32 counterpart. Now, I have not seen this used in X++, which is for the better.

FormRun.lock()

is internally invoking lockWindowUpdate to prevent the redraw of the window, and then also prevents the IntelliMorph control layout engine from running. This is commonly used in scenarios where control properties affecting control arrangement are being set in a loop, which provides a performance optimization as it avoids redundant arrange calls being processed. On the other hand, when calling FormRun.unlock, more work will need to be done, compared to using lockWindowUpdate(false), where the control layout changes were actually processed by the layout engine, but simply not displayed.

So, based on my investigation, I would suggest to use the following recommendations when doing form development:

  • When formRun.resetSize() is used, specifically, when some controls become visible, increasing the form size, always use formRun.lock()/unlock(), otherwise the change in the size of the form might not get reflected on the screen correctly.
  • When changing multiple layout properties (Left, Width, etc.) on one or more controls, use lock/unlock
  • When you modify the properties that do not impact the layout of controls on the form, use formRun.lockWindowUpdate(), or, if there are only very few control properties being modified, do not lock the form window at all.

Monday, April 11, 2011

Microsoft Dynamics AX 2012 Beta now available for download - please share your feedback

As some might have noticed, I was quiet for quite some time now. I won't go into much detail as to why. What I want to say is that I along with a number of dedicated people have been hard at work on the release of a solution for Process Manufacturing and Distribution industry, which is also available in Beta through the below links.

Those of you working in this industry, I would be grateful for your feedback on our work so far, as well as any bug reports or design change requests for the RTM version or future releases.
Any other feedback, especially on the development tools and environment, is also welcome, of course.


Virtual Machine: 

https://mbs.microsoft.com/customersource/downloads/servicepacks/AX2012DemoToolsMaterials


Installable bits (ISO & IS IExpress pkgs):

https://mbs.microsoft.com/partnersource/support/selfsupport/productreleases/AX2012Beta

MSDN Dev Center:



TechNet Library: