Debugging Dynamic NAV
From TroubleshootingWiki
| Official Page |
| Project Documentation |
| Download |
|
Contents |
[edit] Identifying problems
Nothing is perfect. Sometime, somewhere, something will most certainly go wrong, the thing will stop working as expected, and the better prepared you are for it, the more chance you have of quickly determining the cause and eliminating it efficiently.
As a multi-tiered application with several distributed components, Microsoft Dynamics NAV 2009 can get troubled by many kinds of problems.
The most common issues, however, are these:
- Bugs, when the system doesn't produce expected results
- Performance issues, when the system doesn't perform as expected
- Scalability issues, when the system can't accept any more users
- Concurrency issues, when users have trouble accessing the database at the same time
These problems may originate in the application itself, or outside of it. To remove the problem, you must first identify the real cause of it, and sometimes this is not as simple as it seems. A slow report can happen to be tracked to a clogged network interface after days of tweaking and tuning the indexes, or a suspected C/AL code bug can turn out to be a poorly defined table relation.
There are many tools at your disposal that you can use for troubleshooting the issues you may encounter during any phase of an implementation project, or even far into the live production stage of the solution. Sometimes it will take a minute in a debugger to correctly diagnose the problem, but often you will need to combine several tools before you get to the root of the problem.
But there is good news for you: all the tools you need are already available to you, because they are already included in the operating system, SQL Server, or Microsoft Dynamics NAV.
[edit] Debugging
When code doesn't execute the way it was initially intended by the programmer, we say we have a bug. Debugging is a process of detecting such code and effectively removing it.
|
An urban legend goes that the term bug has its origin in the early days of computing, when an insect trapped within the computer circuitry could easily cause the sensitive electronics to malfunction. An actual incident in 1947, when two engineers at Harvard University lab found a real bug trapped in a relay, contributes to this legend. The truth is different. Bug, as an engineering term for designating engineering faults, has been in use for many decades, and as early as 1878 it was most likely already widespread, when Thomas Edison mentioned it in a letter to his associate Tivadar Pusk s. Debugging is also not of computational origin. A 1945 article in the Journal of the Royal Aeronautical Society mentions the term in the context of airplane engine testing. It wasn't until mid 1950's that these two terms took on widespread usage among computer scientists. |
Bugs come in many forms. A missing piece of code, which the programmer didn't write for any conceivable reason, an extra line of code, an incorrect condition branching, a variable that wasn't reset these are examples of bugs that frequently happen, and are fairly easy to detect and correct.
Other types of bugs can get uglier: perfectly working code suddenly stops working after another part of code has been changed. Adding parameters to existing functions, adding new options to the middle of existing option fields, changing the length of text or code fields, adding another option field to the table all of these are examples of operations that can cause perfectly working code to stop behaving as expected. We call these the regression issues.
All of these are the situations where you need some debugging tools those that can help you detect and remove any bugs. However, a debugger can come in handy not only for removing bugs. Sometimes perfectly legal situations, such as error messages indicating that some invalid conditions have occurred, can be analyzed and troubleshot using a debugger.
There are two ways you can go about debugging in Microsoft Dynamics NAV:
- Debugging the Classic client: By using a debugger built into the C/SIDE development environment of the Classic client, it is possible to debug business logic contained in all kinds of objects except pages.
- Debugging the Service Tier: To address the limitation of the Classic clients in respect to debugging page objects, you can use Microsoft Visual Studio to debug the Service Tier. Microsoft Dynamics NAV 2009 translates the C/AL code into C#, which is then compiled into .NET assemblies. By attaching Visual Studio to Microsoft Dynamics NAV Server service, it is possible to debug the business logic in the Service Tier.
[edit] Debugging the Service Tier
Microsoft Dynamics NAV 2009 made a step forward towards integrating the development with mainstream Microsoft development tools: .NET, C#, and Visual Studio. While it is still not possible to develop Microsoft Dynamics NAV solutions using Visual Studio, you can make a good use of the fact that all C/AL code is internally translated into C#, and debug that C# using Visual Studio.
Debugging of the Service Tier is not enabled by default. To enable it, you must switch some configuration settings in the Service Tier configuration XML file.
Start Visual Studio and from the File menu, choose Open, then File. Browse to the Service Tier application folder (if you installed Microsoft Dynamics NAV using default options, it should be C:\Program Files (x86)\Microsoft Dynamics NAV\60\Service), locate the file CustomSettings.config, and click Open.
If you have no previous experience configuring .NET applications, you should know that the majority of them come with a .config file, which allows configuring some application-wide settings by editing this file directly. For Microsoft Dynamics NAV Server, it's the CustomSettings.config file you've just opened.
Different configuration settings are stored in <add> tags. Each <add> tag contains two attributes: key and value. Search for the EnableDebugging key, set its value to true, and save the file.
The configuration change you have made won't take effect until Microsoft Dynamics NAV Server service is restarted. You can do so by restarting it using Services console in your administrative tools, or by typing this into your command prompt:
net stop MicrosoftDynamicsNavServer
After it has completed, type this:
net start MicrosoftDynamicsNavServer
|
Create a batch file that contains these two commands one after another, and save it as |
Now go back to Visual Studio, and from the Debug menu choose the Attach to Process option. It will display the Attach to Process dialog. This is used to attach the Visual Studio to an external process you want to debug.
If you are doing this for the first time, make sure to switch on both Show processes from all users and Show processes in all sessions.
Because the Service Tier runs in a session other than your logon session, also in the context of a user account other than your own, without these two options switched on, the list of processes won't include it.
In the Available Processes list, locate Microsoft.Dynamics.Nav.Server.exe and click the Attach button:
This has enabled the debugging in the Service Tier and made your Visual Studio ready to debug some Microsoft Dynamics NAV C#.
The next step is to create C# files for all application objects. Thankfully, this is something that is done automatically when the first RoleTailored client connection is made to the server for which debugging is enabled. Start the RoleTailored client, and lean into your chair: it might take a few minutes before the Service Tier completes its chore.
The RoleTailored client being completely started means that all of the C# translations of underlying application C/AL code have been saved as individual C# files ready to be debugged. To confirm this has happened, browse to folder C:\ProgramData\Microsoft\Microsoft Dynamics NAV\60\Server\MicrosoftDynamicsNavServer\source, and make sure it is not empty. It should contain the following folders: Codeunit, Page, Record, Report, and XMLport.
|
One folder represents each application object type you can debug, with the |
In each of these folders there is one file per C/SIDE object, and files are named in a consistent and logical way: object type, followed by object ID, ending in a .cs file extension. For example, codeunit 80 Sales-Post is saved as file Codeunit80.cs.
Let's debug page 21 Customer Card. Open file Page21.cs in Visual Studio and observe its structure. Every C/AL trigger and function has been translated into a C# function. For example, search for the OnOpenPage trigger, and see how it looks like in C#:
It's much more of a mouthful than the same thing in good old C/AL:
Obviously, with C# there is a lot of overhead with type conversion and .NET infrastructure, but fortunately every original C/AL line has been preserved as a comment line above the matching C# line. This makes reading and understanding much easier.
Now, set a breakpoint on the ActivateFields(); line by positioning the cursor on that line, and from the Debug menu choose Toggle Breakpoint (or press F9):
Now, any time the Customer Card page is opened in the RoleTailored client, the execution will be suspended, and the control will be passed on to Visual Studio and its debugger process.
You can easily confirm this by opening a customer card for any of the customers. If you use the default Sales Order Processor role, you can do it by choosing Customers from the Home pane in the navigation pane, then opening any customer from the list. As soon as the execution hits a breakpoint, Visual Studio is brought into focus, with the execution point line highlighted in yellow, and indicated by a yellow arrow to the left:
A wealth of Visual Studio debugging options is at your disposal, and you can now debug your Microsoft Dynamics NAV application in much the same way as you would debug any .NET application.
As long as Visual Studio is attached to the Microsoft Dynamics NAV Server process, any runtime error caused by C/AL code will also suspend execution and pass control to Visual Studio, which will ask the user whether to debug, or to continue:
Clicking Break will open the source file for the object that caused the error and will start debugging, while hitting Continue will relinquish control back to Microsoft Dynamics NAV Server.
Although debugging using Visual Studio provides a deep insight into Microsoft Dynamics NAV Service Tier processing and .NET concepts at work, this kind of debugging is only a workaround that makes it possible to debug page objects something that is otherwise impossible using the Classic client and built-in Microsoft Dynamics NAV debugger. Translated C# code is much more difficult to follow than native C/AL code, so for debugging all other object types, you'll probably want to stick with the Classic client.
|
Never debug the Service Tier directly in production or any multi-user environment. As it's not possible to specify which user process you are debugging, your breakpoints will be hit for all users, and any runtime errors will halt the execution for users, and pass the exclusive control of the Service Tier process to your debugging session. Always debug on a dedicated single-user machine. |
[edit] Debugging the Classic client
You might decide not to deploy the Microsoft Dynamics NAV 2009 Classic client into production, but you will still spend a lot of time with it during debugging. As much as Visual Studio provides a fancy user interface with numerous options, for the majority of debugging tasks of business logic debugging, you'll probably want to stick with the Microsoft Dynamics NAV Debugger. This kind of debugger is built-in and integrated with the Classic client, and you can use it to debug all kinds of objects, except pages.
To activate debugger, from the main menu choose Tools, then open the Debugger submenu. It contains the following options:
Activating the debugger is a no brainer: clicking Active or pressing the Shift+Ctrl+F11 keystroke combination will set it waiting for a debugger triggering condition to occur.When it is active, there are three conditions that can trigger the debugger:
- An error: Whenever a C/AL function results in an error, before the error message is shown, the Microsoft Dynamics NAV Debugger is invoked and control is passed to it.
- Starting of any trigger or function: If you switched on the Breakpoint on Triggers option in the Debugger menu, Microsoft Dynamics NAV Debugger will be invoked as soon as any trigger or function executes.
- A breakpoint in code: you can set a breakpoint on a line of code where you would like the C/AL code execution to halt and pass control to the Microsoft Dynamics NAV Debugger.
The first two situations are obvious and require absolutely no user input before the debugger is invoked. Breakpoints are places in code where you want the execution to stop and debugging to start, and these places can be only manually set by you.
To set a breakpoint, open the object you want to debug, place the cursor on the line of code where you want the execution to halt, and press the F9 key or choose Tools | Debugger | Toggle Breakpoint from the main menu. The breakpoint is indicated by a small dark red disk to the left of the code:
|
After you set a breakpoint, it doesn't come into effect automatically. You must first completely close any open windows belonging to the designer of that object (C/AL Editor, Table Designer, Form Designer, Request Options Form Designer, Section Designer, and similar). |
For the sake of an example, design Table 36 Sales Header, locate the field Sell-to Customer No., and invoke the C/AL Editor by pressing F9 or choosing C/AL Code from the View menu. Position the cursor on the first line of code and set the breakpoint. Close the C/AL Editor and Table Designer.
To test the breakpoint, open a Sales Order, select the field Sell-to Customer No., and press F2 to invoke the field validation. This will bring up the Microsoft Dynamics NAV Debugger application:
The default screen layout you get might not look exactly like the one above, and you can rearrange the screen elements to suit your needs.
The elements displayed are the following:
- C/AL Code: shows the C/AL code of the currently executed object. The current execution point is indicated by a yellow arrow pointing to the line of code which will be executed next.
- Variables: show the values and types of variables the in scope of the current C/AL function. There is a tab for viewing variables of different scopes Locals and Globals show local and global variables respectively; Text Constants shows both local and global text constants; and All shows local and global variables but no text constants.
- Watches: show the values and types of user-selected variables. This is useful when there are too many global or local variables, and you only need to watch values of a few variables at a time.
- Output: displays
BreakOnErrorif the debugger was invoked as a result of an error condition. - Call stack: displays the list of all active partly executed functions, which were called as part of current execution thread before the current execution point was reached.
When the debugger is called, you can execute it line by line and monitor the changes of variables, which helps you determine the cause of any code-related problems and detect the sources of bugs. You can advance code in two ways: by stepping over a function, or by stepping into it. Stepping over will execute a function by calling it in the background and returning control to the debugger at the next line of code. Stepping into a function will call the function and set the debugger execution point at the first line of code within that function.
The debugger leaves much to be desired, and is by no means a perfect application. We don't intend to grumble about missing features such as conditional breakpoints and dynamic variable assignments, something that comes for free with Visual Studio debugger, but some features that are inside sometimes behave unpredictably. Here are a few especially annoying behaviors:
- If the debugger is invoked because of an error, any record variables will display the value of
<Uninitialised>. This makes debugging of error conditions difficult, but can be effectively mitigated by placing a breakpoint in front of the line that generated the error. - The execution point indicator may not point to the correct line. It is quite common for it to point to a comment line instead of the code line immediately after it, or to stop at
BEGIN, but skip the very next line. Otherwise, debugging error conditions works much better in Visual Studio debugger. - Watches don't follow the usual C/AL syntax, but must be specified using syntax valid only inside the debugger. This can be addressed by dragging-and-dropping variables from the Variables list into a Watch list. Still, this is better compared to the Visual Studio debugging experience, where there is a lot of .NET overhead around the whole context, including variables.
- Stepping over the next line of code might execute the remainder of the debugged function (or code altogether) without ever stopping again. This can be addressed by setting extra breakpoints or by stepping into such lines of code, which may enter a lengthy function, which we don't want to debug step by step. If this behavior annoys you, use Visual Studio to debug in situations when this happens.
After a few tries, debugging will probably start feeling like a stepparent: you may never grow fond of it, but you had better learn to get along with it. Otherwise, you'll experience even more pain by programming debugging code and making sure you remove it completely before shipping the code out to the customer.
|
Sometimes the debugger will become so stubborn that the only way to debug code is to insert some |
If you are not a programmer, don't bother too much with the debugging, it's the programmer's chore after all to clean up any problematic code. But even if you don't know how to debug, you can make good use of the debugger to help the programmer understand problem conditions quicker.
For example, you can test the application with the debugger switched on. On any unexpected error you can take a screenshot of the debugger and send it to the programmer. This will make fixing errors much easier, because the programmer might not need to repeat a lengthy operation to understand the error.
[edit] Code Coverage
Another feature you can use for troubleshooting code execution is Code Coverage. It's a utility built into the Classic client that monitors the code executed, and gives you an overview of executed and non-executed lines of code afterwards.
Similar to the Debugger, it must first be activated. You can do this by choosing Tools | Debugger | Code Coverage from the main menu. This opens the Code Coverage form. Click Start to begin monitoring the coverage of C/AL code.
After you have started the Code Coverage monitoring, execute whatever operations you want analyzed. For example, create and post a Sales Order, selling a single line of type Item. Then return to the Code Coverage form and click Stop.
The Code Coverage you collected will look similar to the following:
Every object whose C/AL code has been executed in the course of the operation you performed is listed here together with the most basic information:
| Field | Description |
|---|---|
| Object Type, Object ID, and Object Name | Type, ID, and name of the object |
| No. of Lines | Total number of lines of C/AL code inside the object |
| Lines Covered | Total number of executed lines |
| Coverage Ratio | Ratio of the number of executed lines to the number of total lines |
To see exactly which lines of code have been executed, select an object you'd like to inspect, such as Codeunit 80 Sales-Post, and click the Code button. This will invoke the Code Overview form:
Black lines represent the executed lines, while red lines represent those lines that were skipped. This is royally confusing for every first-time user, but after a while you get used to it.
|
Code Overview is not a feature built into the Classic client, but is a normal C/SIDE form: 566 Code Overview. You can customize it and replace the default red color for non-executed lines with a light-gray one; it can better convey the fact that a certain line wasn t executed. To do this, design the form 566, select the Code column, and press F9 to invoke the C/AL Editor for
...with this:
|
Code Coverage is especially good at detecting silent bugs though. When you notice that the results of a transaction are inconsistent with your expectations, and no error occurred, you can start debugging by putting the Code Coverage feature to work. It will tell you which lines of code haven't been executed, which is exactly what you will be looking for with most silent bugs. After detecting the branching conditions that caused important parts of code to be skipped, you can set a few breakpoints and engage in a regular debugging activity.
|
While analyzing Code Coverage, you can also set filters and search for certain operations, such as insertions, deletions, or modifications. If you decided to modify the form 566 Code Overview, you may add other fields from the underlying virtual table 2000000049 Code Coverage to this form: |
[edit] Source
The source of this content is Chapter 9: Debugging Dynamic NAV of Implementing Microsoft Dynamics NAV 2009 by David Roys , Vjekoslav Babić (Packt Publishing, 2008).

