Bagaimana Dokumentasi Xml untuk Api Web menyertakan dokumentasi dari luar proyek utama?

102

The dokumentasi untuk memungkinkan integrasi xmldoc ke proyek-proyek Api Web Anda tampaknya hanya situasi pegangan di mana semua jenis API Anda adalah bagian dari proyek WebAPI Anda. Secara khusus, ini membahas cara mengubah rute dokumentasi XML ke App_Data/XmlDocument.xmldan menghapus komentar baris di konfigurasi Anda yang akan menggunakan file itu. Ini secara implisit hanya memungkinkan untuk satu file dokumentasi proyek.

Namun, dalam pengaturan saya, saya memiliki jenis permintaan dan respons yang ditentukan dalam proyek "Model" umum. Ini berarti jika saya memiliki titik akhir yang ditentukan seperti:

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

Di mana OpenIdLoginRequestdidefinisikan dalam proyek C # terpisah seperti:

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

    ...
}

Terlepas dari dokumen XML, properti requestparameter tidak berisi dokumentasi saat Anda melihat halaman bantuan khusus titik akhir (yaitu http://localhost/Help/Api/POST-auth-openid-login).

Bagaimana cara membuatnya sehingga jenis subproyek dengan dokumentasi XML muncul di dokumentasi Web API XML?

Kirk Woll
sumber

Jawaban:

165

Tidak ada cara bawaan untuk mencapai ini. Namun, ini hanya membutuhkan beberapa langkah:

  1. Aktifkan dokumentasi XML untuk subproyek Anda (dari properti / build proyek) seperti yang Anda miliki untuk proyek API Web Anda. Kecuali kali ini, arahkan langsung ke XmlDocument.xmlsehingga dibuat di folder root proyek Anda.

  2. Ubah acara postbuild proyek API Web Anda untuk menyalin file XML ini ke App_Datafolder Anda :

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

    Di mana Subproject.xmlharus diganti namanya menjadi apa pun nama proyek Anda plus .xml.

  3. Selanjutnya buka Areas\HelpPage\App_Start\HelpPageConfigdan cari baris berikut:

    config.SetDocumentationProvider(new XmlDocumentationProvider(
        HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));

    Ini adalah baris yang pertama kali Anda hapus komentarnya untuk mengaktifkan dokumentasi bantuan XML. Ganti baris itu dengan:

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

    Langkah ini memastikan bahwa XmlDocumentationProviderdirektori yang berisi file XML Anda diteruskan, bukan file XML tertentu untuk proyek Anda.

  4. Terakhir, ubah Areas\HelpPage\XmlDocumentationProviderdengan cara berikut:

    Sebuah. Ganti _documentNavigatorbidang dengan:

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

    b. Ganti konstruktor dengan:

    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. Tambahkan metode berikut di bawah konstruktor:

    private XPathNavigator SelectSingleNode(string selectExpression)
    {
        foreach (var navigator in _documentNavigators)
        {
            var propertyNode = navigator.SelectSingleNode(selectExpression);
            if (propertyNode != null)
                return propertyNode;
        }
        return null;
    }

    d. Dan terakhir, perbaiki semua kesalahan kompilator (seharusnya ada tiga) yang menghasilkan referensi ke _documentNavigator.SelectSingleNodedan menghapus _documentNavigator.bagian sehingga sekarang memanggil SelectSingleNodemetode baru yang kita definisikan di atas.

Langkah terakhir ini adalah yang mengubah penyedia dokumen untuk mendukung pencarian di dalam beberapa dokumen XML untuk teks bantuan, bukan hanya proyek utama.

Sekarang ketika Anda memeriksa dokumentasi Bantuan Anda, itu akan menyertakan dokumentasi XML dari tipe dalam proyek terkait Anda.

Kirk Woll
sumber
7
Jawaban yang sangat bagus. Saya benar-benar berpikir itu sedikit lebih mudah bagi konstruktor untuk menerima array string: public XmlDocumentationProvider (string appDataPath) dan menghitung daftar ini di penyedia Dokumentasi.
Kapten John
14
Fantastis, inilah yang saya cari !! Sarankan untuk mengganti var files...baris dengan var files = Directory.GetFiles(documentPath, "*.xml");jika Anda (seperti saya) tidak selalu tahu nama / jumlah file dokumentasi xml yang akan ada di sana. Bisa juga melakukan penyaringan lebih lanjut sesuai kebutuhan.
sǝɯɐſ
2
@Leandro, terima kasih telah meningkatkan jawabannya! :) Senang Anda merasa terbantu.
Kirk Woll
5
Jika saya bisa, saya akan memberi +10 Anda untuk jawaban yang rinci & benar ini
Mark van Straten
2
Saya ingin menambahkan modifikasi saya di atas beberapa yang lain di sini. Saya menggunakan ... \ notation untuk membuat file xml di folder root project App_Data \ dokumentasi. Saya kemudian menggunakan metode @ sǝɯɐſ untuk mem-puling semua file xml dari direktori itu. Ini bekerja dengan baik dan saya terkejut bahwa ini bukan hanya cara kerjanya di luar kotak. Terimakasih banyak.
Darroll
32

