Saturday, December 24, 2011

Error in Management Reporter: "The request for data from Microsoft Dynamics AX failed. Provider query name: LedgerMRBalanceRequestQueryBuilder"

Issue:
When generating a YTD Balance sheet in Management Reporter (MR) for AX 2012, we were seeing an error being thrown and the report did not run.

The error: “The request for data from Microsoft Dynamics AX failed. Provider query name: LedgerMRBalanceRequestQueryBuilder.”

We checked the appropriate permissions to all folders that MR must access but we were still getting the issue.

The error was isolated to that one specific report as we could run other reports without issue.
Cause:
The report had a significant amount of data in it and it was causing the query to fail.

Workaround:
Breaking down the report into smaller sections allow the users to run the report without hitting this issue.

Resolution:
This was an MS product issue.  Thankfully, the helpful staff in Fargo was able to resolve it and push out the resolution out in the new AX2012 MR provider Service pack.  Download it from customersource/partnersource to resolve this issue.  The name of the update is
'Microsoft Dynamics AX 2012 Provider for Service Pack 2'
Name of the file you will be downloading: AX2012Provider.zip

Hope this helps!!

Tuesday, December 20, 2011

Run static method through X++ code

The following is code that will allow you to run a static method using two strings and a container. You need to assert and revert permissions around doing this but it allows you to dynamically run a static method without knowing what the method is.  This is good for frameworks.
  • _className     = the string name of the AX AOT Class name.
  • _methodName = the string name of the method from the AX AOT Class above.
  • _params           = the container which has the variables, [parameter 1, parameter 2, etc]. 
// Start DAX code
// From parameters:
ClassName _className
MethodName _methodName
Container _params;
// From method variables
Container               result;
DictClass               dictClass;
;

// This code will run the static method
executePermission = new ExecutePermission();
executePermission.assert();

dictClass = new DictClass(className2Id(_className));
result = dictClass.callStatic(_methodName, _params);

CodeAccessPermission::revertAssert();
// End DAX code

This code is dynamic and powerful.  Enjoy!

Monday, December 19, 2011

How to get to AOT in AX 2012 (Application object tree)

I was asked this question by someone who was a 3 year seasoned application AX person recently. This person knew enough AX development to be dangerous but was not a developer.  He never claimed to know dev but in talking with him, he knew his stuff.  Which brings me to the question that was asked, "How do you get to the AOT in AX 2012?  It doesn't look like you can anymore".  

I was kind of confused at how the person did not know the answer but then, after talking a bit, realized they would only access the AOT through the AX toolbar. I actually met 2 other people who I know did the same thing.  In AX 2012, the IDE is actually a whole seperate workspace in contrast to previous versions of AX which were all tiled together.  With this new configuration, that button is gone (or moved. I don't know. I never use it...).

Getting to the AOT is as easy as hitting Ctrl+D as long as your user rights permit it.  I could put up screenshots and get into the details but I think everyone who is involved in AX knows that the easiest way is the best way. Just hit Ctrl+D when you are in your AX instance and, BLAMMO!, a new instance/workspace of AX with the AOT will appear to you like a magic genie in a bottle. 

Easier and faster than ordering room service...  Enjoy!

AX 2012 WCF Error: 'The specified client configuration does not contain valid WCF settings'

I hit the following error while working in AX 2012: 'The specified client configuration does not contain valid WCF settings' (Figure 1 below).  This seemed to happen all over the place when specfic actions were done. Didn't care or have enough time to pin point what.  The actions were pretty varied and seemed almost random.  Try running the On Hand Inventory report...

This error was only encountered in AX 2012.  It is because of an issue with a new feature in the AX configuration file that needs to be fixed through the configuration utility.  Do the following to fix the issue:
  1. Open the .axc where this issue was being seen in the Microsoft Dynamics AX Configuration Utility.
  2. Click on the 'Connection' tab
  3. Click on the 'Refresh' button and wait for the proces to complete.
  4. Click on the 'Configure Services' button'
  5. You will now see the info message in Figure 2. Click 'Ok'
  6. You will now see the info message in Figure 3. Click 'Yes'
  7. You will now see the info message in Figure 4. Wait for the process to finish.
  8. You will now see the info message in Figure 5. Click 'Ok'
  9. A new window for Microsoft Service Configuration Editor will appear (Figure 6 below).  You can close this screen.
  10. Save this configuration
  11. Open the config file and verify there is an XML section of the file (Figure 7 below).
  12. Replace the config file in all the user's desktop with the new one.
Figure 1 - The error at hand...
Figure 2 - Clicking 'Configure Services' will give this information. Click 'Ok'

Figure 3 - Clicking 'Ok' in Figure 2 gives this message. Click 'Yes'
Figure 4 - Clicking 'Yes' in Figure 3 will show this process window.  Wait for it to finish
Figure 5 - Once Figure 4's process is complete, this information is presented. Click 'Ok'
Figure 6 - This pops up at the end of the process.  Just close out of it.
Figure 7 - This is what opening the new .axc file looks like after running that process.

Monday, November 14, 2011

AX 2012 for Retail POS development

As I stated in one of my previous posts, the AX for Retail solution is highly customizable. There is not a lot out there on the web about it but there should be. While I am not so much of a technical person anymore (just by title...), I will still do a bunch of mods in this solution to make sure I know my stuff.

A functional consultant that knows the technical aspects of things is an extremely valuable resource and I can assure you that I will stay current with tech to keep that badge.

I'll post some stuff on here as I do it to keep people informed of my adventures.

Here is one great blog post about retail POS development that I've found helpful.  I hope you will, too.  I hope to come out with one that is equally as helpful that people will come to as well...

http://blog.rahulsharma.in/2011/09/dynamics-ax-for-retail-pos-development.html

AX 2012 for Retail history summary and how it got to where it is today

Microsoft had two primary Point of Sale (POS) solutions in their Dynamics software stack: Retail Management System (RMS) and POS 2009.  These solutions were great for cash and carry retail operations that had a few locations and could handle a fair amount of volume without a problem.  They handled all of their backoffice functionality in smaller accounting solutions like Quickbooks and PeachTree to name a few. 

For larger companies, Microsoft's Dynamics AX (Axapta) solution was the obvious choice for their backoffice applications as these smaller accounting solutions were not capabale of sustaining their operations. The issue with these POS products and larger corporations is that they were developed for smaller operations out of the box (OOTB).  The major selling point of large scale ERP's are their abilites to centralize managment of all operations into a single location.  These products had to be adapted for larger companies via third party integrations like ToIncrease's Retail Chain Management (RCM) or Blue Horseshoe's Retail Operations Bridge (ROB) interfaces (for example) in order to integrate RMS to the AX system.
There were two issues with this solution: 1) Not a OOTB integration with a lot of effort in upgrading  and 2) RMS was not a flexible application to allow major customizations like AX was able to.

