Как Xml Documentation для Web Api включает документацию из-за основного проекта?

Документация для включения интеграции XmlDoc в ваши проекты Web Api работает только с ситуациями, когда все ваши типы API являются частью вашего проекта WebApi. В частности, в нем обсуждается, как перенаправить XML-документацию на App_Data/XmlDocument.xml и раскомментировать строку в вашем конфиге, которая будет потреблять этот файл. Это подразумевает только один файл документации проекта.

Однако в моей настройке у меня есть мои типы запросов и ответов, определенные в общем проекте "Модели". Это означает, что если я определил конечную точку, например:

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

Где OpenIdLoginRequest определяется в отдельном проекте С# так:

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

    ...
}

Несмотря на документы doccomments XML, свойства параметра request не содержат документации, когда вы просматриваете страницу справки о конкретной точке (т.е. http://localhost/Help/Api/POST-auth-openid-login).

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

Ответ 1

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

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

  • Измените событие postbuild проекта веб-API, чтобы скопировать этот XML файл в папку App_Data:

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

    Где Subproject.xml следует переименовать в любое имя вашего проекта плюс .xml.

  • Затем откройте Areas\HelpPage\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 для вашего проекта.

  • Наконец, измените 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());
        }
    }
    

    с. Добавьте следующий конструктор ниже конструктора:

    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 из типов в вашем связанном проекте.

Ответ 2

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

Основываясь на других ответах, здесь имеется автономный поставщик документации для нескольких источников 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.GetDocumentation(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")));

Ответ 4

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