Category Archives: Help

Creating user documentation and help for Dynamics NAV

Here are the slides from my NAVUG talk on doing documentation for Microsoft Dynamics NAV solutions.

COM08 An elegant solution for creating Dynamics NAV user documentation

The open sourced code can be found at:

A precompiled package of the tools can be downloaded from here:


I suggestion reading through the old posts on this to understand whats going on at

User documentation of a NAV solution

In this series of articles I will explain a alternative method of handling user documentation for Microsoft Dynamics NAV 2015 code.

In E Foqus we use this for our ISV product Foqus Finance, but it can be used for any NAV solution, ranging from a small customer modification to huge ISV solutions (as Foqus Finance)

We have tried to solved a series of challenges with documentation:

First challenge: Documentation is dead the minute you’re finish writing it. Code changes, customers want it work differently, change requests keeps popping up. And the documentation (if any) stays at the initial level

Second challenge: Documentation is kept in documents (Word/PDF) sitting on local drives, attached to email, stored on file shares, often in multiple versions without any clear version strategy.

Third challenge: Customer want F1 help, and this has historical been an nightmare to create with NAV – from compiling CHM files with 3rd party tools to distribute files to clients.

Fourth challenge: New formats comes along all the time, creating an ebook with the help would be a very modern thing to do.

Read on for our solution to all this:

Step 1 – Organizing the input text
Step 2 – Getting structure into our documentation
Step 3 – Graphical Layout
Step 4 – Updating the Help Server Table Of Content (ToC.XML)
Step 5 – Editing and storing help text with NAV Code
Step 6 – Running the whole thing

Download the current version of the help toolkit:

EFoqusHelpToolkit 0.03

Further development:

Step 7 – Producing automated screenshots from NAV

Update the NAV2015 ToC.XML

The ToC.XML is a simple recursive structure with entries like this:

<?xml version="1.0" encoding="utf-8"?>
<Node Name="DynamicsHelp" DisplayName="Help" Page="conGettingStarted.htm">
    <Node Name="TechRef" DisplayName="Technical Reference" Page="conTechnicalReference.htm">
      <Node Name="CSIDERef" DisplayName="C/SIDE Reference Guide" Page="conCSIDEReferenceGuide.htm" />
      <Node Name="DevEnvCmds" DisplayName="Development Environment Commands" Page="conDevelopmentEnvironmentCommands.htm" />
      <Node Name="CSIDEwindows" DisplayName="Windows Overview" Page="conWindowOverviews.htm" />
    <Node Name="Upgrade" DisplayName="Upgrading to Microsoft Dynamics NAV 2015" Page="oriUpgradingToNAVCrete.htm">
      <Node Name="MigratingToMultitenancy" DisplayName="Migrating to Multitenancy" Page="conMigratingTenantDatabases.htm" />

Just a name, a title and a page, and that looks very similar to the structure we already have in place from the manual. So we do here, is run through our own Structure.XML, and inserts matching entries into the ToC.

This is the main piece of code that will generate the html files, and update the ToC at the same time:

public bool GenerateAllContentAsHtml()
            XDocument TOC = XDocument.Load(ConfigurationManager.AppSettings["input-toc"]);

            XElement root = (from xml2 in TOC.Descendants("Node")
                             where xml2.Attribute("Name").Value == ConfigurationManager.AppSettings["projectname"]
                             select xml2).FirstOrDefault();
            if (root == null)
                root = GetNode(ConfigurationManager.AppSettings["projectname"], Data.manual.Title, ConfigurationManager.AppSettings["projectname"] + ".htm");
            root.Nodes().Remove(); // If we already have our stuff in this TOC remove it first

            StringBuilder ChapterList = new StringBuilder();
            foreach (var chapter in Data.manual.Chapters)
                string str = "<a href=\"" + ConfigurationManager.AppSettings["projectname"] + "_" + chapter.No + ".htm\" xmlns=\"\">";
                str += chapter.Title + "</a><br>";

            Article preface = Data.Articles.Find(m => m.ID == Data.manual.Preface.ID);
            if (preface == null)
                preface = new Article()
                    ID = Data.manual.Preface.ID,
                    Text = "TODO: Article " + Data.manual.Preface.ID,
                    Title = "TODO: Article Caption " + Data.manual.Preface.ID
            StringBuilder topic = new StringBuilder(File.ReadAllText(ConfigurationManager.AppSettings["helppage-html"]));
            topic.Replace("$1$", preface.Title);
            topic.Replace("$1$", preface.Title);
            topic.Replace("$2$", ConvertMarkdown(preface.Text, "html") + ChapterList);
                ConfigurationManager.AppSettings["output-path-helpserver"] + @"\" +
                ConfigurationManager.AppSettings["projectname"] + ".htm", topic.ToString());

            return false;