As many in the AX industry know, AX is VERY customizable.  With this customization power comes great customization responsibility.  As an observation, the larger a corporation was, the more unique requirements their business contained.  This created an obvious limitation of using these solutions as they were not very customizable.  To note, they did not need to be and they did their job extremely well.

In order to bridge these two gaps, Microsoft purchased LS Retail POS and ToIncrease's RCM in order to develope their own, highly integrated, highly customizable POS end-to-end solution for their larger clients.  From this came AX 2009 for Retail.  This was a great product and everyone instantly saw that every implementation had customizations.  I have yet to hear of a single solution that was 100% OOTB.  This was by design as one size does not fit all.

Microsoft will soon release in the third quarter of 2012 (tentative), the AX 2012 for Retail feature pack.  This is currently in the TAP process at the moment.

This is obviously just a high level history of how AX for Retail came to be.  I left some stuff out and may have been too broad in some areas so please comment below if you can help add to this.  I'm always interested to learn the background of stuff...

Tuesday, November 8, 2011

Allow a single user name to log into a server without taking over a session

The following should be used very carefully. I thought I would write about it since it helped me out of a tight situation a few times.
An example of where I used this: There is a third party application running at a client site and it doesn't seem to work for any other user except for the administrator account on that machine.  The client wants to get in there and start using the program but the vendor is unavailable to assist at the moment.  By allowing multiple people to log into the single administrator account, it helps progress move forward.  THIS IS NOT IDEAL FOR A LIVE ENVIRONMENT.

A note to people making config changes: PLEASE TEST YOUR CHANGES.  DO NOT ASSUME THIS WILL JUST WORK SINCE I SAID SO.  This is a VERY important step and seperates the posers experts and the real experts that know better.

The following is for Remote Desktop Services (RDS).  Microsoft (MS) rebranded Terminal Services (TS) as RDS.  This process can be done with any user that has privileges to do this and it affects all users logging into that server.

Step 1 - Navigate to 'Remote Desktop Session Host Configuration'
To get here, go to: Start -> Administrative Tools -> Remote Desktop Services -> 'Remote Desktop Session Host Configuration' (See Figure 1 below)

Step 2 - Uncheck the 'Restrict each user to a single session' box.
Once in Remote Desktop Session Host Configuration, under the 'Edit Settings' section, look at the options in the General option.  The third one down should read 'Yes' if you log into the server and immediately take over an active session.  Double click on this option and you will see the form in Figure 2 pop up.  Uncheck the 'Restrict each user to a single session' box and click Apply. 

Step 3 - Validate the changed setting
While keeping your current session open, open a new RDP session and log in as your current user.  If the new window opens a fresh instance on the server, you're all set!

Hope this helps!

Figure 1 - Navigate to 'Remote Desktop Session Host Configuration'

Figure 2 - Uncheck the 'Restrict each user to a single session

Wednesday, October 12, 2011

Microsoft Dynamics Retail Management Systems (RMS) CSC (CVC2/CVV2/CID) code support

UPDATE 1/19/2015: RMS is a deprecated product and no new features are being added to it (including support for Chip+PIN or Chip+Signature) which is VITAL in the US for October 2015. Look at upgrading to Retail Essentials which will allow you to use the new Retail Modern POS for mobility, in store, and ecommerce. 

UPDATE: This is all taken care of in AX 2012+. The post below was pre-2012 release. Wanted to update this as it was the #2 post on my blog for January 2014.

In today’s economic climate, fraudulent credit card purchases are rampant.  In traveling for work, I have had my credit card stolen twice in a single year.  Additionally, with the spike in internet sales and unsecured wireless networks, it is even easier to grab a person’s credit card (and a bit of other personal information that is easy to find online with a name and birth date) and start to purchase like wild.
To help protect against this, credit card companies needed to find a way to differentiate a credit card transaction as being a ‘card not present’ situation.  The use of credit card security codes (CSC) are the way that they achieve this.  They are not imbedded in the magnetic strip and do not pop out of the card like the normal numbers. It is a violation of the credit card companies terms to save this number, too.

CSC’s are also known as CVV2 (for Visa), CVC2 (for MasterCard), or CID (for Discover).  These other names are just the names that the credit card companies use so don’t let it fool you.  If someone asks for a CVV code, they are referring to a Visa card even though the overarching name for the security code concept is CSC.

