Wednesday, 9 April 2008

Try Catch in Dynamics NAV

This has to be up there on my list of "all time desirable features" for NAV. As you probably know NAV has an ERROR function that is used to, well, throw errors. It will abort the current transaction (and roll back to the point of the last commit) and display the text message that you selected in an error dialogue box.

The thing is, sometimes you don't want it to do the abort and rollback. For example if we are importing a file or maybe a series of files, we may just want to log the error somewhere and carry on with the next file. You can do this in NAV 5.0 using the new GETLASTERRORTEXT function.

Here's an example of how to do it.

First of all, create a simple codeunit that, when run, will throw an error:

OBJECT Codeunit 50000 ThrowError
{
OBJECT-PROPERTIES
{
Date=09/04/08;
Time=[ 9:34:55 PM];
Modified=Yes;
Version List=;
}
PROPERTIES
{
OnRun=BEGIN
// Call a function that throws an error.
DoSomething();
END;

}
CODE
{

PROCEDURE DoSomething@1000000000();
BEGIN
ERROR('Hey Look I threw an error.');
END;

BEGIN
END.
}
}


When you run this codeunit you get the following error message displayed.



Now create another codeunit that will call the first one and trap the error it generates:

OBJECT Codeunit 50001 Test Throw Error
{
OBJECT-PROPERTIES
{
Date=09/04/08;
Time=[ 9:35:58 PM];
Modified=Yes;
Version List=;
}
PROPERTIES
{
OnRun=VAR
l_ThrowError@1000000000 : Codeunit 50000;
BEGIN
IF NOT l_ThrowError.RUN THEN
MESSAGE(GETLASTERRORTEXT+ ' - or did I?');
END;

}
CODE
{

BEGIN
END.
}
}


When you run this second codeunit, even though it calls the first codeunit, you don't see the error message. Instead you see this:



You'll need to make a COMMIT before trying to trap the return code from running the codeunit but if you have uncommitted transactions you'll get a run time error telling you this. Unfortunately this only works when you Run a codeunit so you either have to use lots of codeunits or write some kind of clever dispatcher that allows you to set the action on the codeunit first and then run it.

So my most desired feature would require some language additions to C/AL. Introduce a TRY CATCH language construct – it would work similar to an IF ELSE statement. Here is an example:


TRY
BEGIN
DoSomething();
DoSomethingElse();
END
CATCH
BEGIN
MESSAGE(GETLASTERRORTEXT);
END;


I have put the BEGIN and END in the CATCH part to illustrate how it work in a similar manner to the IF ELSE construct but it wouldn't be needed. The neat thing about this is you would not need to use a codeunit just to be able to trap the error. The same rules regarding commits, etc. would apply.

I guess I'll just nip over to the Connect site and suggest this little beauty for the product team to ponder over.

4 comments:

Gaspode said...

If you want to vote for this suggested language enhacement, use this link Connect Site Link

Vjeko said...

Amen to this. This would be a great enhancement. The only problem is that the link is broken, so I can't vote even if I'd really love to :-(

Cheers,

Vjeko

Gaspode said...

Yes - weird. It seems that if you are signed in to your Windows Live Passort (that you use for accessing Partnersource and that you used for registering on the Connect site) - it works fine. If you are not signed in then you just get a site not found error.

I also found that the link to the Connect sign up page on my other blog does not work unless you are signed in with your Windows Live Passport.

Vjeko said...

Yep, that's what I did, I logged in using my Live ID that I use to access PartnerSource, but it still gives me 404. Weird.