Sunday, December 15, 2013

Tool: Update: User preferred startup menu for AX 2012

I have over the last year received a couple mails and comments from people, asking to publish an update for the below tool for AX 2012

There aren't really any serious changes to it as such, just some minor things.
Again, note, that there are a few changes to some of the existing "high profile" AOT elements, so please read through the description of changes in the above post.

Download updated xpo

Monday, March 11, 2013

Microsoft Dynamics Salary Survey 2013

The time of the annual Microsoft Dynamics Salary survey is again upon us.

Here's the official invite. Please participate, so we can make the data accurate statistically. They also have prizes for people participating.. :)
Link to start the Microsoft Dynamics Salary survey
Take the Microsoft Dynamics Salary Survey 2013 for a Chance to Win a Microsoft Surface Pro (128 GB), the Nokia Lumia 920 or Xbox 360 Kinect Bundle
Nigel Frank International would like to invite you to complete our annual Microsoft Dynamics Salary Survey. 
Take the survey and you will automatically be entered into our prize draw to win a Microsoft Surface Pro (128 GB), the Nokia Lumia 920 or Xbox 360 Kinect Bundle.
You will also receive a FREE copy of the Salary Survey report once it has been compiled.
The industry acclaimed annual “Microsoft Dynamics Salary Survey” is the world’s most comprehensive insight into global salary trends for Dynamics professionals. Use the survey to benchmark your team's, company's or your own salary.

Wednesday, August 29, 2012

Inside Microsoft Dynamics AX 2012 is available for Pre-Order

With the release of AX 2012 the market was in need of an updated book on the development aspects in X++/.NET for the purposes of extending the AX application functionality.

As some of you might know, I translated 2 of the MS Press books on AX development for the previous versions to Russian.

This time around, I was lucky enough to participate in the creation of the English version as well.

Inside Dynamics AX 2012 book cover
The book has been significantly updated to account for the numerous changes in the latest AX release, so I am sure many of you will enjoy the read.

The book is not out yet, but you can pre-order it at Amazon by using the link below

Pre-order "Inside Microsoft Dynamics AX 2012" now


Thursday, February 23, 2012

Tutorial: Determine if a string is a valid UtcDateTime

In my post about UtcDateTime in Dynamics AX, I recently received a question about determining if a specific string is a valid UtcDateTime in X++.I've spent some time looking into it and could not find an available method that could be used for that.
Also, it was not really clear, which format should be called valid.

Anyhow, I have so far discovered 2 ways to do it in AX: the simple way, and MY way :) They produce slightly different results however. Let me know if you find other ways.

The simple way is to use the intrinsic function str2datetime.
As you can see on MSDN, it supports a couple of input formats, and if you provide a non-date value, will just ignore it silently and return an empty value.

However, when working with DateTimeUtil methods, the expected format is yyyy-mm-ddThh:mm:ss
And, as you can see from the below test job, specifically this format is not supported by str2datetime.
So I wrote my own method based on DateTimeUtil::parse(), that returns true/false based on the string value matching the above format. This is however the only supported format for DateTimeUtil, so the other 3 examples that work with str2datetime do not work here.

Anyhow, you can download the code (I've put the method into Global) and the test job from my SkyDrive.

Test job:

   1:  public static void isValidUTCDateTimeTest(utcDateTime _utcDateTime)
   2:  {
   3:      boolean utc1 = str2datetime("2012/02/25 23:04:59", 321) != utcDateTimeNull();
   4:      boolean utc2 = str2datetime("Feb-2012-25 11:04:59 pm", 231) != utcDateTimeNull();
   5:      boolean utc3 = str2datetime("25 02 2012 11:04:59 pm", 123) != utcDateTimeNull();
   6:      boolean utc4 = str2datetime("2012-02-25T23:04:59", 321) != utcDateTimeNull();
   7:      boolean utc5 = str2datetime("XXXX", 123) != utcDateTimeNull();
   9:      void showResult(str format, boolean isValid)
  10:      {
  11:          info(strFmt("%1 - %2", format, isValid));
  12:      }
  14:      setPrefix("Date time validation");
  15:      setPrefix("str2datetime has multiple valid formats");
  16:      showResult("2012/02/25 23:04:59",       utc1);
  17:      showResult("Feb-2012-25 11:04:59 pm",   utc2);
  18:      showResult("25 02 2012 11:04:59 pm",    utc3);
  19:      showResult("2012-02-25T23:04:59",       utc4);
  20:      showResult("XXXX",                      utc5);
  22:      setPrefix("Correct UtcDateTime format for DateTimeUtil: yyyy-mm-ddThh:mm:ss");
  23:      showResult("2012/02/25 23:04:59",      isValidUTCDateTime("2012/02/25 23:04:59"));
  24:      showResult("Feb-2012-25 11:04:59 pm",  isValidUTCDateTime("Feb-2012-25 11:04:59 pm"));
  25:      showResult("25 02 2012 11:04:59 pm",   isValidUTCDateTime("25 02 2012 11:04:59 pm"));
  26:      showResult("2012-02-25T23:04:59",      isValidUTCDateTime("2012-02-25T23:04:59"));
  27:      showResult("XXXX",                     isValidUTCDateTime("XXXX"));
  28:  }

Tip: Illegal 'closing bracket' character when defining a macro

Just a very quick tip today, related to macros:

As you all know, there are multiple ways to define and use macros in X++.
For those that need a refresher, please look up the corresponding section on MSDN
(Direct link:

Below is a simple X++ job, that demonstrates an existing shortcoming in the #define command, and a possible workaround for this problem.

Nothing complicated, basically, just use #localmacro, if you can't compile your code.

   1:  static void ClosingBracketInMacroDefinition(Args _args)
   2:  {
   3:      //#define.Question("Why are brackets ')' not working ?")
   4:      //#define.Question(@"Why are brackets ')' not working ?")
   5:      //#define.Question("Why are brackets '\)' not working ?")
   6:      #define.LegalCharacters(' !"#$%&\'(*+,-./:;<=>?@[\\]^_`{|}~\n\r\t')
   7:      #localmacro.Question
   8:          "Why are brackets ')' not working ?"
   9:      #endmacro
  11:      Box::info(#Question);
  12:      Box::info(#LegalCharacters);
  13:  }

Thanks for finding the issue to Bogdana, one of our new developers.

Friday, January 20, 2012

Microsoft Dynamics Salary Survey 2012 - Please participate

I don't usually make posts like this, but this is one of those things I always look forward to reading when it comes out, so I decided helping the guys out won't hurt :)

What I am asking from you guys is some time (2 minutes or so) to fill out the survey below about how much you make, what kind of benefits you get, where you work, and so forth. It's anonymous, obviously, and every participant will get a copy of the report afterwards. And this time around, you can even win something for participating! So please do.

Participate in the survey about Dynamics
Microsoft Dynamics Salary Survey 2012
Nigel Frank International would like to invite you to complete our annual survey of global Microsoft Dynamics salaries. The survey will only take a couple of minutes to complete and your response and any personal details will be kept strictly confidential.

Complete the survey by the closing date and you will automatically be entered into our prize draw to win one of five amazing prizes:

1st Prize = Apple iPad2 16gb with Wi-Fi + 3G

2nd Prize = Microsoft Xbox 360 250gb + Kinect
3rd Prize = Kindle Keyboard with Free 3G + Wi-Fi
4th Prize = Microsoft LifeCam Studio Webcam
5th Prize = Microsoft Arc Touch Mouse

You will also receive a FREE copy of the Salary Survey report once it has been compiled.

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

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.

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!