Some credit card companies are now requiring that, when a card fails to swipe and process, the company needs to be able to validate that the card was physically there in order to protect the business making the sale from fraudulent transactions that the credit card company gets challenged about.  Businesses can process the credit card by either manually keying in the card number into the system or making a manual imprint of the card for later processing.  The problem with keying in the card is that there is no way to verify that the card was actually there.  Since CSC’s were a way to help verify against fraud by verifying that the card was physically present, they want those to be manually keyed in as well. By successfully swiping the card, the CC company can determine that the card was physically present. 

The problem comes in that Microsoft Dynamics Retail Management System (RMS) was designed to be a ‘face-to-face’, or a ‘card present’ retail solution.  Because of this, there was no need to be able to manually key in the CSC code since everything was taken through swiping the card.  Yes it is true that RMS had a web component of it but this is just a remnant of QuickSell (Microsoft purchased QS from Sales Management Systems [SMS] in 2002 and rebranded it RMS).  There may be plug-ins out there that people have created with a new integration point.

Unfortunately, the POS component of AX for Retail 2009 R2 doesn't have this ability either. Bummer…  It might be supported but only through the Dynamics Online payment processor.  I have not heard if AX 2012’s POS has this support or not.  They can be mod’ed to include this functionality but it doesn’t currently exist.

Key take-away: Please review your credit card processing contracts and make sure you are protected against fraud claims. Find a workaround to this product deficiency so that you can stay protected.

I think that CSC support is something that Microsoft should support sooner than later…

Tuesday, September 13, 2011

Typing focus jumps to mouse cursor location when typing

When working with a client who has a laptop, one thing that I see a lot of is that the mouse jumps around to the mouse cursor when typing rather than styaing on the location where the cursor focus should be (on the line being typed). This can almost seem random and frequent. This causes a lot of frustration and retyping work since you'll have words like HeWorldllo instead of Hello World. 

I can not guarantee it will fix everyone's issues but it did for me.

The following simple configuration change is how I fixed it on my system:
  1. Go to Start -> Control Panel -> Hardware -> click Mouse. 
  2. Click the 'Pointer Options' tab.
  3. Uncheck the Hide pointer while typing box (if unchecked already, something else is going on)
That should be it!
Figure 1 - The 'Mouse' configuration option in the control panel

Figure 2 - The 'Hide pointer while typing' option that should be unchecked.
\

Monday, August 22, 2011

How to change/rename an existing Item Number

Depending on the business that you run, you will create a bunch of items (or some other main value) that you will need to rename.  In this example, I am talking about renaming a unique record key value for the item master (InventTablee.ItemId), but you could apply this to any ‘unique record key’ field table in AX.  For those that are not fully technically inclined, a ‘unique record key’ for a table would be a field that unique identifies that record in a table.  Using the example of the item master in this blog post, the key field would be the item id as you could not have two records with the item id ‘001234’ for example; it is a unique identifier to that specific record...

Anyways, all nerding out aside, we’ll proceed talking about the scenario where we need to change the value for an item id and have this change be reflected across the entire system.  While it may seem that ItemId’s can be changed in the item master at any time without repercussions, this is not the case.  The trick is that the item number also needs to be changed in all other records that reference this ItemId (Item Number) since it uniquely identifies this record.

Steps to changing the item number to have it reflect the changes in the rest of the existing transactions:

1.       Right click on the unique field (Item Number/InventTable.ItemId) and select the ‘Record Info’ option (Figure 1 below)


Figure 1 - Right Click on the Item Number field and select 'Record Info'

2.       Select the ‘Rename’ button (n Figure 2 below).

a.       VERY IMPORTANT NOTE: This could take A VERY LONG time to complete depending on how many transactions exist for that record.  I’ve had it last anywhere from 1 minute to 3 hours.  The 3 hours was for a client that had incredibly large volume.
Figure 2 - The 'Rename' button on this form will allow you to change the item number displayed in the item number field


It’s a fairly simple process to complete but very powerful and can take a long time.  The only reason I am writing this entry is that I was sharing beers with a seasoned AX consultant who did not know how to do this.  He did not work for our company but definitely pointed out to me how this feature is not really talked about in any specific point.  While it may seem obvious to the technical folk (or not), it may not be obvious to the functional peeps.

Just make sure to be VERY careful with this process.  I think its solid but I cannot vouch for it being 100% perfect.  I’ve never seen it faulter but PLEASE take the following precautions before doing this:

1.       Backup the PROD database

2.       Restore PROD to TEST/UAT/DEV (or whatever…)

3.       Execute the procedure on your target record

4.       Do extensive testing on that record Before and After this process (either BI reports or manual comparison)

5.       Compare the results and make sure all the target results are like you would expect

6.       Make the change in the PROD environment

7.       Validate the data in the PROD environment

8.       Sign off the change and party like its 1999 (pre-Y2K catastophies! [psych])

Friday, July 29, 2011

Management Reporter reports stuck in the queue.


Well, your Management Reporter reports are stuck and you can't run anything.  That is no fun.  What the hell is going on?

Don't worry (yet).  This is a common issue that we see with Management Reporter.  It will happen in any product that runs MR whether it is AX, GP, NAV, or similar. It can be due to many issues.  The key to this is determining what is causing it if it occurs on a very common basis.

Thankfully, there is an easy way to fix this: restart the MR services.  The tricky part is finding out why its happening since its not a reasonable expectation to have to deal with this when it goes down all the time.

Below is a good guide from Microsoft in debugging this issue.  I would STRONGLY suggest any IT staff dealing with MR read this guide since this issue will inevitably happen.

There are five potential causes for this error:
There are five potential causes for this error: 

