Web APIのXmlドキュメントに、メインプロジェクト以外のドキュメントをどのように含めることができますか?


102

XmlDocをWeb Apiプロジェクトに統合できるようにするためのドキュメントは、すべてのAPIタイプがWebApiプロジェクトの一部である状況のみを処理するように見えます。特に、XMLドキュメントを再ルーティングして、App_Data/XmlDocument.xmlそのファイルを使用する構成内の行のコメントを外す方法について説明します。これは暗黙的に1つのプロジェクトのドキュメントファイルのみを許可します。

ただし、私のセットアップでは、リクエストとレスポンスのタイプを共通の「モデル」プロジェクトで定義しています。つまり、次のようなエンドポイントが定義されている場合、

[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 doccommentsにもかかわらず、requestエンドポイント固有のヘルプページ(つまりhttp://localhost/Help/Api/POST-auth-openid-login)を表示すると、パラメーターのプロパティにはドキュメントが含まれません。

XMLドキュメントを含むサブプロジェクトの型がWeb API XMLドキュメントに表示されるようにするにはどうすればよいですか?

回答:


165

これを実現する組み込みの方法はありません。ただし、必要な手順はわずかです。

  1. Web APIプロジェクトの場合と同様に、(プロジェクトプロパティ/ビルドから)サブプロジェクトのXMLドキュメントを有効にします。今回以外は、直接ルーティングしてXmlDocument.xml、プロジェクトのルートフォルダーに生成されるようにします。

  2. Web APIプロジェクトのポストビルドイベントを変更して、このXMLファイルをApp_Dataフォルダーにコピーします。

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

    where Subproject.xmlは、プロジェクトの名前がplusであるものに名前を変更する必要があります.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に、次の方法で変更します。

    a。_documentNavigatorフィールドを次のものに置き換えます。

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

    b。コンストラクタを次のものに置き換えます。

    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。最後に、すべてのコンパイラエラーを修正し(3つ存在する必要があります)_documentNavigator.SelectSingleNode、その_documentNavigator.部分を参照して削除し、SelectSingleNode上記で定義した新しいメソッドを呼び出すようにします。

この最後のステップでは、ドキュメントプロバイダーを変更して、プライマリプロジェクトだけでなく、複数のXMLドキュメント内でヘルプテキストを探すことをサポートします。

ヘルプドキュメントを調べると、関連プロジェクトのタイプのXMLドキュメントが含まれています。


7
すばらしい答えです。実際には、コンストラクターが文字列の配列を受け入れる方が少し簡単だと思います:public XmlDocumentationProvider(string appDataPath)そしてこのリストをドキュメントプロバイダーで列挙します。
ジョンキャプテン

14
素晴らしい、これはまさに私が探していたものでした!(私のように)そこにあるxmlドキュメントファイルの名前/数が常にわからない場合は、var files...行を置き換えるvar files = Directory.GetFiles(documentPath, "*.xml");ことをお勧めします。必要に応じて、さらにフィルタリングを行うこともできます。
2014

2
@Leandro、回答を改善してくれてありがとう!:)お役に立ててうれしいです。
Kirk Woll 2014年

5
できれば、この詳細で正解の+10をお送りします
マークファンストラテン

2
ここで他のいくつかの上に私の変更を追加したいと思います。... \表記を使用して、xmlファイルをルートプロジェクトのApp_Data \ documentationフォルダーに作成しました。次に、@ s fromメソッドを使用して、そのディレクトリからすべてのxmlファイルをプルしました。これは美しく機能し、これがそのままの状態で機能するだけではないことに驚いています。どうもありがとう。
Darroll

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

...そして、必要なHelpPageConfigXMLドキュメントへのパスを使用してそれを有効にします。

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

これは素晴らしいソリューションです。更新時に上書きされるため、デフォルトのHelpPageクラスの変更が必要なソリューションよりも優先します。
AronVanAmmers 2015

3
これは見事に機能します。投稿していただきありがとうございます。これを使用して誰かを少し時間を節約するには、上記のカークの回答の最初の2段階を実行する必要があります。つまり、1)サブプロジェクトのXMLドキュメントを有効にし、2)Web APIプロジェクトのポストビルドイベントを変更して、このXMLファイルをApp_Dataフォルダー。
tomRedox 2015

1
次に、この行は次のようになります。 ( "〜/ App_Data / [サブプロジェクトxmlファイル名] .xmlと呼んだもの")));
tomRedox 2015

手順を実行したが機能しなかった:(。エラーは発生していないため、何が問題だったのかは不明です。APIドキュメントのみが表示され、追加のプロジェクトドキュメントは表示されません。承認された回答の手順も試してみましたが、同じことです。特に確認すべきことはありますか?
stt106 '19

何らかの理由で、VSの入門プロジェクトテンプレートに付属するデフォルトのGET api / meがまだ表示されます。
John Zabroski、2016



0

この問題を修正する最も簡単な方法は、デプロイしたサーバーにApp_Codeフォルダーを作成することです。次に、binフォルダーにあるXmlDocument.xmlをローカルでApp_Codeフォルダーにコピーします。


提案をありがとう!そのような役立つ答えに対しては、これ以上-1はありません。はい、Azure Cloud App Serviceにデプロイすると、複数の* .xmlデプロイで多くの問題が発生するため、たとえば、それらをswaggerで使用できるようにするのは非常に難しい場合があります。ただし、xmldocファイルはリソースに非常によく似ているため、別の標準のASP.Netサーバー側フォルダー、つまりApp_GlobalResourcesを選択します。私のプロジェクトにはまだApp_Codeフォルダーがなく、どの標準フォルダーを作成するかは問題ではないため、これは特に当てはまります。
moudrick 2016年

App_Code-デフォルト設定ではクライアントから表示されないApp_GlobalResources-デフォルト設定ではクライアントから表示されないApp_LocalResources-デフォルト設定ではクライアントから表示されない
moudrick

私にとってうまくいかなかった各標準フォルダの問題もリストアップします。bin-メインアセンブリの* .xmlのみがApp_Dataに展開されます。最も実用的な設定は、クラウドへの展開時にこのフォルダーのすべてをスキップすることです
moudrick

興味のある人はこの回答を編集して、おそらくこれらの考慮事項をすべて反映して、おそらく拡張された推測をすることができますか?
moudrick 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.