Web Api için Xml Belgeleri, ana projenin dışındaki belgeleri nasıl içerebilir?


102

Dokümantasyon Web Api projelerine XmlDoc entegrasyonunu sağlamak için API türlerinin tüm WebAPI projesinin bir parçası olan sadece sap durumlara görünür. Özellikle, XML belgelerinin App_Data/XmlDocument.xmlyapılandırmanızdaki bu dosyayı tüketecek bir satıra nasıl yeniden yönlendirileceğini ve yorumlanmayacağını açıklar. Bu örtük olarak yalnızca bir projenin dokümantasyon dosyasına izin verir.

Ancak, kurulumumda istek ve yanıt türlerimi ortak bir "Modeller" projesinde tanımlıyorum. Bu, aşağıdaki gibi tanımlanmış bir uç noktam varsa anlamına gelir:

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

Nerede OpenIdLoginRequestşöyle ayrı C # projesi tanımlanır:

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 belgelerine rağmen, requestuç noktaya özgü yardım sayfasını (yani http://localhost/Help/Api/POST-auth-openid-login) görüntülediğinizde parametrenin özellikleri hiçbir belge içermez .

XML belgeli alt projelerdeki türlerin Web API XML belgelerinde ortaya çıkması için bunu nasıl yapabilirim?

Yanıtlar:


165

Bunu başarmanın yerleşik bir yolu yoktur. Ancak, yalnızca birkaç adım gerektirir:

  1. Web API projenizde olduğu gibi alt projeniz için XML belgelerini etkinleştirin (proje özelliklerinden / derlemesinden) Bu sürenin dışında XmlDocument.xml, projenizin kök klasöründe üretilmesi için doğrudan yönlendirin .

  2. Bu XML dosyasını App_Dataklasörünüze kopyalamak için Web API projenizin postbuild olayını değiştirin :

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

    Subproject.xmlProjenizin adı artı ise nerede yeniden adlandırılmalıdır .xml.

  3. Ardından Areas\HelpPage\App_Start\HelpPageConfigaşağıdaki satırı açın ve bulun:

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

    Bu, ilk etapta XML yardım belgelerini etkinleştirmek için ilk başta yorumlamadığınız satırdır. Bu satırı şununla değiştirin:

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

    Bu adım XmlDocumentationProvider, projeniz için belirli XML dosyası yerine XML dosyalarınızı içeren dizinin geçmesini sağlar .

  4. Son olarak, Areas\HelpPage\XmlDocumentationProvideraşağıdaki şekillerde değişiklik yapın :

    a. _documentNavigatorAlanı şununla değiştirin :

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

    b. Yapıcıyı şununla değiştirin:

    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. Yapıcının altına aşağıdaki yöntemi ekleyin:

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

    d. Ve son olarak, tüm derleyici hatalarını düzeltin (üç tane olması gerekir) _documentNavigator.SelectSingleNode, bu _documentNavigator.bölüme referanslarla sonuçlanır ve bölümü kaldırır, böylece şimdi SelectSingleNodeyukarıda tanımladığımız yeni yöntemi çağırır .

Bu Son adım, belge sağlayıcısını, yalnızca birincil proje yerine yardım metni için birden çok XML belgesine bakmayı destekleyecek şekilde değiştiren şeydir.

Artık Yardım belgelerinizi incelediğinizde, ilgili projenizdeki türlerden XML belgelerini içerecek.


7
Mükemmel cevap. Aslında, kurucunun bir dizi dizeyi kabul etmesinin biraz daha kolay olduğunu düşünüyorum: public XmlDocumentationProvider (string appDataPath) ve bu listeyi Documentation sağlayıcısında numaralandırın.
Captain John

14
Harika, tam da aradığım buydu !! Siz (benim gibi) orada olacak xml dokümantasyon dosyalarının adlarını / sayısını her zaman bilmiyorsanız , var files...satırı değiştirmenizi önerin var files = Directory.GetFiles(documentPath, "*.xml");. Gerektiğinde daha fazla filtreleme de yapabilir.
2014

2
@Leandro, cevabı geliştirdiğiniz için teşekkürler! :) Yararlı bulduğunuza sevindim.
Kirk Woll

5
Yapabilseydim, bu ayrıntılı ve doğru cevap için seni +10 yapardım
Mark van Straten