Cause 1
If the Management Reporter Process Service is on the same machine as the machine hosting your ManagementReporter SQL database. The Process Service may have errored out by attempting to start before SQL Server was accepting connections. See Resolution 1 in the Resolution section. 

Cause 2
A SQL Server connection error has occurred and the Management Reporter Process Service needs to be restarted. See Resolution 2 in the Resolution section. 

Cause 3
The user running the Management Reporter Process Service does not have sufficient permissions to read from the ManagementReporter SQL Server database. See Resolution 3 in the Resolution section. 

Cause 4
The SQL Service Broker on the ManagementReporter SQL Server database is not enabled. See Resolution 4 in the Resolution section. 

Cause 5
This can happen if the owner of the Management Reporter database is a Windows User while the SQL Server Service is being run by a local user. If you check the Event Viewer, you may see this message:

An exception occurred while enqueueing a message in the target queue. Error 15404, State 19. Could not obtain information about Windows NT group/user 'domain\user', error code 0x5.

See Resolution 5 in the Resolution section.
Resolutions

Resolution 1
If using Windows Server 2008 you can set the Management Reporter Process Service to Automatic (Delayed Start) rather than Automatic.
OR
Restart Process Service manually or with a script similar to the following:

NET STOP MRProcessService
NET START MRProcessService

Resolution 2
Restart Process Service manually or with a script similar to the following:

NET STOP MRProcessService
NET START MRProcessService

Resolution 3
Grant the user running this service the GeneralUser role under the Management Reporter database in SQL Server. This user can be found on the Log On tab under the Services Control panel.

Resolution 4
Run the following statement on the SQL server where your ManagementReporter database resides:

SELECT name, is_broker_enabled FROM sys.databases WHERE name = DB_NAME() AND is_broker_enabled = 1

This statement should return a row for the ManagementReporter SQL Server database. If it does not, run the statement below to re-enable the SQL Service Broker on the ManagementReporter SQL Server database:

ALTER DATABASE [ManagementReporter] SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE;

Resolution5
Change the database owner to sa or change the SQL Server Service user to a domain user.

Wednesday, July 27, 2011

How to find the SQL Server version from within AX 2009

I am usually asked how to find various information around SQL Server from within AX. This can happen from either a fellow consultant or a client.

Usually from a consultant standpoint, it is in the scenario where they are thrown into a situation where they don’t really know anything about the client and it is one more thing for them to ask people. Another scenario would be when a consultant or client need to submit a ticket to a company for support and the company needs to know some information around SQL Server.

Whatever the case may be, people will need to be able to get information about SQL from AX and those people may not be technologically inclined. AX has a way to do this :-)

To find out information about SQL, navigate to Administration -> Inquiries -> Database -> ‘Database information’ (Figure 1).

Figure 1 - Database Information form location
In figure 2 below it, shows the Database Information form that will pop up to the user. There are three tabs on this form: ‘General’, ‘System variables’, and ‘ODBC’. There is a whole lot of information on these tabs but I doubt a lot of it would apply to most people. The primary information people will want to see:
  • First tab (Figure 2)
    • Logon database
      • The database the current AX environment is using
    • Logon server
      • The server where the database is located
    • Database
      • The type of database AX is running against (SQL or Oracle)
  • Third tab (Figure 3)
    • DBMS_VER
      • The version of SQL Server that AX is running (please refer to the next paragraph for translating this number to something that means something)
Feel free to add to the various fields you find helpful in the comments below. I don’t want to detail them all…

When assessing what SQL Server version your current AX environment is on, look at the third tab’s DBMS_VER variable described above. You can take this number and compare it to numbers you can find online. For example, if the database is SQL Server and the DBMS_VER is 10.50.1600, try entering ‘SQL Server 10.50.16000’ in a search engine (Bing!) and you should see the server version and Service Pack version.

From my example above, using the list of versions I’ve included below, indicate that my current AX environment is running SQL Server 2008 RTM.

SQL Server 2000 version numbers:
-RTM - 8.0.194
-SP1 - 8.0.384
-SP2 - 8.0.534
-SP3 - 8.0.760.0
-SP3a - 8.0.760
-SP4 - 8.0.2039

SQL Server 2005 version number examples:
-RTM - 9.0.1399
-SP1 - 9.0.2047
-SP2 - 9.0.3042
-SP3 - 9.0.4035

SQL Server 2008 version number examples:
-RTM - 10.0.1600
-SP1 - 10.0.2531

Figure 2 – Tab one of the Database Information form
Figure 3 – Tab three of the Database Information form
Hope this helps!

Tuesday, June 28, 2011

Cycle through datasources and ranges to find values

Here is some basic code to cycle through a datasource in AX 2009 X++ and then loop through all of the data sources and their ranges and present some info to the users. Its nice for analyzing queries if something is not acting right. 

If you use this code, please leave me a comment and say thank you.  Its nice just to have someone say hi or thanks for using code like this.  If you don't use it and it helps you out, feel free to say so to.  We're all friends here :-)

// START CODE
// 2009 DAX DUDE

    int test1;
    int test2;
    int dsCount;
    int dsPlace;
    QueryBuildRange qbrTEST;
    QueryBuildDatasource qbdsTest;

    dsCount= queryRun.query().dataSourceCount();
    for (dsPlace= 1; dsPlace<= dsCount; dsPlace++)
    {
        qbdsTest = queryRun.query().dataSourceNo(dsPlace);

        test1 = qbdsTest.rangeCount();

        for (test2 = 1; test2 <= test1; test2++)
        {
            qbrTEST = qbdsTest.range(test2);

            info (strFmt("Range Field %1, Value %2", qbrTEST.AOTName(), qbrTEST.value()));
        }
    }
