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.