Как может XML-документация для веб-API включать документацию, выходящую за рамки основного проекта?

документация для включения интеграции XmlDoc в ваш веб-API. Кажется, что проекты обрабатывают только ситуации, когда все ваши типы 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?


person Kirk Woll    schedule 19.02.2014    source источник


Ответы (5)


Для этого нет встроенного способа. Однако для этого требуется всего несколько шагов:

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

  2. Измените событие postbuild вашего проекта 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;
    }
    

    d. И, наконец, исправьте все ошибки компилятора (их должно быть три), приводящие к ссылкам на _documentNavigator.SelectSingleNode, и удалите часть _documentNavigator., чтобы теперь она вызывала новый метод SelectSingleNode, который мы определили выше.

Этот последний шаг - это то, что изменяет поставщика документов для поддержки поиска текста справки в нескольких XML-документах, а не только в основном проекте.

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

person Kirk Woll    schedule 19.02.2014
comment
Отличный ответ. Я действительно думаю, что конструктору немного проще принять массив строк: public XmlDocumentationProvider (string appDataPath) и перечислить этот список в поставщике документации. - person Captain John; 20.02.2014
comment
@CaptainJohn, спасибо! Я согласен, что ваше предложение сработает. Тем не менее, я думаю, что оставлю его как есть, поскольку он сохраняет большинство изменений в XmlDocumentationProvider. Изначально я собирался оставить эту строку без изменений и извлечь родительскую папку из переданного файла, но мне это показалось слишком беспорядочным. - person Kirk Woll; 21.02.2014
comment
Потрясающе, это было именно то, что я искал !! Предложите заменить строку var files... на var files = Directory.GetFiles(documentPath, "*.xml");, если вы (как и я) не всегда знаете имена / количество файлов документации xml, которые будут там. При необходимости может также выполнять дополнительную фильтрацию. - person sǝɯɐſ; 03.07.2014
comment
Кроме того, мне нужно было исправить только 2 ссылки на шаге 4d ... Я использую Web API 2.1 - person sǝɯɐſ; 03.07.2014
comment
Спасибо, Кирк Уолл, это просто идеальный ответ. Позволю себе (извините) обновить ваш идеальный вопрос, потому что я с первого взгляда не нашел, где изменить путь XML :) - person Leandro Bardelli; 05.11.2014
comment
@Leandro, спасибо за улучшение ответа! :) Рад, что ты нашел это полезным. - person Kirk Woll; 05.11.2014
comment
Есть ли причина не просто установить файл документации XML в App_Data \ XmlDocument.xml и пропустить этап сборки? - person Steven; 16.12.2014
comment
@StevenBerkovitz, но тогда вы бы уничтожили любую XML-документацию для вашего основного проекта веб-API, верно? - person Kirk Woll; 16.12.2014
comment
Если бы я мог, я бы поставил вам +10 за этот подробный и правильный ответ - person Mark van Straten; 07.04.2015
comment
Просто потому, что у меня возникла ошибка в событии postbuild, я подумал, что это может быть полезно для тех, у кого такая же проблема: скопируйте $ (SolutionDir) SubProject \ XmlDocument.xml $ (ProjectDir) App_Data \ SubProject.xml - person Stefano Magistri; 16.07.2015
comment
Просто великолепно!!! Следуйте инструкциям и работает как шарм !!! Спасибо @KirkWoll - person SO User; 03.02.2016
comment
Я хотел бы добавить сюда свои модификации поверх некоторых других. Я использовал нотацию ... \, чтобы создать XML-файл в корневой папке проекта App_Data \ documentation. Затем я использовал метод @ sǝɯɐſ для удаления всех файлов xml из этого каталога. Это прекрасно работает, и я удивлен, что это работает не только из коробки. Большое спасибо. - person Darroll; 17.06.2016
comment
Отличный ответ! Я бы предложил одно небольшое улучшение. Пусть все ваши документы заканчиваются на XmlDocument.xml (например: Subproject.XmlDocument.xml) и заменяют var files = new[] { "XmlDocument.xml", "Subproject.xml" }; foreach (var file in files) на foreach (var file in Directory.EnumerateFiles(documentPath, "*XmlDocument.xml")) и удаляют вызов Path.Combine - person Stanislav; 08.07.2016
comment
Чувак - офигенно. - person Jmoney38; 02.12.2016
comment
... безмолвный, почти плачущий ... Пятница, 7 вечера, последовала за этим в полном тупике, не понимая ни слова. ШАРМ - person Shockwaver; 13.01.2017
comment
Может быть, я слишком тупой, но почему бы просто не скопировать все файлы .xml из каталога \ bin после сборки? Таким образом, вы получите всю документацию для всех .dll? - person DaleyKD; 09.02.2018