// END CODE

GUEST POST: Setup email alerts in DAX 2009

I have to include a reference to Nagaraj Jadhav's blog as he does a great job with all his posts.

This is a great blog around setting up email alerts in AX 2009.  I would normally try to improve upon things but I don't think I can on this one. Enjoy!

Below
http://learnax.blogspot.com/2010/12/setup-email-alerts-in-dax-2009.html

Sunday, April 24, 2011

Designing an interface queue in AX:

When I create tables that are used in the interface to hold large strings of data (like a large blob or XML from external system or AX report), I put those fields in a separate table linking to the original 'metadata' table through a unique key.  This would make the typical one table interface turn into two tables: one to hold the metadata for the user and the other to hold the large files.  

In using this design, there are many upsides but two primarily stick out that I would like to talk about:

The first is the obvious performance gain in the form used to manage the records in the interface.  When, for example, 20 records are retrieved from the database, records that do not contain an extremely large fields will come back faster.

The second is in regards to the maintenance.  A user may not need the data stored in the large fields after a few weeks but would still want to maintain the history of that data coming into the system.  To do this on a single table structure would require a cleanup job to specifically clear out the field holding the large data.  Doing this in a two table structure would allow the entire record to be deleted, but leave the original record in place.  A simple inner join between the two tables would show all records in those tables that still have the data in place.

Discuss your preferred way to do this below in the comments section...

Saturday, April 23, 2011

Improve Performance for slow retrieval of records in a grid

Sometimes there are forms that take a long time to load the data in a grid.  A common example of this would be for an AX interface where there is a grid that holds records in various statuses (e.g. Waiting, Error, Ended, etc) and carry data in the data source table that the user would normally not care about seeing (e.g. XML).  

I generally would not include a large field on a table that is used in something like an interface.  I have recommendations for designing one in my blog post called "Recommendation in designing an interface queue in AX".

The following fix may not be the best option for addressing the issue as there are lots of factors that can affect performance, but this fixed it for me.  Its fixed the issues for me in a few instances that I've seen and have remained stable with no issues for over 3 years.  

There is a property on a form's data source called 'OnlyFetchActive' that was able to resolve the problem for me.  I've included the exact information from MSDN to assist you in determining whether this could work for your issue.

From MSDN AX 4.0 - Form Data Source Properties      "Determines whether all fields in the data source should be fetched, or only those that are used by controls on the form.
This property is designed to be used in lookup forms. There is no code in these forms, and they open more quickly because the result set is smaller.

When the OnlyFetchActive property has been set to Yes, records cannot be deleted from within the form. This is to preserve data integrity by ensuring that a delete operation is never attempted on incomplete records. If the user attempts to delete a record, an error message is issued."






Monday, April 18, 2011

AX AOS randomly crashes after a code promotion

I recently encountered an issue where a code promotion was done from a staging environment to a production environment and, the next day, the AOS'es would all crash in both client and batch (server) mode when a process not relating to the code promotion (Invoicing) was run.  The code all compiled in PROD and everything was working great during all tests in lower environments.

Simple solution: 
Run a compile forward on any base class (eg Classes\CustVendSettle) affected from the previous promotion.
The journey to this solution:
After looking at the AX Crash Dump file, we were able to extract out the call stack to determine where the crash was occurring. It pointed to a class (eg CustVendSettle_VendPaym) inheriting a base class (eg CustVendSettle) looking for a global variable that was found in the CustVendSettle class.  The references to CustVendSettle were not updated for the CustVendSettle_VendPaym class.  This was causing the AOS to crash.

The take away:
I normally compile forward when errors are received in the process being imported.  There were no errors on this import and the process in PROD was running fine during the weekend validation testing.

There is a difference between a compile and compile forward.  A compile just compiles the class that is compiled. A compile forward on the main (eg CustVendSettle) will compile that class as well as update the references to that for all class that inherit it (eg CustVendSettle_Cust, CustVendSettle_VendPaym, etc).
A compile forward will not run automatically on import and all classes could compile successfully if just compiled. Anytime a change is made to a base class involved in inheritance (eg CustVendSettle, SalesFormLetter, etc), a compile forward on that class is needed. A good example of something that would be guaranteed to need this is making a change in the classDeclaration on a class that is inherited.
In AX 2009, a compile forward can be done by right-clicking on the object that is inherited,  go to 'Add-Ins', then 'Compile forward'.  Once this was done, the process worked and no longer crashed the AOS.  Hooray...

Hope that helps anyone hitting the same issue.

Friday, April 1, 2011

AX 2009 Best Practice Violation: Display methods must be typed ('VarString, displayMethodName')

Hit a display method violation I recently hit in AX 2009: 'Display methods must be typed ('VarString displayMethodName').  There wasn't anything online about this issue outside of MSDN documentation about the BP so I thought I would put this out there for whoever wants to read it.

From: http://msdn.microsoft.com/en-us/library/bb530207.aspx
_________________________________________________________________________________
Display methods must be typed ('%1 %2') For more information, see Best Practices for Unique Labels. Table No Extended Return Type, @SYS60362
_________________________________________________________________________________

How to resolve the BP deviation: Check the display method in question (eg 'displayMethodName' from my example above).  Check the top line where you declare the method.  You cannot use a non-EDT string for a display method.  The line 'display str displayMethodName(CustTrans _custTrans)' would need to be (as an example) 'display CashDiscAccount displayMethodName(CustTrans _custTrans)'. Note that the 'str'was replaced with the EDT of the returned value of the display method.

Making this change to the display method will solve the issue.

Wednesday, March 30, 2011