2
Değişikliklerimi burada diğerlerinin bazılarının üzerine eklemek istiyorum. Kök proje App_Data \ dokümantasyon klasöründe xml dosyasını oluşturmak için ... \ gösterimini kullandım. Daha sonra bu dizindeki tüm xml dosyalarına pul atmak için @ sǝɯɐſ yöntemini kullandım. Bu çok güzel çalışıyor ve bunun kutudan çıktığı gibi çalışmamasına şaşırdım. Çok teşekkürler.
Darroll

32

Bununla ben de karşılaştım, ancak daha sonra sorunları önlemek için üretilen kodların hiçbirini düzenlemek veya kopyalamak istemedim.

Diğer yanıtlardan yola çıkarak, birden çok XML kaynağı için bağımsız bir belge sağlayıcısı burada. Bunu projenize bırakın:

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

... ve HelpPageConfigistediğiniz XML belgelerine giden yollarda bunu etkinleştirin :

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

Bu harika bir çözüm. Güncellemelerde üzerine yazılacağı için varsayılan HelpPage sınıflarının değiştirilmesini gerektiren çözümlere tercih ederim.
AronVanAmmers

3
Bu harika çalışıyor, gönderdiğiniz için teşekkürler. Bunu kullanan herkesi biraz zaman kazanmak için, yukarıdaki kirk'in kabul ettiği yanıtın ilk iki aşamasını yapmanız gerekir, yani 1) Alt projeniz için XML belgelerini etkinleştirin ve 2) Web API projenizin postbuild olayını bu XML dosyasını kopyalayacak şekilde değiştirin. App_Data klasörünüz.
tomRedox

1
ve sonra bu satır şu hale gelir: config.SetDocumentationProvider (new MultiXmlDocumentationProvider (HttpContext.Current.Server.MapPath ("~ / App_Data / [orijinal web api projesinin xml dosya adı, varsayılan olarak XmlDocument] .xml"), HttpContext.Current.Server.MapPath ("~ / App_Data / [Alt Projenizin xml dosya adı] .xml")));
tomRedox

Adımları izledim ama işe yaramadı :(. Hata yok, bu yüzden neyin yanlış gittiğinden emin değilim. Hala sadece api belgesini gösteriyor, ek proje belgesini göstermiyor. Ayrıca kabul edilen cevaptaki adımları denedim ve aynı şey . Özellikle kontrol etmem gereken bir şey var mı?
stt106

Bazı nedenlerden dolayı, VS'de başlarken proje şablonuyla birlikte gelen varsayılan GET api / me'yi görüyorum.
John Zabroski


0

Bu sorunu çözmenin en kolay yolu, dağıttığınız sunucuda App_Code klasörünü oluşturmaktır. Ardından bin klasörünüzde bulunan XmlDocument.xml dosyasını yerel olarak App_Code klasörüne kopyalayın.


Öneriniz için teşekkürler !! Böylesine yararlı bir cevap için artık -1 yok. Evet, onu Azure Bulut Uygulama Hizmeti'ne dağıtıyorsanız, birden çok * .xml dağıtımıyla ilgili birçok sorun ortaya çıkar, bu nedenle, örneğin, bunları havalı için kullanılabilir hale getirmek gerçekten zor olabilir. Ancak xmldoc dosyaları kaynaklara oldukça benzer olduğundan, başka bir standart ASP.Net sunucu tarafı klasörü olan App_GlobalResources'i seçmeyi tercih ederim. Bu özellikle doğrudur çünkü projemde hala App_Code klasörüm yoktu ve hangi standart klasörün yaratılacağı önemli değildi.
moudrick

Aşağıdaki standart klasör benim için çalıştı: App_Code - varsayılan ayarlarda istemciden görünmez App_GlobalResources - varsayılan ayarlarda istemciden görünmez App_LocalResources - varsayılan ayarlarda istemciden görünmez
moudrick

Benim için çalışmayan her bir standart klasörle ilgili sorunları da listeleyeyim. bin - ana derleme için yalnızca * .xml, App_Data'ya deplopyed - en pratik ayar, bu klasördeki her şeyi buluta dağıtmak için
atlamaktır

Bu cevabı, muhtemelen geniş kapsamlı spekülasyonlarla, yukarıdaki tüm bu düşünceleri yansıtacak şekilde düzenlemek isteyen biri olabilir mi?
moudrick
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.