Everyone likes to save they document their code.  But in the Agency world they first thing to go is documentation; often quickly followed by unit testing.  But we can use DocFX to make the process easy, painless and automate as part of your build and pipeline.

When I first started looking into generating documentation I stumbled over little roadblocks that were my own doing.  But I’ve found a few things that make my life (and hopefully those of my developers) easier.

First, no matter how hard you try someone has to try something.  It is just the way it is, but really, if you are creating your /// comments in your code you are already there for a functional set of documentation.  That said, the more effort you put into you comments and documentation the more useful it will become.  If you do not know about /// comments I will make a post on them soon™ or you can see the documentation from Microsoft.

My requirements

I’m not asking for much…

The documentation must end up in source control
This one seems self evident; but as your code base evolves and changes, your documentation should as well.  Since the changes go hand in hand - keeping it all under source control means you docs will match the code when you switch branches. 

It should be easy to deploy the documentation as part of a pipeline
If it isn’t easy to use, there is no point.  The CI/CD pipeline should be able to update the documentation automatically.  It doesn’t matter if that means it is published to an internal webserver, generated into a PDF, pushed to a github pages site or an azure/aws service.  Ideally all of these options should be easy.  As I am working, I do want to be able to access the documentation easily as well.

When the solution is built the documentation should “update”
There are going to be two “types” of documentation here. 

  1. The things we create and edit by hand; how much you do here will cause your mileage to vary but this is where you can make use of diagrams, requirements documents, use cases etc etc. These items take more time to create but are often part of the “ask” for a feature.  It wouldn’t hurt to make a new file for a feature and keep everything together (including a link to the epic and stories in your workflow management tool of choice like Jira).
  2. Automatically generated documentation from the code comments.  Documentation comments are often processed by a ‘documentation generator’ to create a structured XML file (the documentation file) that is used by a ‘documentation viewer’ for people to interact with it.  We’re going to skip most of that because it is to much of a pain. 

When we build the documentation we should have usable documentation without worrying about xml or any configuration.

To be able to include UML and other diagrams
Class diagrams, flow charts, gnat diagrams, even pie charts have a place in my docs.  They help convey process and can provide insight in how things should and are intended to work.

Diagrams should be easy to update without an extra process
No-one wants to have to export a diagram into a png file and include it into a document.  Those extra steps just create more work when the diagram needs to be updated.  In 10 years the original file may have gone the way of the Dodo, and recreating the file could be ‘problematic’.  The point is to keep things easy for us now and later down the road.  Which brings us to our next requirement-

Diagrams should be defined as plain text
if the diagrams are defined as plain text, we don’t need to worry about software versions, importing/exporting or trying to remember if it was created in gliffy, lucidchart, Visio or some other tool that no longer exists.  In two years, Joe might leave to become a volunteer for Doctors without borders and there is no way to get the Visio file that generated the png file from him… Because that never happens.  If the diagrams are define in plain text, what if we keep all the styling and formatting in plain text?  Which brings us to our last requirement….

Documents should be written using Markdown
Markdown keeps the structure of your text as plain text.  I make heavy use of the Markdown Guide while I am writing md files and it is a fairly common format for text.  Notepad++, Visual Studio and VSCode all have extensions/plugins that can support Markdown.  There are a great many flavors of Markdown out there; it seems like everyone creates their own version of Markdown like a JavaScript framework.  Think about all of the Readme.md files you’ve ignored completely read on github, yeah those are Markdown. 

Enter DocFX

There are lots of tools out there that can meet these requirements with various plugins and extensions; but DocFX is backed by Microsoft, works, is free, and is easy enough.  It is important to note that DocFX can be used in many different contexts and ways outside of the way I am going to walk though it.  You should check out their site to dive into further when we are done here.

For the record I don’t like having to drop to the command line to run DocFX --serve to run the documentation site or compile the documentation.  You dont need to put the DocFX project into your solution but I am going to do so to make it easier to update and work on as I develop.  First Most tutorials say to add a class library to your solution.  well, no.  Don’t get me wrong, they are not wrong, but I want to be able to hit play and be able to browse my documentation without having to drop to a command line and my port 8080 might be busy.  A few minutes of extra setup to make it easier for the other developers and not needing to drop to the command line is worth it in the long run.  The beauty is the command line will still work when you have the need.

Mermaid

“Mermaid is a JavaScript based diagramming and charting tool that uses Markdown-inspired text definitions and a renderer to create and modify complex diagrams.”  You can use something like PlantUML but that comes with some unique considerations.  I am using Mermaid because it works locally and does not require a separate server (or Java locally) to generate the diagrams.

Our project