Я тоже столкнулся с этим, но я не хотел редактировать или дублировать какой-либо сгенерированный код, чтобы избежать проблем позже.

Основываясь на других ответах, вот автономный поставщик документации для нескольких источников 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")));
person Pathoschild    schedule 06.02.2015
comment
Это отличное решение. Я предпочитаю его решениям, требующим изменения классов HelpPage по умолчанию, поскольку они будут перезаписаны при обновлении. - person AronVanAmmers; 15.04.2015
comment
Это прекрасно работает, спасибо за публикацию. Чтобы сэкономить кому-то, кто использует это немного времени, вам все равно нужно выполнить первые два этапа принятого ответа Кирка выше, то есть 1) включить документацию XML для вашего подпроекта и 2) изменить событие postbuild вашего проекта веб-API, чтобы скопировать этот XML-файл в ваша папка App_Data. - person tomRedox; 01.07.2015
comment
а затем эта строка становится: config.SetDocumentationProvider (новый MultiXmlDocumentationProvider (HttpContext.Current.Server.MapPath (~ / App_Data / [исходное имя файла xml проекта веб-API, по умолчанию - XmlDocument] .xml), HttpContext.Current.Server.MapPath (~ / App_Data / [Как бы вы ни называли свой XML-файл субпроекта] .xml))); - person tomRedox; 01.07.2015
comment
Выполнил шаги, но не сработал :(. Ошибки нет, поэтому не уверен, что пошло не так. Он по-прежнему показывает только документ api, но не дополнительный документ проекта. Я также попробовал шаги в принятом ответе, и это то же самое .. Что-нибудь конкретное я должен проверить? - person stt106; 19.11.2015
comment
По какой-то причине я все еще вижу GET api / me по умолчанию, который поставляется с шаблоном проекта для начала работы в VS. - person John Zabroski; 21.04.2016
comment
заметил одну мелочь: метод GetResponseDocumentation должен возвращать this.GetFirstMatch(p => p.GetResponseDocumentation(subject)); - person mikelt21; 12.04.2018
comment
Первая попытка работает нормально. Спасибо за решение. - person Mahi Uddin; 04.03.2020

Еще один упрощенный способ сделать это - объединить файлы xml. Пример кода в моем ответе ниже:

XML-комментарии страницы справки веб-API из более чем 1 файла

person Kiran Challa    schedule 05.03.2014

Самый простой способ решить эту проблему - создать папку App_Code на развернутом сервере. Затем скопируйте файл XmlDocument.xml, который находится в папке bin, локально в папку App_Code.

person Ziregbe Otee    schedule 04.03.2016
comment
Спасибо за предложение !! Не больше -1 за такой полезный ответ. Да, если вы развертываете его в Azure Cloud App Service, многие проблемы возникают при развертывании нескольких * .xml, поэтому сделать их доступными, например, для чванства может быть действительно сложно. Но я бы предпочел выбрать другую стандартную серверную папку ASP.Net, а именно App_GlobalResources, поскольку файлы xmldoc во многом похожи на ресурсы. Это особенно верно, потому что в моем проекте все еще не было папки App_Code, и не имело значения, какую стандартную папку создавать. - person moudrick; 16.11.2016
comment
У меня работала следующая стандартная папка: App_Code - не отображается на клиенте в настройках по умолчанию App_GlobalResources - не отображается из клиента в настройках по умолчанию App_LocalResources - не отображается из клиента в настройках по умолчанию - person moudrick; 16.11.2016
comment
Позвольте мне также перечислить проблемы с каждой из стандартных папок, которые у меня не работали. bin - только * .xml для основной сборки деплопируется в App_Data - наиболее практичный параметр - пропустить все в этой папке при развертывании в облако - person moudrick; 16.11.2016
comment
Может ли кто-нибудь, кто заинтересован, отредактировать этот ответ, чтобы отразить все эти соображения, приведенные выше, возможно, с расширенными предположениями? - person moudrick; 16.11.2016

Я нашел лучшее решение

  1. Перейдите к свойствам вашего решения и на странице Built, Out Put, Documentation XML File просто заполните свою папку данными вашего приложения.

  2. Добавьте строку с файлом, который вы хотите вставить в свою документацию, вот так.

config.SetDocumentationProvider (новый XmlDocumentationProvider (HttpContext.Current.Server.MapPath (~ / App_Data / FenixCorporate.API.xml)));

        config.SetDocumentationProvider(new XmlDocumentationProvider(
            HttpContext.Current.Server.MapPath("~/App_Data/FenixCorporate.Entities.xml")));
person user1768874    schedule 15.09.2020