Web Api 용 Xml 문서에 기본 프로젝트 이외의 문서를 포함하려면 어떻게해야합니까?


102

문서 귀하의 웹 API 프로젝트에 해당 xmldoc 통합을 가능하게하여 API 유형의 모든 당신의 WebApi 프로젝트의 일부로 만 핸들 상황에 나타납니다. 특히, App_Data/XmlDocument.xml구성에서 해당 파일을 사용할 줄로 XML 문서를 다시 라우팅 하고 주석 처리를 제거하는 방법에 대해 설명 합니다. 이것은 암시 적으로 하나의 프로젝트 문서 파일 만 허용합니다.

그러나 설정에서 공통 "모델"프로젝트에 정의 된 요청 및 응답 유형이 있습니다. 이는 다음과 같이 정의 된 엔드 포인트가있는 경우를 의미합니다.

[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 문서 주석에도 불구하고 request엔드 포인트 별 도움말 페이지 (예 :) 를 볼 때 매개 변수 의 속성 에는 문서가 포함되어 있지 않습니다 http://localhost/Help/Api/POST-auth-openid-login.

XML 문서가있는 하위 프로젝트의 유형이 Web API XML 문서에 표시되도록하려면 어떻게해야합니까?

답변:


165

이를 달성하기위한 기본 제공 방법이 없습니다. 그러나 몇 단계 만 필요합니다.

  1. Web API 프로젝트와 마찬가지로 하위 프로젝트 (프로젝트 속성 / 빌드에서)에 대한 XML 문서를 활성화합니다. 이번을 제외하고 XmlDocument.xml는 프로젝트의 루트 폴더에 생성되도록 직접 라우팅하십시오 .

  2. Web API 프로젝트의 postbuild 이벤트를 수정하여이 XML 파일을 App_Data폴더 에 복사 합니다.

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

    어디에서 Subproject.xml어떤 프로젝트의 이름으로 이름을 변경해야한다 플러스입니다 .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다음과 같은 방법 으로 수정 하십시오.

    ㅏ. _documentNavigator필드를 다음으로 바꿉니다 .

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

    비. 생성자를 다음으로 바꿉니다.

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

    씨. 생성자 아래에 다음 메서드를 추가합니다.

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

    디. 마지막으로 모든 컴파일러 오류 (3 개가 있어야 함)를 수정 _documentNavigator.SelectSingleNode하여 _documentNavigator.부분 을 참조 하고 제거하여 SelectSingleNode위에서 정의한 새 메서드를 호출합니다 .

이 마지막 단계는 기본 프로젝트가 아닌 여러 XML 문서에서 도움말 텍스트를 찾을 수 있도록 문서 공급자를 수정하는 것입니다.

이제 도움말 문서를 검토 할 때 관련 프로젝트에있는 유형의 XML 문서가 포함됩니다.


7
훌륭한 대답입니다. 실제로 생성자가 문자열 배열 인 public XmlDocumentationProvider (string appDataPath)를 받아들이고 문서 공급자에서이 목록을 열거하는 것이 조금 더 쉽다고 생각합니다.
Captain John

14
환상적입니다. 이것은 제가 찾던 것이 었습니다 !! (나와 같은) xml 문서 파일의 이름 / 수를 항상 알지 못할 경우 var files...줄을 바꾸는 것이 var files = Directory.GetFiles(documentPath, "*.xml");좋습니다. 필요에 따라 추가 필터링을 수행 할 수도 있습니다.
sǝɯɐs

2
@Leandro, 답변을 개선해 주셔서 감사합니다! :) 도움이되었다 니 다행입니다.
Kirk Woll 2014

5
나는이 설명 및 정답을 +10 것입니다 수 있다면
마르크 반 Straten에게

2
여기에 다른 일부에 내 수정 사항을 추가하고 싶습니다. ... \ 표기법을 사용하여 루트 프로젝트 App_Data \ documentation 폴더에 xml 파일을 생성했습니다. 그런 다음 @ sǝɯɐſ 방법을 사용하여 해당 디렉토리에서 모든 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));
    }
}

... HelpPageConfig원하는 XML 문서에 대한 경로를 사용하여 활성화하십시오 .

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
이것은 훌륭하게 작동합니다. 게시 해 주셔서 감사합니다. 이것을 사용하는 모든 사람을 절약하려면 위에서 kirk의 승인 된 답변의 처음 두 단계를 수행해야합니다. 즉, 1) 하위 프로젝트에 대한 XML 문서 활성화 및 2)이 XML 파일을 복사하도록 Web API 프로젝트의 빌드 후 이벤트를 수정합니다. App_Data 폴더.
tomRedox

1
이 줄은 다음과 같습니다. config.SetDocumentationProvider (new MultiXmlDocumentationProvider (HttpContext.Current.Server.MapPath ( "~ / App_Data / [원본 웹 API 프로젝트의 xml 파일 이름, 기본값은 XmlDocument] .xml"), HttpContext.Current.Server.MapPath ( "~ / App_Data / [SubProject xml 파일 이름] .xml")));
tomRedox

단계를 따랐지만 작동하지 않았습니다. (. 오류가 없어서 무엇이 잘못되었는지 확실하지 않습니다. 여전히 api 문서 만 표시되고 추가 프로젝트 문서는 표시되지 않습니다. 또한 수락 된 답변의 단계를 시도했는데 동일한 결과입니다. . 특히 확인해야 할 사항이 있습니까?
stt106

어떤 이유로 VS에서 시작하기 프로젝트 템플릿과 함께 제공되는 기본 GET api / me가 여전히 표시됩니다.
John Zabroski



0

이 문제를 해결하는 가장 쉬운 방법은 배포 한 서버에 App_Code 폴더를 만드는 것입니다. 그런 다음 bin 폴더에있는 XmlDocument.xml을 로컬로 App_Code 폴더에 복사합니다.


제안 해 주셔서 감사합니다 !! 그런 유용한 답변에 대해 더 이상 -1이 아닙니다. 예, Azure Cloud App Service에 배포하는 경우 여러 * .xml 배포에서 많은 문제가 발생하므로 예를 들어 Swagger에 사용할 수 있도록 만드는 것은 정말 까다로울 수 있습니다. 그러나 xmldoc 파일은 리소스와 거의 유사하므로 다른 표준 ASP.Net 서버 쪽 폴더 인 App_GlobalResources를 선택하는 것이 좋습니다. 내 프로젝트에 여전히 App_Code 폴더가 없었고 어떤 표준 폴더를 만들지 중요하지 않았기 때문에 특히 그렇습니다.
moudrick 16.11.

다음 표준 폴더가 나를 위해 일했습니다. App_Code-기본 설정에서 클라이언트에서 볼 수 없음 App_GlobalResources-기본 설정에서 클라이언트에서 볼 수 없음 App_LocalResources-기본 설정에서 클라이언트에서 볼 수 없음
moudrick

또한 저에게 적합하지 않은 각 표준 폴더의 문제를 나열하겠습니다. bin-주 어셈블리 용 * .xml 만 App_Data로 배포됩니다. 가장 실용적인 설정은 클라우드에 배포 할 때이 폴더의 모든 항목을 건너 뛰는 것입니다
moudrick

관심있는 사람이 위의 모든 고려 사항을 반영하기 위해이 답변을 편집 할 수 있습니까?
moudrick 16.11.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.