Як Xml Документація для Web Api може включати документацію поза основним проектом?


102

Документація для забезпечення інтеграції XmlDoc в ваші Api проектів Web з'являється тільки рукоятки ситуацій , коли всі ваші типів API є частиною вашого WebAPI проекту. Зокрема, в ньому йдеться про те, як перепрограмувати XML-документацію App_Data/XmlDocument.xmlта коментувати рядок у вашому конфігурації, який буде використовувати цей файл. Це неявно дозволяє лише один файл документації проекту.

Однак у моїй установці у мене є типи запитів та відповідей, визначені у загальному проекті "Моделі". Це означає, що якщо у мене визначена кінцева точка, наприклад:

[Route("auth/openid/login")]
public async Task<AuthenticationResponse> Login(OpenIdLoginRequest request) { ... }

Де OpenIdLoginRequestвизначено в окремому проекті C # так:

public class OpenIdLoginRequest
{
    /// <summary>
    /// Represents the OpenId provider that authenticated the user. (i.e. Facebook, Google, etc.)
    /// </summary>
    [Required]
    public string Provider { get; set; }

    ...
}

Незважаючи на документи XML, властивості requestпараметра не містять документації при перегляді довідкової сторінки, що стосується кінцевої точки (тобто http://localhost/Help/Api/POST-auth-openid-login).

Як я можу зробити так, щоб типи підпроектів з документацією XML з'являлися в документації XML Web API?

Відповіді:


165

Немає вбудованого способу цього досягти. Однак для цього потрібно лише кілька кроків:

  1. Увімкніть XML-документацію для вашого підпроекту (із властивостей проекту / збірки), як у вашому проекті Web API. За винятком цього часу, направляйте його безпосередньо на XmlDocument.xmlтак, щоб він генерувався у кореневій папці вашого проекту.

  2. Змініть події після збирання проекту Web API, щоб скопіювати цей XML-файл у свою App_Dataпапку:

    copy "$(SolutionDir)SubProject\XmlDocument.xml" "$(ProjectDir)\App_Data\Subproject.xml"

    Куди Subproject.xmlслід перейменувати те, що має назву вашого проекту .xml.

  3. Далі відкрийте Areas\HelpPage\App_Start\HelpPageConfigта знайдіть наступний рядок:

    config.SetDocumentationProvider(new XmlDocumentationProvider(
        HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
    

    Це рядок, який ви спочатку прокоментували, щоб в першу чергу включити довідкову документацію XML. Замініть цей рядок на:

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

    Цей крок забезпечує XmlDocumentationProviderпередачу каталогу, який містить ваші XML-файли, а не конкретний XML-файл для вашого проекту.

  4. Нарешті, модифікуйте Areas\HelpPage\XmlDocumentationProviderнаступними способами:

    а. Замініть _documentNavigatorполе на:

    private List<XPathNavigator> _documentNavigators = new List<XPathNavigator>();

    б. Замініть конструктор на:

    public XmlDocumentationProvider(string appDataPath)
    {
        if (appDataPath == null)
        {
            throw new ArgumentNullException("appDataPath");
        }
    
        var files = new[] { "XmlDocument.xml", "Subproject.xml" };
        foreach (var file in files)
        {
            XPathDocument xpath = new XPathDocument(Path.Combine(appDataPath, file));
            _documentNavigators.Add(xpath.CreateNavigator());
        }
    }
    

    c. Додайте наступний метод під конструктором:

    private XPathNavigator SelectSingleNode(string selectExpression)
    {
        foreach (var navigator in _documentNavigators)
        {
            var propertyNode = navigator.SelectSingleNode(selectExpression);
            if (propertyNode != null)
                return propertyNode;
        }
        return null;
    }
    

    г. І останнє, виправте всі помилки компілятора (їх повинно бути три), що призводить до посилань на _documentNavigator.SelectSingleNodeта видаліть _documentNavigator.частину, щоб вона тепер викликала новий SelectSingleNodeметод, який ми визначили вище.

Цей останній крок - це те, що змінює постачальника документів на підтримку пошуку в декількох XML-документах для довідкового тексту, а не лише для основного проекту.

Тепер, коли ви вивчаєте свою Довідкову документацію, вона буде включати XML-документацію з типів вашого відповідного проекту.


7
Відмінна відповідь. Насправді я думаю, що конструктору трохи простіше прийняти масив рядків: public XmlDocumentationProvider (string appDataPath) і перерахувати цей список у постачальника документації.
Капітан Джон

14
Фантастичний, це було саме те, що я шукав !! Запропонуйте замінити var files...рядок на те, var files = Directory.GetFiles(documentPath, "*.xml");якщо ви (як я) не завжди знаєте імена / кількість файлів документації xml, які там будуть. Також можна зробити більш необхідну фільтрацію.
sǝɯɐſ

2
@Leandro, дякую за покращення відповіді! :) Радий, що Ви вважаєте це корисним.
Кірк Уолл

5
Якби я міг, я поставив би вам +10 за цю детальну та правильну відповідь
Марк ван Стратен

2
Я хотів би додати свої зміни поверх деяких інших тут. Я використав ... \ notation, щоб створити файл xml у папці кореневого проекту App_Data \ документація. Тоді я застосував @ sǝɯɐſ метод видалення всіх файлів xml з цього каталогу. Це прекрасно працює і я здивований, що це не просто те, як це працює поза коробкою. Велике дякую.
Дарролл

32

Я також наткнувся на це, але я не хотів редагувати чи дублювати жоден із створених кодів, щоб уникнути проблем пізніше.

Спираючись на інші відповіді, ось окремий постачальник документів для декількох джерел XML. Просто впустіть це у свій проект:

/// <summary>A custom <see cref="IDocumentationProvider"/> that reads the API documentation from a collection of XML documentation files.</summary>
public class MultiXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
{
    /*********
    ** Properties
    *********/
    /// <summary>The internal documentation providers for specific files.</summary>
    private readonly XmlDocumentationProvider[] Providers;


    /*********
    ** Public methods
    *********/
    /// <summary>Construct an instance.</summary>
    /// <param name="paths">The physical paths to the XML documents.</param>
    public MultiXmlDocumentationProvider(params string[] paths)
    {
        this.Providers = paths.Select(p => new XmlDocumentationProvider(p)).ToArray();
    }

    /// <summary>Gets the documentation for a subject.</summary>
    /// <param name="subject">The subject to document.</param>
    public string GetDocumentation(MemberInfo subject)
    {
        return this.GetFirstMatch(p => p.GetDocumentation(subject));
    }

    /// <summary>Gets the documentation for a subject.</summary>
    /// <param name="subject">The subject to document.</param>
    public string GetDocumentation(Type subject)
    {
        return this.GetFirstMatch(p => p.GetDocumentation(subject));
    }

    /// <summary>Gets the documentation for a subject.</summary>
    /// <param name="subject">The subject to document.</param>
    public string GetDocumentation(HttpControllerDescriptor subject)
    {
        return this.GetFirstMatch(p => p.GetDocumentation(subject));
    }

    /// <summary>Gets the documentation for a subject.</summary>
    /// <param name="subject">The subject to document.</param>
    public string GetDocumentation(HttpActionDescriptor subject)
    {
        return this.GetFirstMatch(p => p.GetDocumentation(subject));
    }

    /// <summary>Gets the documentation for a subject.</summary>
    /// <param name="subject">The subject to document.</param>
    public string GetDocumentation(HttpParameterDescriptor subject)
    {
        return this.GetFirstMatch(p => p.GetDocumentation(subject));
    }

    /// <summary>Gets the documentation for a subject.</summary>
    /// <param name="subject">The subject to document.</param>
    public string GetResponseDocumentation(HttpActionDescriptor subject)
    {
        return this.GetFirstMatch(p => p.GetResponseDocumentation(subject));
    }


    /*********
    ** Private methods
    *********/
    /// <summary>Get the first valid result from the collection of XML documentation providers.</summary>
    /// <param name="expr">The method to invoke.</param>
    private string GetFirstMatch(Func<XmlDocumentationProvider, string> expr)
    {
        return this.Providers
            .Select(expr)
            .FirstOrDefault(p => !String.IsNullOrWhiteSpace(p));
    }
}

... і ввімкніть це у вашому HelpPageConfigканалі до потрібних документів XML:

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

Це чудове рішення. Я віддаю перевагу над рішеннями, які потребують модифікації класів HelpPage за замовчуванням, оскільки вони будуть перезаписані в оновленнях.
AronVanAmmers

3
Це працює чудово, дякую за публікацію. Щоб заощадити будь-кого, хто використовує це трохи часу, вам потрібно виконати перші два етапи прийнятої відповіді kirk вище, тобто 1) Увімкнути XML-документацію для вашого підпроекту та 2) Змінити події після збирання проекту Web Web, щоб скопіювати цей XML-файл у вашу папку App_Data.
tomRedox

