Using NDoc: Adding World-Class Documentation to Your .NET Components
Pages: 1, 2
Using the <include> Tag To Keep Docs Out of Sight, But Not Out of Mind
As I mentioned earlier, one of the traditional problems with source-code-based documentation generators is that in order to write full-fledged documentation for your product, you must swamp your code in comments. (Too many comments? Yes indeed, it is always possible to have too much of a good thing.)
The doc-comment feature of the C# compiler addresses this problem nicely by
allowing you to keep the meat of your documentation in a separate XML
file. You need only insert one line of doc-comment code, the
<include>
element, to link that part of your source code to the appropriate bits in your
XML doc.
Use of the
<include>
element requires you to specify two attributes: the relative path to the
XML file, and an XPath expression to point to the XML node(s) to include.
If you're new to XPath, this is a perfect opportunity to learn this important
bit of XML technology -- see the References section
for links to some XPath tutorials.
/// <include file='myrefdocs.xml'
/// path='//Class[@name="Foo"]/summary'
/// />
/// <include file='myrefdocs.xml'
/// path='//Class[@name="Foo"]/remarks'
/// />
/// <include file='myrefdocs.xml'
/// path='//Class[@name="Foo"]/seealso'
/// />
public class Foo
{ ... }
The XPath expressions in the above example grab the
<summary>,
<remarks>, and
<seealso>
child elements from all
<Class>
elements with the
name="Foo"
attribute. I just made this up -- you're free to invent your own XML
grammar to organize your documentation.
<?xml version="1.0"?>
<Library>
<Namespace name="Arithex.Samples">
<Class name="Foo">
<summary>This is a sample class.</summary>
<remarks>
Here are some interesting remarks about the Foo sample class.
</remarks>
<seealso cref="Bar" />
</Class>
</Namespace>
</Library>
For serious software engineering projects, it's well worth your time to make
use of the
<include>
element in this way. You can split the documentation up among multiple
XML files, in any way you wish -- you'll be able to hand off these XML doc files
to a team of tech writers, or even other engineers, who'll be able to check the
files in and out of source code control independent of the actual C# source
code, thus avoiding many merging-related headaches for you or your team.
For example, in a project I'm currently working on, we've decided to split the
XML documentation into separate peer files for each C# file -- where Foo.cs
would be accompanied by a Foo.xml file, which contains the meat of the
documentation. For smaller projects, keeping all of the docs in single XML
file may serve you better. You can even choose to mix and match (perhaps
keeping the
<summary>
elements inline in your C# code, and everything else out-of-line in a separate
XML file).
NDoc Extensions to C#'s XML Documentation Tags
There are a few important bits missing from Microsoft's specification of C#'s XML Documentation feature. The most notable of these is a way to specify a common summary for the overloads of a function. This is where NDoc really comes into its own: because the format of the docs output by the C# compiler is XML, it's trivial for NDoc to extend the schema to include any missing bits. The C# compiler doesn't complain -- it will pass through any XML tags it doesn't recognize into the resulting documentation, where they can be interpreted by third-party tools (like NDoc).
NDoc extends the set of Microsoft-defined tags by defining a new
<overloads>
tag, a new
<events>
tag for documenting the events raised by a member function, and extending the
grammar of the
<see>
and
<seealso>
tags to allow linking to arbitrary URLs (not just other code items).
You can find some rudimentary documentation for these extended tags in the
tags.html
file, which is included in the NDoc distribution. The
<overloads>
tag requires a bit of explanation -- it comes in two flavors: simple and
complex.
The simple form of
<overloads>
is used very much like a
<summary>
tag, to provide a short description string for the suite of overloaded
methods. (If you neglect to provide an
<overloads>
tag, NDoc will use the
<summary>
tag on the first overload to describe the overloaded method.)
Figure 1: NDoc-generated text for an overloaded method
The more complex form of
<overloads>
allows you to specify other common documentation items, such as a
<remarks>
section. Unfortunately, it's not a general-purpose dumping ground for all
documentation items that are relevant to the individual overloaded methods --
you can't, for example, place documentation for the overloads' common
parameters in the
<overloads>
element and expect them to show up. However, with a little creative
application of the
<include>
tag, you can easily achieve this effect. The sample project accompanying
this article demonstrates the combined use the
<overloads>
and
<include>
tags, for an overloaded method named Solve:
<Method name="Solve">
<docs>
<overloads>Attempts to solve the function.</overloads>
<param name="guessX1">An initial guess.</param>
<param name="guessX2">Another initial guess.</param>
<param name="resultPrecision">
Desired precision for solution.
</param>
<param name="resultStatus">
The outcome of the solution.
</param>
<returns>
The root of the equation (or Double.NaN, upon error).
</returns>
</docs>
</Method>
<Method name="Solve1">
<docs>
<summary>Attempts to solve the function, using the default
max. number of iterations.</summary>
<remarks>Attempts to solve the function, using the default
max. number of iterations.</remarks>
</docs>
</Method>
<Method name="Solve2">
<docs>
<summary>Attempts to solve the function, using the specified
max. number of iterations.</summary>
<remarks>Attempts to solve the function, using the specified
max. number of iterations.</remarks>
<param name="maxIterations">
Maximum number of iterations to search.
</param>
</docs>
</Method>
Linking to External Documentation
One of the nicer features of NDoc is the way it provides seamless links to documentation in the .NET Framework SDK -- it even goes so far as to extract XML documentation for members inherited from their respective assemblies' XML doc-comment files -- but it can only provide links for the types it knows about.
For other types -- types defined in third-party assemblies -- you're on your own. That's not to say the situation is impossible, just that you have to do a little work.
Let's say you have a method with a parameter of type AcmeSoft.Foo, defined in
AcmeSoft.dll. You know that AcmeSoft has wonderful documentation for
their product, available online at acmesoft.com, but there's a problem:
NDoc will generate a hyperlink from your method's page to a non-existent help
topic
"AcmeSoft.Foo.html". If you try to follow this
link in the HtmlHelp browser, you'll be greeted with an error message.
That page doesn't exist in your CHM file, because that type doesn't exist
anywhere in your assembly, so NDoc didn't generate it. To rectify the
situation, all you need to do is supply the missing ingredient:
author an HTML page (manually), name it "AcmeSoft.Foo.html," and pre-place it
into the NDoc output directory before running NDoc (or at least before running
the HtmlHelp compiler).
It's a bit of a hack -- relying on an accident of NDoc's implementation, perhaps -- but it works, until a future version of NDoc offers a better alternative. And by writing your own page, you're allowed the flexibility you need to warn the user that they're about to start reading third-party documentation, and/or that you're about to connect to them to the Internet, etc.
Conclusion
With each new project I work on, I grow continuously more impressed with the flexibility and versatility of NDoc. It's saved me hundreds of hours of tedious labor engineering my own MSDN-style documentation solution, and it looks good doing it!
For a jumpstart into the wonderful world of NDoc, download the sample project accompanying this article, and see if you don't fall in love yourself.
References
- sample.zip
The sample project for this article - NDoc
The proud subject of this article, on SourceForge - "XML
Comments Let You Build Documentation Directly From Your Visual Studio .NET
Source Files"
J. Andrew Schafer, MSDN Magazine -
"XML Documentation Comments"
C# Programmer's Reference, MSDN Library - XPath Tutorial
Courtesy of W3Schools
Shawn Van Ness is an independent consultant specializing in the development of secure, efficient, and robust distributed software systems, based on .NET, COM, and XML technologies.
Return to ONDotnet.com
Showing messages 1 through 22 of 22.
-
comment tags don't appear in nDoc files
2005-07-30 01:16:45 Jon_Paal [Reply | View]
I
--added my comment tags to the vb class file ,
--created my xml file with vb.Doc,
--ran nDoc and created the 'MSDN' documentation
however, the comments I added don't show up in the nDoc files ????
example of comment tags are:
'<SUMMARY>MySummary</SUMMARY>
'<PARAM name="email">string</PARAM>
What am I missing ??
-
Ndoc deletes all files
2004-01-03 06:32:52 anonymous2 [Reply | View]
Hi,
I tried compiling Ndoc with vs.net, and although it gave a massive amount of errors, it did create an executable.
I then tried to use it, but they forgot to mention that it deletes all files within the output file. So bye bye project source code for me!!! What kind of crap application deletes everything in the output directory ??? Such an error is typical for SF-applications, not to mention it totally produced a crap chm, in which each page was an empty html.
But aside from that it looks quite promising :(
/ED -
Ndoc deletes all files
2005-07-30 01:19:05 Jon_Paal [Reply | View]
Ditto i suffered thesame learning experience . there should be a warning that a deletion will occur before just plowing ahead.
And I am still unable to get my comments to appear in nDoc files. it seems to be using relection on the assembly but never uses the XML file (?)
-
External Documentation
2003-11-25 17:06:01 anonymous2 [Reply | View]
I am confused on your workaround for the External documentation for a 3rd party. You suggest placing the html file in the output directory. Is it realistic that you'll have the 3rd party's html files to do this?
What if you have their XML comments file? By placing that in the directory, should it find it there?
Thanks,
Ryan
-
Performance
2003-07-17 12:14:28 anonymous2 [Reply | View]
Hi,
I am attempting to document a rather large project (the xml doc created by the compiler is 3 meg). Ndocs takes about 3 hours to run, and swallows a large amount of memory (somewhere north of 200 meg). It ends up creating over 26,000 files (html and such), and I get an error that 'the compile (of the HTML help file) was aborted' because it did not complete after 10 minutes. Despite this message the resultant .chm file looks complete (obviously I can not be 100% certain that every doc page is present), and it finishes at around 10 meg. After all this descrition, I am simply wondering if there is any way to improve performance (i.e. allocate more space, speed up compilation, etc.). Thanks for the article and the help.
-Sri -
Performance
2003-07-17 12:41:54 arithex [Reply | View]
Wow. 26000? 26000 namespaces, types, and members...!? I haven't checked, but my intuition is that's much larger than the entire .NET Framework.
By my math, if you'd started coding this monstrosity sometime during the early .NET betas, you'd have authored an average of 20 to 30 new types/members, each day (including weekends and holidays). And with full documentation... bully job!
Sarcasm aside -- can I take it this is some kind of autogenerated API? You may wish to skip NDoc, and generate the .html files yourself, at the same time (and in the same manner?) you're generating the actual code.
What happens if you try to compile the intermediate results of NDoc into a CHM file manually, using HHC.exe? Does it still complain about the 10 min. timeout?
(The command line syntax of HHC.exe is trivial -- just point it at the HHP file emitted by NDoc.)
Good luck,
-S
-
multiple dlls
2003-07-16 12:56:20 anonymous2 [Reply | View]
Does the last section on linking to external documentation intimate that it is impossible to place documentation from several .dlls into one .chm file? For example, let's suppose I build acme.dll and foo.dll. Is there a way to combine the resulting .xml files and pass the complete file to NDoc (along with both .dlls)?
Great article.
Regards,
tony -
multiple dlls
2003-07-16 15:01:55 arithex [Reply | View]
It's certainly possible... Just fire up NDocGui.exe, and add all your assemblies (and their associated .xml doc files) to the listbox at the top of the form. Perhaps I misunderstood your question?
Considering the section on external documentation, the key word is "external" -- meaning an assembly which you don't own the source code to.
It's not readily possible to inject your own assemblies' documentation into a .chm file produced by a 3rd party, if that's what you're asking...
-S
-
directory structure
2003-07-15 18:48:16 anonymous2 [Reply | View]
Hi,
I was just wondering how the doc directory only contains the resultant .chm file. When I try running the .xml and .dll file through the NDocGui, I end up with a flat hierarchy containing all the html files that make up the ndocs, along with all the .gif files and a few other files. Does the clean target in the makefile remove the excess? If so, how? Thanks for the help and the article.
-
directory structure
2003-07-16 03:06:56 arithex [Reply | View]
In order to reduce the size of the download, I removed everything but the .chm -- sorry for any confusion.
You're right, in that all the other output files are just temporary/garbage, generated by NDoc. CHM files are completely self-sufficient... in fact, using the HTML Help Workshop you can reverse-engineer that CHM file, to recreate all the original *.html, *.gif, etc.
-
How can i make the help files integrative with the IDE ?
2003-06-16 11:44:03 anonymous2 [Reply | View]
Hey,
I really felt in love with this program.
But I’d like to know how can I merge the help files (htmls or chm files) with the oriented IDE of Visual Studio .Net ?
I want to deploy my class library with the proper index in the IDE like other integrated libraries.
How can I do this?
thanks,
Moshe
-
How can i make the help files integrative with the IDE ?
2003-06-16 14:38:55 arithex [Reply | View]
I went down the H2 road too... even with some help from tools like H2Reg at www.helpware.net, I wasn't impressed with the state of things.
Sure, it worked -- but doing the merge was a pain (both as a developer and as an end user... it took about 60 sec on my 2.4 GHz P4). And doing it properly, in the face of uninstalls/repairs/reinstalls, is a tall order.
Several of our test machines had their whole MSDN indexes blown away, in some non-reproducible test scenarios.
So I'm hot convinced H2 is ready for prime time.
Now, having said that, check out this VS PowerToy...
http://www.gotdotnet.com/team/ide/helpfiles/CustomHelpBuilder.aspx
-S
-
XML comments + NDoc for VB.NET !
2002-12-25 10:35:00 anonymous2 [Reply | View]
Hi !
Just wan't to say that NDoc can also be used with VB.NET using this opensource tool (it generates the xml file that ndoc uses):
http://vb-doc.sourceforge.net
-
Automating NDoc, as part of the build process
2002-12-10 17:27:31 arithex [Reply | View]
I neglected to point this out, in the article, but the accompanying sample solution includes a "post-build" makefile project, which kicks off NDoc after every Release-mode build.
Check out the files in the "xdeploy" subfolder, to see how the magic is done. This technique is extremely useful for many, many tasks -- not just NDoc!
(Mind you, I love NAnt, but I'm not always able to impose its use across your every development team I come across. NMake is everywhere, and rigging it up to run before/after your primary project is a valuable technique, until some future version of VS.NET provides explicit support for this.)
Cheers,
-S
-
Automating NDoc, as part of the build process
2002-12-13 10:32:49 Shawn Wildermuth |
[Reply | View]
FYI - VS.NET 2003 supports pre and post build operations. Running NDoc then will work, though building a CHM on every build could become a bit laborious.






BTW, the documenter does ignore this class when building the list of classes in the namespace (so at least that's working :/ )