I have a number of libraries that I use that are in need of an update (meaning convert to core).  So I am going to setup a new solution for my new Digital Asset Management system; Dams are a thing… I’m using Visual Studio 2022 Community Edition.

  1. Create a new class library project (in my case I am also creating a new solution)
    • Project name: CatLaboratories.DigitalAssetManagementSystem
    • Location: D:\projects
    • Solution Name: CatLaboratories
    • Framework: .NET 6 (Long-term support)
  2. Rename Class1 to Dam
  3. Paste the following code into the class

  4.          /// <summary>
             /// Gets a file from the Dam
             /// </summary>
             /// <param name="id"></param>
             /// <returns>A stream of the files content</returns>
             public Stream GetFileContents(Guid id)
             {
                 return null;
             }

  5. Now that we have a “working” Dam let’s setup our documentation
  6. Add a new ASP.Net Core Web App project to the solution
    • Project name: Documentation
    • Location: D:\projects\CatLaboratories
    • Framework: (Long-term support)
    • Authentication Type: None
    • I am leaving docker off
  7. Delete the /Pages folder
  8. Delete everything in the /wwwroot/ directory
  9. Edit program.cs
    • comment out builder.Services.AddRazorPages();
    • comment out the configure the HTTP request Pipeline

    • if (!app.Environment.IsDevelopment())
      {
           app.UseExceptionHandler("/Error");
           app.UseHsts();
      }

    • Add the following just before the app.UseHttpsRedirection()
                  DefaultFilesOptions options = new DefaultFilesOptions();
                   options.DefaultFileNames.Clear();
                   options.DefaultFileNames.Add("index.html");
                   app.UseDefaultFiles(options);
    • comment out app.UseRouting();
    • comment out app.UseAuthorization();
    • comment out app.MapRazorPages();
  10. Right click the Documentation project and select Manage NuGet Packages
  11. Install the DocFX.Console nuget
  12. Build the documentation project – this will add several directories and files.
  13. Edit the index.md in the root of the documentation project and add the following text to the end of the file

    ```mermaid
         graph TD
         A[Christmas] -->|Get money| B(Go shopping)
         B --> C{Let me think}
         C -->|One| D[Laptop]
         C -->|Two| E[iPhone]
         C -->|Three| F[fa:fa-car Car]
    ```

  14. Add support for Mermaid
    1. Under the documentation project create a folder “templates”
    2. Under Templates create a folder called “mermaid”
    3. Under Mermaid create a folder called “partials”
    4. In partials create a file named “scripts.tmpl.partial”
    5. Paste the following html into the “scripts.tmpl.partial” file

      <div><script type="text/javascript" src="{{_rel}}styles/docfx.vendor.js"></script>
      <script type="text/javascript" src="{{_rel}}styles/docfx.js"></script>
      <script type="text/javascript" src="{{_rel}}styles/main.js"></script>
      <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"
      crossorigin="anonymous"></script>
      <script>mermaid.initialize({ startOnLoad: false });
      mermaid.init(undefined, ".lang-mermaid");</script></div>

    6. Make sure the build action for “scripts.tmpl.partial” is set to None
      If you want to add any other JavaScript Libraries add their script tag to “scripts.tmpl.partial” between the div tags.  Highlight.js maybe?
    7. Edit the docfx.json
      • change line 7   "**.csproj" to  “**/**.csproj"
      • change line 9 from "src": "D:\\projects\\CatLaboratories\\Documentation" to "src": "..","exclude": ["**/Documentation.csproj","**/*tests.csproj",".git"]
      • Press ctrl+k+d to reformat the file
      • Find the template section (right around line 57) after “default” add ,”templates/mermaid”
      • Around line 53, change "dest": "_site", to "dest": "wwwroot",
      • Around line 49 change "_site/**" to "wwwroot/**"
    8. Click show all files
    9. Delete the folder _site
    10. Delete the folder src
    11. Right click each of the following folder and click “Include in project”
      • images
      • apidoc
    12. Build the project
    13. Run it, if you used the ssl option, click yes to trust the ASP.net Core SSL Certificate and yes again
    14. Explore your documentation! You should see the diagram on the first page and when you click the API Documentation in the top navigation you will see the auto generated documentation.  well… mostly…

So here is the rub, with Visual Studio 2022 version 17.3.#(3 maybe?) Microsoft made a breaking change that broke things (hence a breaking change).  But it doesn’t appear that the break was intentional so we may see a patch to fix it.  you will see an error in the build output that says something like System.ReadOnlySpan`1<Char> Microsoft.IO.Path.GetFileName(System.ReadOnlySpan`1<Char>)

Here is a fix for that issue