1
а потім цей рядок стає: config.SetDocumentationProvider (новий MultiXmlDocumentationProvider (HttpContext.Current.Server.MapPath ("~ / App_Data / [xml_файл оригінального веб-api проекту", за замовчуванням для XmlDocument] .xml "), HttpCurPonterntSonterPersterServer. ("~ / App_Data / [як би ви не назвали своє ім'я файлу SubProject xml] .xml")));
tomRedox

Виконуйте кроки, але не вийшло :(. Помилки немає, тому не впевнені, що пішло не так. Він все ще показує лише документ api, але не додатковий документ проекту. Я також спробував кроки у прийнятій відповіді, і це те саме Що-небудь, зокрема, я повинен перевірити?
stt106

Чомусь я все ще бачу типовий GET api / me, який поставляється із шаблоном проекту для початку роботи у VS.
Джон Заброський



0

Найпростіший спосіб вирішити цю проблему - це створення папки App_Code на розгорнутому сервері. Потім скопіюйте файл XmlDocument.xml у папку bin локально у папку App_Code


Дякую за пропозицію !! Не більше -1 для такої корисної відповіді. Так, якщо ви розгортаєте його в службі додатків Azure Cloud App, багато проблем виникають при багаторазовому розгортанні * .xml, тому надання їх доступними для скачування, наприклад, може бути справді складним. Але я вважаю за краще вибрати іншу стандартну папку на сервері ASP.Net, а саме App_GlobalResources, оскільки файли xmldoc в значній мірі схожі на ресурси. Це особливо вірно, тому що в моєму проекті досі не було папки App_Code, і не важливо, яку стандартну папку створити.
moudrick

Наступна стандартна папка працювала для мене: App_Code - не відображається у клієнта у налаштуваннях за замовчуванням App_GlobalResources - не відображається у клієнта у налаштуваннях за замовчуванням App_LocalResources - не видно у клієнта за замовчуванням
moudrick

Дозвольте також перерахувати проблеми з кожною зі стандартних папок, які не працювали для мене. bin - тільки * .xml для основної збірки розгортається в App_Data - найпрактичніший параметр - пропустити все в цій папці при розгортанні до хмари
moudrick

Чи міг би хтось із зацікавлених редагувати цю відповідь, щоб відобразити всі ці міркування вище, ймовірно, з розширеними міркуваннями?
moudrick
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.