Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
270 views
in Technique[技术] by (71.8m points)

c# - ASP Web API Help pages - Link to class from XML <see> tag

I'm working on Developing a Web-API project, and i'm very impressed with the auto generated documentation by Microsoft's HelpPages.

i enabled custom documentation using the official site creating Help Pages

the documentation is generated successfully BUT none of the references to Classes from the <See cref=""> Tag seems to be added to the description, the HelpPages Simply ignores them (that's for a reason).

i really wanted to have this feature in my project, i searched a lot (got close sometimes) but none gave a convincing answer.

That's why i decided to post my solution to this tweak and hopefully benefit other programmers and spare them some time and effort. (my answer is in the replies below)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

my solution is the following:

  1. you've got your custom documentation (from the generated xml file) working
  2. enable HTML and XML tags within the documentation, they normally get filtered out, thanks this Post you can preserve them.
    simply go to: ProjectName > Areas > HelpPage > XmlDocumentationProvider.cs
    on line 123 in method: GetTagValue(XPathNavigator parentNode, string tagName)
    change the code return node.Value.Trim(); to return node.InnerXml;
  3. create the following partial view:
    ProjectNameAreasHelpPageViewsHelp**_XML_SeeTagsRenderer.cshtml**
    this is my code:
@using System.Web.Http;
@using MyProject.Areas.HelpPage.Controllers;
@using MyProject.Areas.HelpPage;
@using MyProject.Areas.HelpPage.ModelDescriptions
@using System.Text.RegularExpressions
@model string
@{
    int @index = 0;
    string @xml = Model;
    if (@xml == null)
        @xml = "";
    Regex @seeRegex = new Regex("<( *)see( +)cref="([^"]):([^"]+)"( *)/>");//Regex("<see cref="T:([^"]+)" />");
    Match @xmlSee = @seeRegex.Match(@xml);
    string @typeAsText = "";
    Type @tp;

    ModelDescriptionGenerator modelDescriptionGenerator = (new HelpController()).Configuration.GetModelDescriptionGenerator();

}

@if (xml !="" && xmlSee != null && xmlSee.Length > 0)
{

    while (xmlSee != null && xmlSee.Length > 0)
    {

            @MvcHtmlString.Create(@xml.Substring(@index, @xmlSee.Index - @index))

        int startingIndex = xmlSee.Value.IndexOf(':')+1;
        int endIndex = xmlSee.Value.IndexOf('"', startingIndex);
        typeAsText = xmlSee.Value.Substring(startingIndex, endIndex - startingIndex);  //.Replace("<see cref="T:", "").Replace("" />", "");
        System.Reflection.Assembly ThisAssembly = typeof(ThisProject.Controllers.HomeController).Assembly;
        tp = ThisAssembly.GetType(@typeAsText);

        if (tp == null)//try another referenced project
        {
            System.Reflection.Assembly externalAssembly = typeof(MyExternalReferncedProject.AnyClassInIt).Assembly;
            tp = externalAssembly.GetType(@typeAsText);
        }  

        if (tp == null)//also another referenced project- as needed
        {
            System.Reflection.Assembly anotherExtAssembly = typeof(MyExternalReferncedProject2.AnyClassInIt).Assembly;
            tp = anotherExtAssembly .GetType(@typeAsText);
        }


        if(tp == null)//case of nested class
        {
            System.Reflection.Assembly thisAssembly = typeof(ThisProject.Controllers.HomeController).Assembly;
            //the below code is done to support detecting nested classes.
            var processedTypeString = typeAsText;
            var lastIndexofPoint = typeAsText.LastIndexOf('.');
            while (lastIndexofPoint > 0 && tp == null)
            {
                processedTypeString = processedTypeString.Insert(lastIndexofPoint, "+").Remove(lastIndexofPoint + 1, 1);
                tp = SPLocatorBLLAssembly.GetType(processedTypeString);//nested class are recognized as: namespace.outerClass+nestedClass
                lastIndexofPoint = processedTypeString.LastIndexOf('.');
            }
        }

        if (@tp != null)
        {
            ModelDescription md = modelDescriptionGenerator.GetOrCreateModelDescription(tp);
                @Html.DisplayFor(m => md.ModelType, "ModelDescriptionLink", new { modelDescription = md })            
        }
        else
        {            
                @MvcHtmlString.Create(@typeAsText)            
        }
        index = xmlSee.Index + xmlSee.Length;
        xmlSee = xmlSee.NextMatch();
    }    
            @MvcHtmlString.Create(@xml.Substring(@index, @xml.Length - @index))    
}
else
{    
        @MvcHtmlString.Create(@xml);    
}
  1. Finally Go to: ProjectNameAreasHelpPageViewsHelpDisplayTemplates**Parameters.cshtml**
    at line '20' we have the code corresponding to the Description in the documentation.
    REPLACE this:

                <td class="parameter-documentation">
                    <p>
                        @parameter.Documentation
                    </p>
                </td>
    

With THIS:

                <td class="parameter-documentation">
                    <p>
                        @Html.Partial("_XML_SeeTagsRenderer", (@parameter.Documentation == null? "" : @parameter.Documentation.ToString()))
                    </p>
                </td>

& Voila you must have it working now.
Notes:

  • i tried putting HTML list inside the docs and it rendered it fine
  • i tried multiple class references (multiple <see cref="MyClass"> and i worked fine
  • you can't refer to a class that is declared within a class
  • when you refer to a class that is outside the current project please add the assembly .getType of a class within that project (check my code above)
  • any un-found class found inside a <see cref> will have it's full name printed in the description (for example if you reference a property or namespace, the code won't identify it as a type/class but it will be printed)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...