【问题标题】:Web Api Help Page XML comments from more than 1 files来自 1 个以上文件的 Web Api 帮助页面 XML 注释
【发布时间】:2014-03-04 07:37:38
【问题描述】:

我的 Web api 项目中有不同的插件和他们自己的 XML 文档,并且有一个集中的帮助页面,但问题是 Web Api 的默认帮助页面只支持单个文档文件

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

如何从不同的文件加载配置?我想做这样的事情:

new XmlDocumentationProvider("PluginsFolder/*.xml")

【问题讨论】:

    标签: asp.net asp.net-web-api documentation asp.net-web-api-helppages


    【解决方案1】:

    您可以在Areas\HelpPage 处修改已安装的XmlDocumentationProvider 以执行以下操作:

    将多个 Xml 文档文件合并为一个:

    示例代码(缺少一些错误检查和验证):

    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();
    

    【讨论】:

    • 我不明白为什么这不在默认版本中。这比 MS 所做的更有意义。
    【解决方案2】:

    Kirans 解决方案效果很好。我最终使用了他的方法,但通过创建一个名为 MultiXmlDocumentationProviderXmlDocumentationProvider 副本,并使用更改的构造函数:

    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();
    }
    

    我从 HelpPageConfig.cs 注册了新的提供者:

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

    在升级等时创建一个新类并保持原来的类不变可能会更方便......

    【讨论】:

      【解决方案3】:

      我没有像 XmlMultiDocumentationProvider 那样创建一个单独的类,而是向现有的 XmlDocumentationProvider 添加了一个构造函数。这不是使用文件夹名称,而是使用字符串列表,因此您仍然可以准确指定要包含的文件(如果文档 XML 所在的目录中有其他 xml 文件,它可能 多毛)。这是我的新构造函数:

      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();
      }
      

      HelpPageConfig.cs 看起来像这样。 (是的,它可以更少行,但我没有行数限制,所以我喜欢拆分它。)

      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);
      

      【讨论】:

        【解决方案4】:

        我同意 gurra777 的观点,即创建新类是更安全的升级途径。我从那个解决方案开始,但它涉及大量的复制/意大利面,在几次包更新后很容易过时。

        相反,我保留了XmlDocumentationProvider 孩子的集合。对于每个实现方法,我都会调用孩子来获取第一个非空结果。

        public class MultiXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
        {
            private IList<XmlDocumentationProvider> _documentationProviders;
        
            public MultiXmlDocumentationProvider(string xmlDocFilesPath)
            {
                _documentationProviders = new List<XmlDocumentationProvider>();
        
                foreach (string file in Directory.GetFiles(xmlDocFilesPath, "*.xml"))
                {
                    _documentationProviders.Add(new XmlDocumentationProvider(file));
                }
            }
        
            public string GetDocumentation(System.Reflection.MemberInfo member)
            {
                return _documentationProviders
                    .Select(x => x.GetDocumentation(member))
                    .FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
            }
        
            //and so on...
        

        HelpPageConfig注册和gurra777的回答一样,

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-06-19
          • 2016-09-24
          • 2015-07-18
          • 2014-12-27
          • 2014-11-23
          • 2016-12-08
          • 1970-01-01
          相关资源
          最近更新 更多