Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web Api Help Page XML comments from more than 1 files

I have different plugins in my Web api project with their own XML docs, and have one centralized Help page, but the problem is that Web Api's default Help Page only supports single documentation file

new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/Documentation.xml"))

How is it possible to load config from different files? I wan to do sth like this:

new XmlDocumentationProvider("PluginsFolder/*.xml")
like image 845
Levan Avatar asked Mar 04 '14 07:03

Levan


People also ask

What is one step you must take to enable XML comments to appear in the default Web API?

You can enable generating this by going to your project Properties -> Build -> Output. Here select the checkbox for XML Documentation file.

What is the proper commenting method for XML?

To insert XML comments for a code element Type /// in C#, or ''' in Visual Basic.

What is one step you must take to enable XML comments?

Now enable XML documentation. In Solution Explorer, right-click the project and select Properties. Select the Build page. Under Output, check XML documentation file.


3 Answers

You can modify the installed XmlDocumentationProvider at Areas\HelpPage to do something like following:

Merge multiple Xml document files into a single one:

Example code(is missing some error checks and validation):

using System.Xml.Linq;
using System.Xml.XPath;

 XDocument finalDoc = null;
 foreach (string file in Directory.GetFiles(@"PluginsFolder", "*.xml"))
 {
    if(finalDoc == null)
    {
        finalDoc = XDocument.Load(File.OpenRead(file));
    }
    else
    {
        XDocument xdocAdditional = XDocument.Load(File.OpenRead(file));

        finalDoc.Root.XPathSelectElement("/doc/members")
                     .Add(xdocAdditional.Root.XPathSelectElement("/doc/members").Elements());
    }
}

// Supply the navigator that rest of the XmlDocumentationProvider code looks for
_documentNavigator = finalDoc.CreateNavigator();
like image 118
Kiran Avatar answered Oct 19 '22 20:10

Kiran


Kirans solution works very well. I ended up using his approach but by creating a copy of XmlDocumentationProvider, called MultiXmlDocumentationProvider, with an altered constructor:

public MultiXmlDocumentationProvider(string xmlDocFilesPath)
{
       XDocument finalDoc = null;
        foreach (string file in Directory.GetFiles(xmlDocFilesPath, "*.xml"))
        {
            using (var fileStream = File.OpenRead(file))
            {
                if (finalDoc == null)
                {
                    finalDoc = XDocument.Load(fileStream);
                }
                else
                {
                    XDocument xdocAdditional = XDocument.Load(fileStream);

                    finalDoc.Root.XPathSelectElement("/doc/members")
                        .Add(xdocAdditional.Root.XPathSelectElement("/doc/members").Elements());
                }
            }
        }

        // Supply the navigator that rest of the XmlDocumentationProvider code looks for
        _documentNavigator = finalDoc.CreateNavigator();
}

I register the new provider from HelpPageConfig.cs:

config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/")));

Creating a new class and leaving the original one unchanged may be more convenient when upgrading etc...

like image 21
gurra777 Avatar answered Oct 19 '22 19:10

gurra777


Rather than create a separate class along the lines of XmlMultiDocumentationProvider, I just added a constructor to the existing XmlDocumentationProvider. Instead of taking a folder name, this takes a list of strings so you can still specify exactly which files you want to include (if there are other xml files in the directory that the Documentation XML are in, it might get hairy). Here's my new constructor:

public XmlDocumentationProvider(IEnumerable<string> documentPaths)
{
    if (documentPaths.IsNullOrEmpty())
    {
        throw new ArgumentNullException(nameof(documentPaths));
    }
    XDocument fullDocument = null;
    foreach (var documentPath in documentPaths)
    {
        if (documentPath == null)
        {
            throw new ArgumentNullException(nameof(documentPath));
        }

        if (fullDocument == null)
        {
            using (var stream = File.OpenRead(documentPath))
            {
                fullDocument = XDocument.Load(stream);
            }
        }
        else
        {
            using (var stream = File.OpenRead(documentPath))
            {
                var additionalDocument = XDocument.Load(stream);
                fullDocument?.Root?.XPathSelectElement("/doc/members").Add(additionalDocument?.Root?.XPathSelectElement("/doc/members").Elements());
            }
        }
    }

    _documentNavigator = fullDocument?.CreateNavigator();
}

The HelpPageConfig.cs looks like this. (Yes, it can be fewer lines, but I don't have a line limit so I like splitting it up.)

var xmlPaths = new[]
{
    HttpContext.Current.Server.MapPath("~/bin/Path.To.FirstNamespace.XML"),
    HttpContext.Current.Server.MapPath("~/bin/Path.To.OtherNamespace.XML")
};
var documentationProvider = new XmlDocumentationProvider(xmlPaths);
config.SetDocumentationProvider(documentationProvider);
like image 6
jack Avatar answered Oct 19 '22 20:10

jack