BOMConsistOf Report different in AX 2009 from 4.0

There was an issue where a customer upgraded from AX 4.0 to 2009 and reported a problem with the BOMConsistOf (Lines) report which prints items that the bills of materials are composed of, or versions used by the items.

Figure 1 (AX 4.0) and 2 (AX 2009) below are the same X++ report and have the same code (even modified the XPO file to import the code from one to the other to assure that they are equal) but they still look different when run under the same data.

The strange thing is that this is coming from the same AX system (AX 2009) with the same code and data set.  The only difference is in name.  I exported the 4.0 report into a new report in AX with a new name to verify the differences, exported this XPO once the report matched the old one, then modified the XPO contents so it would import into the base report but still no success.

Thought I would note this on here if anyone is curious.  I fixed this issue by importing the 4.0 report to a new custom report in AX 2009 called 'BOMConsistOf_version40' and point the security key to the new report.  Works like a charm. Still don't know why this incongruency exists...


Figure 1 - BOMConsistOf report from AX 4.0

Figure 2 - BOMConsistOf report from AX 2009

Thursday, March 24, 2011

Error: CLR object cannot be marshaled to Microsoft Dynamics anytype

I was hitting a problem with marshaling a string from System.String to str datatype (X++). The error was 'CLR object cannot be marshaled to Microsoft Dynamics anytype' when I tried to convert them using the code below.  This is how I fixed it. Hope it helps you out...

System.String clrString;
str                  axString
;

clrString = Microsoft.Win32.Registry::GetValue(XXXX, XXXX, XXXX);

// This way does not work in AX 2009 despite what you read online
// axString = clrString;

// This is the way the marshaling needs to occur
regValue = System.Convert::ToString(clrString);

Monday, March 21, 2011

Consume AIF Inventory On Hand web service in AX PART 2 - WSDL request


This is the second part of the consuming AX 2009 AIF On Hand Inventory web service via C#. The first part was consuming an AIF web service using SOAP. This one is using WSDL

DocumentContext context;
WebReference.InventoryOnhandService ws;

// Populate Document Context
context = new DocumentContext();
context.SourceEndpoint = "DAT";
context.DestinationEndpoint = "DAT";
context.SourceEndpointUser = Environment.ExpandEnvironmentVariables("DOMAIN\\WEBSERVICEUSER");
// Invoke the Web Service
ws = new WebReference.InventoryOnhandService();
ws.Credentials = new NetworkCredential("WEBSERVICEUSER", "PASSWORD", "DOMAIN"); // System.Net.CredentialCache.DefaultCredentials; // Use the current user to authenticate in IIS
ws.Url = "http://99.999.99.99/inventoryonhandservice.asmx";

// Create new Guid
context.MessageId = Guid.NewGuid().ToString();

//Create Query Criteria
CriteriaElement myCriteria = new CriteriaElement();
myCriteria.FieldName = "ItemId";
myCriteria.Operator = Operator.Equal;
myCriteria.Value1 = "AX_ITEM";
myCriteria.DataSourceName = "InventSum";

QueryCriteria myQueryCriteria = new QueryCriteria();
myQueryCriteria.CriteriaElement = new CriteriaElement[1];
myQueryCriteria.CriteriaElement[0] = myCriteria;

// Call find list
WebReference.AxdInventoryOnhand ioh = ws.findListInventoryOnhand(context, myQueryCriteria);

// Display the result
Console.WriteLine(ioh.InventSum[1].ItemId);
Console.Read();

Consume AIF Inventory On Hand web service in AX PART 1 - SOAP request

Sample XML consumption in C# code to AIF Inventory On Hand. This is from AX 4.0 but I think it's the same in AX 2009.
try
{
     string strSoapEnvelope = "";
     string responseString = "";

     // Build SOAP envelope
     strSoapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
     strSoapEnvelope += "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">";
     strSoapEnvelope += "<soap12:Body>";
     strSoapEnvelope += "<findListInventoryOnhand xmlns=\"http://schemas.microsoft.com/dynamics/2006/02/documents/InventoryOnhand\">";
     strSoapEnvelope += "<DocumentContext>";
     strSoapEnvelope += "<MessageId>" + Guid.NewGuid().ToString() + "</MessageId>";
     strSoapEnvelope += "<SourceEndpointUser> DOMAIN \\WEBSERVICESUSER</SourceEndpointUser>";
     strSoapEnvelope += "<SourceEndpoint>XXXXXXXXXXXXXXXX</SourceEndpoint>";
     strSoapEnvelope += "<DestinationEndpoint>ENDPOINT NAME</DestinationEndpoint>";
     strSoapEnvelope += "</DocumentContext>";
     strSoapEnvelope += "<QueryCriteria xmlns=\"http://schemas.microsoft.com/dynamics/2006/02/documents/QueryCriteria\">";
     strSoapEnvelope += "<CriteriaElement>";
     strSoapEnvelope += "<DataSourceName>InventSum</DataSourceName>"; strSoapEnvelope += "<FieldName>ItemId</FieldName>";
     strSoapEnvelope += "<Operator>Equal</Operator>";
     strSoapEnvelope += "<Value1>YYYYYYYYYYYYYYYYYY</Value1>";
     strSoapEnvelope += "</CriteriaElement>";
     strSoapEnvelope += "</QueryCriteria>";
     strSoapEnvelope += "</findListInventoryOnhand>";
     strSoapEnvelope += "</soap12:Body>";
     strSoapEnvelope += "</soap12:Envelope>";
     MSXML2.XMLHTTP xmlHTTP = new XMLHTTP();
     xmlHTTP.open("Post", "http://ZZZ.ZZ.ZZ.ZZZ:ZZZZ/inventoryonhandservice.asmx", false, @"DOMAIN\WEBSERVICESUSER", " PASSWORD");
     xmlHTTP.setRequestHeader("Host", "99.999.99.99");
     xmlHTTP.setRequestHeader("Content-Length", strSoapEnvelope.Length.ToString());
     xmlHTTP.setRequestHeader("Content-Type", "application/soap+xml; charset=utf-8");
     xmlHTTP.send(strSoapEnvelope.ToString());

     responseString = xmlHTTP.responseText.ToString();
     MessageBox.Show(string.Format("XML: {0}", responseString.ToString()));

     WebClient webby = new WebClient();
     webby.Encoding = System.Text.Encoding.UTF8;
     webby.Credentials = new NetworkCredential("WEBSERVICESUSER ", "PASSWORD", " DOMAIN");
     webby.Headers.Add("Content-Type", "text/xml;");
     string stuff = webby.UploadString("http://99.999.99.999/inventoryonhandservice.asmx", "POST", strSoapEnvelope.ToString());

     MessageBox.Show(stuff);
}
catch (Exception ex)
{
     MessageBox.Show(ex.ToString());
}

