To continue my series about exception handling in NAV, this time I’ll discuss how to gain insight into exceptions in NAV. As I mentioned already, the GETLASTERROROBJECT function gives you an instance of System.Exception, actually of a class descending from it, which allows you to get more information about the context of the error that has just happened.
One part of the context you have already learned in the previous post – it’s the exception type. Since each exception is strongly typed, you can compare against each exception you get with its expected type.
Another important context element of the exception, which is kind of understood, is its Message property. It is of type System.String and it gives you the error message. Depending on what exactly you are doing, in most cases it will just match whatever you get from the GETLASTERRORTEXT function.
However, the most important context element of the System.Exception class is its InnerException property – it gives you access to details of the exception. You see, unlike errors in NAV, which are (or at least they used to be before NAV 2015) pretty flat, exceptions in the .NET world are quite complex. You can have an exception which contains an inner exception (which can in turn contain an inner exception) which tells you in more detail what exactly kind of exception happened.
To better understand this concept, let’s take a look at the following failing codeunit:
A no brainer, really. It plainly gives the division by zero error. Now take a look at the handler for this exception:
If you want to handle the division by zero exception, you are toast, because it shows this:
And – mind you – the division by zero is actually the System.DivideByZeroException type. Obviously, if you write some error handling code to handle the DivideByZeroException then the Exception instance in the code above by itself does not help.
However, its InnerException property (again, of type System.Exception) can help. So, change the code like this:
Run it, and you get this:
So, if you want to properly handle the exception of the System.DivideByZeroException, you would have to take a look at the InnerException property of the result of the GETLASTERROROBJECT function call.
However, in all likelihood, in most situations you’ll just want to look there anyway. There are a range of exception types that GETLASTERROROBJECT will give you, which don’t provide any valuable insight directly, and where you need to peek into the InnerException to actually understand what happened. Apart from the NavALException, another one that you’ll frequently see is this:
This one will happen whenever you make a .NET interoperability call, and it fails for whatever reason. You’ll just need to take a look inside of the InnerException to realize what exactly kind of exception it was.
And here we come to the point of my two previous posts – handling exceptions purely by name is baaaad. When handling the resulting exception directly, you are fairly safe, because – as I’ve shown – all of them are from the same Microsoft.Dynamics.Nav.Types.dll assembly. However, when handling inner exceptions, these can come from any assembly in the world, and there is no guarantee that you might get two different exception types which have the same name, but are not of the same type. Yes, you could use the AssemblyQualifiedName property, but it’s both ugly, and it’s hardcoding. If you don’t believe me, just compare this:
… to this:
There is a big difference here, isn’t there?