Code highlighting

Showing posts with label Exception. Show all posts
Showing posts with label Exception. Show all posts

Thursday, March 30, 2017

Development tutorial: Platform improvements for handling X++ exceptions the right way

A while back I wrote about a pattern we discovered in X++ code which could lead to serious data consistency issues. You can read it again and look at an example mfp wrote up here:
http://kashperuk.blogspot.dk/2016/11/tutorial-link-handling-exceptions-right.html

With the release of Platform update 5 for Dynamics 365 for Operations we should now be better guarded against this kind of issue.

Let's look at the below example (needs to be run in USMF company):

class TryCatchAllException
{
    public static void main(Args _args)
    {
        setPrefix("try/catch example");

        try
        {
            ttsbegin;

            TryCatchAllException::doSomethingInTTS();

            ttscommit;
        }
        catch
        {
            info("Inside main catch block");
        }

        info(strfmt("Item name after main try/catch block: %1", InventTable::find("A0001").NameAlias));
    }

    private static void doSomethingInTTS()
    {
        try
        {
            info("Doing something");
   
            InventTable item = InventTable::find("A0001", true);
            item.NameAlias = "Another name";
            item.doUpdate();

            throw Exception::UpdateConflict;

            // Some additional code was supposed to be executed here
        }
        catch
        {
            info("Inside doSomething catch block");
        }
  
        info("After doSomething try/catch block");

    }

}

Before Platform Update 5 the result would be:


As you can see, we 
  • went into doSomething()
  • executed the update of NameAlias for the item, 
  • then an exception of type UpdateConflict was thrown
  • At this point the catch-all block caught this exception without aborting the transaction, meaning the item is still updated. We did not abort the transaction because we did not think about this case before
  • We exit the doSomething() and commit the transaction, even though we got an exception and did not want anything committed (because the second part of the code did not execute)
  • As a result, the NameAlias is still modified.

Now with Platform Update 5 the result will be:

That is, we

  • went into doSomething(),
  • executed the update of NameAlias for the item,
  • then an exception of type UpdateConflict was thrown
  • At this point the catch-all did not catch this type of exception, as we are inside a transaction scope, so the exception was unhandled in this scope, and went to the one above
  • Since we are by the outer scope outside the transaction, the catch-all block caught the exception,
  • and the NameAlias is unchanged


So, again, we will simply not handle the 2 special exception types (UpdateConflict and DuplicateKey) any longer in a catch-all block inside a transaction scope, you will either need to handle them explicitly or leave it up to the calling context to handle.

This will ensure we do not get into this erroneous code execution path where the transaction is not aborted, but we never handle the special exception types internally.

Hope this helps!

Thursday, November 24, 2016

Tutorial Link: Handling exceptions the right way in X++

Michael and I have been working the last couple of weeks to uncover some of the difficult to repro bugs in Warehouse management code, and one of the things we discovered is a pattern which can lead to very unpredictable behavior when used incorrectly.

I encourage all of you to read it and make sure all of your code is up to standard.

https://blogs.msdn.microsoft.com/mfp/2016/11/24/x-the-catch/


Thanks!

Friday, February 05, 2016

Tips: Configuring Warehouse Mobile Devices Portal after installation on CTP7 and CTP8 builds of the latest Dynamics AX release

Introduction

Over the last couple of months we have had a number of customers go live on the latest version of Microsoft Dynamics AX, and some of them have decided to use the Advanced Warehousing solution including the Warehouse Mobile Devices Portal (WMDP) that is shipped together with AX.

In my last post I provided links for how to install and use the portal:
http://kashperuk.blogspot.dk/2016/01/tutorial-warehouse-mobile-devices.html

Here I would like to focus on a few aspects we've learnt based on interaction with the Go-Live customers, that will hopefully help some of you to avoid the same problems.

Tip 1

In CTP7 and CTP8 (in case you don't know what CTP stands for, read wiki) WMDP was not strongly signed. That means that on your environment after installation, you could receive an error like below (In Event Log):

Exception information: 
    Exception type: ConfigurationErrorsException 
    Exception message: Could not load file or assembly 'Microsoft.Dynamics.AX.Whs.Web, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. Strong name signature could not be verified.  The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT: 0x80131045)

In the final (RTW) release of Microsoft Dynamics AX the assembly is strongly signed.

But if you are on CTP7 or CTP8, you can refer to one of the below solutions:

Solution 1

One thing you can do to resolve this is sign the assembly, using the strong name tool in a command like the following:

C:\Program Files (x86)\Warehouse Mobile Devices Portal\DEFAULT\bin> sn -Vr .\Microsoft.Dynamics.AX.Whs.Web.dll

This is the preferred approach.
For test environments, you could also just go with Solution 2

Solution 2

You can also just disable strong name verification on the machine you are testing out the portal on, by modifying the registry with commands below (for x86 and x64):

reg DELETE HKLM\Software\Microsoft\StrongName\Verification /f
reg ADD HKLM\Software\Microsoft\StrongName\Verification\*,* /f
reg DELETE HKLM\Software\Wow6432Node\Microsoft\StrongName\Verification /f
reg ADD HKLM\Software\Wow6432Node\Microsoft\StrongName\Verification\*,* /f 

Or, if you want to limit the scope of allowed non-signed assemblies, you can restrict it to just the WMDP dll in the above ADD commands like below:

reg ADD HKLM\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.Dynamics.AX.Whs.Web,31bf3856ad364e35

reg ADD HKLM\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.Dynamics.AX.Whs.Web,31bf3856ad364e35 

If you want to learn a bit more (or get a ready PowerShell function for the above), refer to this blog post.

Tip 2

WMDP is an ASP.NET MVC based web site and has a number of important configuration options in its web.config file. You can read more about the configuration options on MSDN.
One particular setting is important to note, since it is believed that it has an "incorrect" value by default after installation in AX 2012 CU8 build.

The setting is customErrors, and you can read all about it on MSDN

In production environments, this setting should always be set to "On", as WMDP X++ code in some cases throws unhandled exceptions, which result in a complete meltdown of the web site, if not redirected correctly to a user-friendly error page. 
The "Off" setting can be used on test environments when debugging the site, as it will provide call stack information for what happened. 

Hope this helps!

And let me know if you have additional tips to add here about WMDP, I will gladly add them here