AIF Integration Differences: .NET BC vs XML integration to AX 2009 web service


I've received a question from a customer: 'We have two vendors who are integrating into AX using the same AIF web service except that one integration has the failed XMLs in the AX Queue Manager (Basic -> Periodic -> Application Integration Framework -> 'Queue Manager') but the other doesn't have a record in there. Both integrations, when they have transaction errors, show up in the Exceptions form (Basic -> Periodic -> Application Integration Framework -> 'Exceptions'). What gives?'

Good question! Here are two ways to integrate into AX's AIF: 1) .NET BC or 2) XML (eg SOAP, WSDL). From the scenario above, it sounds like the vendors are each using a different integration type. The one with failed XMLs in the AX Queue Manager is using the XML hitting the web service method while the other that is just showing errors in the Exceptions form is using the .NET BC.

When using the .NET BC integration method, the AX Queue Manager is not used as this feature is used for XMLs and parsing the data from them into the AIF web service AX components.  The .NET BC way is not using XMLs, but instead, writes the data directly to the AIF web service AX components completely bypassing the XML step (hence no record in the Queue).

Both methods are using the AIF framework objects which is why the errors relating to AX data are all showing up in the Exceptions form.

The XML integration way handles resubmitting failed data through the AX Queue Manager. Without AX modifications, the .NET BC will need to have an external way of resubmitting failed data to the web service.

With this in mind, depending on the application, both ways have their pros and cons. Hope this helps explain the issue my customer saw above.

For an example of the XML Consumption of the Inventory On Hand service in C#, check my other blog posts on here somewhere with some name (descriptive right??).

Thursday, March 17, 2011

AX Error: Cannot execute a data definition language command on (). The SQL database has issued an error


If you are seeing the error 'Cannot execute a data definition language command on (). The SQL database has issued an error', this is how you can resolve it.





Step 1 – Synchronize the SQL database
  1. Navigate to Administration module -> Periodic -> 'SQL Administration'
  2. Select the table and click table actions check/synchronise
    1. Sometimes you will not be able to determine which tables are causing the error so just do this for all
  3. Click 'Start' with the default options.
     
Step 2 – Step 1 with 'Remove unknown indexes' in the check/synchronise step
  1. Follow steps 1 and 2 from step 1
Step 3 – Check the Event Viewer (SQL and AOS box)
  1. This should give you a good indication on where to go for the issue going forward as there could be index violations.

Wednesday, March 16, 2011

AX 2009 AIF Common Errors


Hello. You may be looking at this posting because you are going bald over dealing with the AIF. This blog post will be growing as I add more. I don't want to have it accumulate in my ToDo bin waiting to remember all of the errors.

Common errors in the AIF: 
  1. On the AIF Queue Manager form (Basic -> Periodic -> Application Integration Framework -> 'Queue Manager')
    'The user is not authorized to perform this action'
    You will want to check the XML node <SourceEndpointUser> on the XML that failed to make sure that a few things are true:
  • The user is valid in AX
  • The valid AX user is added to the endpoint
  • The domain is included in on the user (eg the source endpoint text would look like this: TEST_DOMAIN\PeeWee.Herman)
  • Make sure the '\' in the name is facing the correct direction

Wednesday, March 9, 2011

Good Quotes

Here are some good quotes/philosophies that I feel teach great lessons in business that I've collected through the years. 

I'll keep updating these as this blog is my meant to be my personal file folder that just so happens to be public. Feel free to add more in the comments section.  Enjoy!
  • "It's not what you do, but it's what you do about it" ~my dad
  • "Be Prepared!" ~Boys Scouts of America
  • "Tell me and I'll forget; show me and I may remember; involve me and I'll understand." ~Chinese proverb
  • "If you're interested in 'balancing' work and pleasure, stop trying to balance them. Instead make your work more pleasurable." ~Donald Trump
  • "A man only learns in two ways, one by reading, and the other by association with smarter people." ~Will Rogers
  • "A 'No' uttered from the deepest conviction is better than a 'Yes' merely uttered to please, or worse, to avoid trouble." ~Mohandas Gandhi
  • "Even if you're on the right track, you'll get run over if you just sit there." ~Will Rogers
  • "A boo is a lot louder than a cheer. If you have 10 people cheering and one person booing, all you hear is the booing. " ~Lance Armstrong
And now, a quote about quotes: "I never said most of the things I said." ~Yogi Berra

