21

我在我的Web api項目中使用他們自己的XML文檔有不同的插件,並且有一個集中的幫助頁面,但問題是Web Api的默認幫助頁面僅支持單個文檔文件Web Api幫助頁面來自多個文件的XML評論

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

如何從不同的文件加載配置?我婉做某事是這樣的:

new XmlDocumentationProvider("PluginsFolder/*.xml") 

回答

29

您可以修改在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(); 
+2

正是我需要的。 – Levan

+2

我不明白爲什麼這不是在默認版本。它比MS所做的更有意義。 –

19

Kirans解決方案工作得很好。最後我用他的做法,但通過創建XmlDocumentationProvider的副本,叫做MultiXmlDocumentationProvider,具有改變的構造函數:

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

創建一個新的類並保持原來的不變可能會更方便升級等...

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/"))); 
5

而不是產生沿着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);