DocProject Tips and Tricks

DocProject with Sandcastle are a great choice for creating MSDN-style documentation. You can author conceptual documentation using MAML (Microsoft Assistance Markup Language) and reference documentation from managed assemblies and XML comments. Here is the documentation for DocProject. Writing conceptual documentation I ran into some problems that were not straight forward to solve. Hopefully these tips will help you if you have the same problems.

Overloaded Methods
The codeEntityReference tag allows you to link to API reference documentation (namespaces, types, methods, properties, fields). You have to prefix the fully qualified name of the entity with N: for namespaces, T: for types, P: for properties, F: for fields and M: for methods. What if you have overloaded methods and you want to link to the page that displays all of them, not one particular method? The O: prefix Visual Studio is expecting (for XML comments) does not work. Sandcastle Help File Builder (SHFB) expects Overload: instead.

  <codeEntityReference>Overload:YourNamespace.YourClass.YouOverloadedMethod</codeEntityReference>

Methods with arguments
If you want to link to API reference documentation for a method that take some parameters you must specify those parameter’s type in parenthesis.

  <codeEntityReference>M:YourNamespace.YourClass.Function(System.String)</codeEntityReference>

However, if the method takes more than one parameter, you must separate the argument types with a comma and use no whitespaces between them. If you have whitespaces the API reference will not be resolved.

  <codeEntityReference>M:YourNamespace.YourClass.Function(System.String,System.Int32[])</codeEntityReference>

Constructors
Constructors are special methods so you must use a special notation for them: instead of using their name use the #ctor tag.

  <codeEntityReference>M:YourNamespace.YourClass.#ctor</codeEntityReference>

Of course, if the constructor has some arguments you must specify them in parenthesis:

  <codeEntityReference>M:YourNamespace.YourClass.#ctor(System.String)</codeEntityReference>

Generics
When it comes to generics you must use the special notation with ` (grave accent). The grave accent (`) indicates the level and the number after it is the number of the generic types. Here are the rules (as indicated in the ECMA specification ):

  • Arguments that define generic type parameters have an appended grave accent character followed by the number of type parameters (ex. T`1)
  • For nested types, the number is based upon the of new type parameters on the nested type(ex. T`1.Nested`2)
  • Arguments that refer to generic type parameters on types are encoded using a single grave accent character (`) followed by the zero-based index of the type parameter.
  • Arguments that use generic parameters on methods use double grave accent characters (``) followed by the zero-based index of the type-parameter instead of the single grave accent used for parameters on types.

For instance, let’s say your class looks like this:

namespace foo
{
   class bar<T>
   {
   }
}

If you want to link to the generic bar type you must do it like this:

  <codeEntityReference>T:foo.bar`1</codeEntityReference>

What if you had a generic method too?

namespace foo
{
   class bar<T>
   {
      public TR func1<TR>(string s)
      {
         return (default)TR; // just something dummy
      }

      public TR func2<TR>(string s, TR arg)
      {
         return (default)TR; // just something dummy
      }

      public void func3<T1, T2>(T a, T1 b, T2 c)
      {
      }
   }
}

Then you must refer to the function as follows:

  // function is generic, but no generic argument is used
  <codeEntityReference>M:foo.bar`1.func1``1(System.String)</codeEntityReference>

  // function is generic and has a generic argument on the method => use `` + 0-based index of type
  <codeEntityReference>M:foo.bar`1.func2``1(System.String,``0)</codeEntityReference>

  // function is generic and has generic arguments on type and on the method
  // first argument type comes from the type => `0
  // second and third argument types come from the method, in the order they were declared => ``0 and ``1
  <codeEntityReference>M:foo.bar`1.func3``1(`0,``0,``1)</codeEntityReference>

API Reference Documentation
When you author documentation you probably want to put together conceptual documentation and API reference documentation. The later you build from external sources, i.e. assemblies and XML files with the XML-comments you wrote in the source code. Question is where and how do you insert this API reference? The answer was not very easy to find; luckily a colleague of mine was able to help me with the answer.

First of all, there is only one place in the hierarchy of your topics hierarchy where you can insert it. So no matter from how many sources you build this, it all goes into one place. To set the place you must edit the topics.xml file (under Help\Settings). This file looks like this (of course, this is a dummy sample):

<?xml version="1.0" encoding="utf-8"?>
<topics>
  <topic id="cec0ab12-05b5-4a00-ab8a-391d67625997" file="topic1.aml">
    <topic id="854aeed0-510e-4ca1-b2bb-12104ba9eada" file="topic1\topic11.aml">
  </topic>
</topics>

There is a special tag you can insert as a child of a topic. It’s called stoc and looks like this:

<?xml version="1.0" encoding="utf-8"?>
<topics>
  <topic id="cec0ab12-05b5-4a00-ab8a-391d67625997" file="topic1.aml">
    <stoc project="Project" />
  </topic>
</topics>

This will tell the builder to insert under topic1 all the API reference documentation.

2 Replies to “DocProject Tips and Tricks”

  1. Thanks for the article and the post at Code Project. Quick question: what’s the benefit of using DocProject with Sandcastle vs. just using Sandcastle? I have used HTML Help, nDoc, and Sandcastle, but I haven’t spent much time with DocProject. I glanced over the intro documentation page, but still a bit hazy. What does DocProject do that Sandcastle can’t?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.