UPDATE: There are such things as Chinese Proverbs.  They are not some cop-out way to pretend you are quoting something smart. http://www.quotationspage.com/quotes/Chinese_Proverb/  There actually a lot of them and they are legit and official.  

Monday, March 7, 2011

AX Carriage Return - Address field


In AX, a field that is an address will likely show up on multiple lines with the street name, city, state, etc on different lines. In previous versions of AX, carriage returns were seen in the AX database and table browser with a '' value. In AX 2009, you will just see a string value with these squares absent. The spacing is determined some other way.

Since there are no square carriage returns in the strings in AX 2009, how we determine when the values will return to a new line? I've seen an error where there is a magical break in an address with no explanation as to why it would be this way. In the image below, the string in the SalesTable.DeliveryAddress field would look like '272 E ASHE DRASHEBORO, NC 27203US'. Why is there this big blank thing?

The Extended Data Type (EDT)'s DisplayHeight property value specifies the number of lines to be displayed simultaneously when the EDT is displayed in a form.

If the value is NOT equal to 1 (Figure 3), the value will be displayed in a single line like it appears in the DB (eg '272 E ASHE DRASHEBORO, NC 27203US'). If the value is not 1 (Figure 2), it will add the spaces and split up the line into multiple lines. This DOES NOT mean that it will be split into 2 lines. It will split the exact same way it does with 5 but instead show the field in the form with 2 lines and give you a scrolly bar for the field (Yuck!).



Figure 2 – The 'DisplayHeight' value dictates the size of the display



Figure 3 – The 'DisplayHeight' value dictates the size of the display. NOTE: on one line.

This makes me wonder, what happens when this DisplayHeight value is not 1? Using the all of the powers of the internets and the Bing/Google, I didn't get anything. L Looks like it is something that is hidden in the kernel now.

Still can't find anything on this but I solved the issue: On the street, there was a process somewhere that was putting an enter in after the string. This made it look like there was a blank space in it. This blank space would not show up in the address field string but the string could somehow put that in there between the street and the city while not showing the value in a string.

Interesting mystery…

Thursday, February 10, 2011

ASK ME A QUESTION AND I'll [TRY TO] POST ABOUT IT

Please shoot me an email with your AX tech questions and I'll see what I can do about answering them. If I answer it, unless you request otherwise, I will use it as a post on this website.

I'm looking for new things to fill my blog up with. I have tons but I want to learn some fun stuff that I may not have in my toolbelt but that would increase my arsenal of stuff I use for clients as well as teaching. I'm an information hog.

I can't guarantee a fast response unless you have talked to me before and I gave you alternate contact information that I check more often.
So... PLEASE ASK ME A QUESTION!!

Use X++ wildcard (LIKE and NOT LIKE) in X++ select statement

If you want to use wildcards in an AX X++ select statement (*), you will have to use the LIKE command. The following select statement will find all captions in the batch tasks (BatchHistory) table.

For x++ select statements:
select firstOnly batchHistory
     where batchHistory.Caption LIKE "*Test*"


For x++ queries:
queryBuildRange.value(*Test*);

Note the LIKE instead of a '==' and the wildcards inside of the quotations. All other combinations of wildcard usage will work here. This is the same functionality as what the users would put in the grid filtering(eg. '*TEST*' in the caption field filter on the batch tasks form).

However, if you want to find all Captions that do not have the word Test in them (NOT LIKE, !LIKE), you will have to modify the above example slightly.

For x++ select statements:
select firstOnly batchHistory
     where !(batchHistory.Caption LIKE "*TEST*");


For x++ queries:
queryBuildRange.value(!*Test*);

Note the "!(" and ")". Again, this is the same functionality as what the users would put in the grid filtering(eg. '!*TEST*' in the caption field filter on the batch tasks form).
I hope it helps you out!

Wednesday, February 9, 2011

AX 2009 Batch Job Stuck In Executing

Having a batch job stuck in the Executing status in AX 2009 is a pretty common thing for me to get a call about when a customer is upgrading or doing an implementation.

One of the first things that I check is to make sure that the batch job that is stuck in executing has all tasks set to run on the server. You can check this out by going to Basic -> 'View Tasks' button -> 'Run location' field. If it is set to 'client', that is the issue. The next step is determining why this happened.

Check 1: Check the menu item (probably an Action or Output) and make sure the 'RunOn' property is set to 'Server'. If not, change it.

Check 2: Find the class where the 'runsImpersonated' override is. This value must be true. If it is false, change it.

Check 3: Look inside the code for anything that has a client call in it (hint: WinAPI calls a big culprit). If you find some, find an alternate way to do the task using server side calls instead of client(eg System.IO instead of WinAPI). If you're not sure if a method is running client or not, check the method declaration for the word client. If its there, its client. If nothing is there, use the call Global::isRunningOnServer() which will return a boolean of true if you are server side.

I'm sure you're asking yourself 'Why do I have to do this?!?! Couldn't Microsoft leave it like it was??'. There are a variety of reasons that this change was made and it's awesome. The biggest benefit is better performance because all of the processing is on the server so the client->server calls are eliminated. But maintenance and deployment is also a biggie.

The new AX 2009 batch engine does all of its processing on the server whereas the previous AX 4.0 batch engine ran the code client side. Because of this, batch jobs will get hung up if it makes a call that runs client side (aka WinAPI). AX 4.0 had to have services (at least that was our preferred method) that booted up the AX program and had a user run the program like a user and then kick off the process. Remember the little moving progress boxes? No more in the batch engine. Also NO MORE SERVICE MONITORING APPS RUNNING EXTERNAL TO AX! You can manage the batches from within AX now.

if(this.isThisTextBlinking)
{
     warning('your browser is out of date...')
}