Saya mengalami ini juga, tetapi saya tidak ingin mengedit atau menduplikasi kode apa pun yang dihasilkan untuk menghindari masalah nanti.

Berdasarkan jawaban lain, berikut adalah penyedia dokumentasi mandiri untuk berbagai sumber XML. Letakkan saja ini ke dalam proyek Anda:

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

... dan aktifkan di Anda HelpPageConfigdengan path ke dokumen XML yang Anda inginkan:

config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/Api.xml"), HttpContext.Current.Server.MapPath("~/App_Data/Api.Models.xml")));
Pathoschild
sumber
Ini adalah solusi yang bagus. Saya lebih memilihnya daripada solusi yang memerlukan modifikasi kelas HelpPage default karena mereka akan ditimpa pada pembaruan.
AronVanAmmers
3
Ini bekerja dengan sangat baik, terima kasih telah memposting. Untuk menghemat waktu siapa pun yang menggunakan ini, Anda masih perlu melakukan dua tahap pertama dari jawaban kirk yang diterima di atas, yaitu 1) Aktifkan dokumentasi XML untuk subproyek Anda dan 2) Ubah acara postbuild proyek API Web Anda untuk menyalin file XML ini ke dalamnya folder App_Data Anda.
tomRedox
1
dan kemudian baris ini menjadi: config.SetDocumentationProvider (MultiXmlDocumentationProvider baru (HttpContext.Current.Server.MapPath ("~ / App_Data / [nama file xml proyek api web asli, default ke XmlDocument] .xml"), HttpContext.Current.Server.MapPath ("~ / App_Data / [Apapun yang Anda sebut nama file xml SubProyek Anda] .xml")));
tomRedox
Mengikuti langkah-langkah tetapi tidak berhasil :(. Tidak ada kesalahan jadi tidak yakin apa yang salah. Itu masih hanya menampilkan dokumen api tetapi bukan dokumen proyek tambahan. Saya juga mencoba langkah-langkah dalam jawaban yang diterima dan itu hal yang sama Ada hal khusus yang harus saya periksa?
stt106
Untuk beberapa alasan saya masih melihat GET api / me default yang disertakan dengan template proyek untuk memulai di VS.
John Zabroski
0

Cara termudah untuk memperbaiki masalah ini adalah membuat folder App_Code di server yang Anda gunakan. Kemudian salin XmlDocument.xml yang Anda miliki di folder bin Anda secara lokal ke folder App_Code

Ziregbe Otee
sumber
Terima kasih atas saran !! Tidak ada lagi -1 untuk jawaban yang sangat membantu. Ya, jika Anda menerapkannya ke Azure Cloud App Service, banyak masalah terjadi dengan beberapa penerapan * .xml, jadi membuatnya tersedia untuk kesombongan, misalnya, mungkin sangat rumit. Tetapi saya lebih suka memilih folder sisi server ASP.Net standar lainnya, yaitu App_GlobalResources, karena file xmldoc sangat mirip dengan sumber daya. Ini terutama benar karena saya masih tidak memiliki folder App_Code dalam proyek saya dan tidak masalah folder standar mana yang harus dibuat.
moudrick
Folder standar berikut berfungsi untuk saya: App_Code - tidak terlihat dari klien pada pengaturan default App_GlobalResources - tidak terlihat dari klien pada pengaturan default App_LocalResources - tidak terlihat dari klien pada pengaturan default
moudrick
Izinkan saya juga mencantumkan masalah dengan masing-masing folder standar yang tidak berfungsi untuk saya. bin - hanya * .xml untuk perakitan utama disalin ke App_Data - pengaturan paling praktis adalah melewati semua yang ada di folder ini saat menyebarkan ke cloud
moudrick
Adakah yang tertarik mengedit jawaban ini untuk mencerminkan semua pertimbangan di atas, mungkin dengan spekulasi diperpanjang?
moudrick