ASP.NET Web API RC版本新特性:Web API的幫助文檔制作


InfoQ上有一篇文章是 使用IAPIExplorer列舉ASP.NET Web API,文章針對的版本是ASP.NET Web API Beta版本寫,IAPIExplorer已經包含在RC版本里了,而且發現ASP.NET Web API的HttpConfiguration 的RC版本比Beta版本多了一個屬性:

public DefaultServices Services { get; internal set; }

Debug進去可以看到默認有18個服務,IAPIExplorer 就是其中之一:

image

使用該API可以完成的工作有:

  • 產生文檔
  • 創建機器可讀的元數據
  • 創建一個測試客戶端

微軟員工Yao發表了兩篇文章(ASP.NET Web API: Introducing IApiExplorer/ApiExplorerASP.NET Web API: Generating a Web API help page using ApiExplorer)分別用於展示如何使用API打印Web API列表以及如何創建幫助文檔。

所以我們創建幫助文檔主要就是參照這篇文章就可以了ASP.NET Web API: Generating a Web API help page using ApiExplorer;作者在文章里面已經實現了一個IDocumentationProvider,它是通過代碼的注釋XML文檔去生成,這是一個非常好的實現了:

public class XmlCommentDocumentationProvider : IDocumentationProvider 
    {
        XPathNavigator _documentNavigator;
        private const string _methodExpression = "/doc/members/member[@name='M:{0}']";
        private static Regex nullableTypeNameRegex = new Regex(@"(.*\.Nullable)" + Regex.Escape("`1[[") + "([^,]*),.*");
        public XmlCommentDocumentationProvider(string documentPath)
        {
            XPathDocument xpath = new XPathDocument(documentPath);
            _documentNavigator = xpath.CreateNavigator();
        } 
        public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor) 
    {
        ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
            if (reflectedParameterDescriptor != null)
            { 
                XPathNavigator memberNode = GetMemberNode(reflectedParameterDescriptor.ActionDescriptor);
                if (memberNode != null)
                { 
                    string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
                    XPathNavigator parameterNode = memberNode.SelectSingleNode(string.Format("param[@name='{0}']", parameterName));
                    if (parameterNode != null)
                    { 
                        return parameterNode.Value.Trim();
                    } 
                } 
            }
            return "No Documentation Found.";
        } 
        public virtual string GetDocumentation(HttpActionDescriptor actionDescriptor)
        { 
            XPathNavigator memberNode = GetMemberNode(actionDescriptor);
            if (memberNode != null)
            { 
                XPathNavigator summaryNode = memberNode.SelectSingleNode("summary");
                if (summaryNode != null)
                { 
                    return summaryNode.Value.Trim();
                } 
            } 
            return "No Documentation Found.";
        } 
        private XPathNavigator GetMemberNode(HttpActionDescriptor actionDescriptor)
        {
            ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
            if (reflectedActionDescriptor != null)
            { 
                string selectExpression = string.Format(_methodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo));
                XPathNavigator node = _documentNavigator.SelectSingleNode(selectExpression);
                if (node != null)
                {
                    return node;
                } 
            } 
            return null;
        } 
        private static string GetMemberName(MethodInfo method)
        {
            string name = string.Format("{0}.{1}", method.DeclaringType.FullName, method.Name); 
            var parameters = method.GetParameters();
            if (parameters.Length != 0) 
            { 
                string[] parameterTypeNames = parameters.Select(param => ProcessTypeName(param.ParameterType.FullName)).ToArray();
                name += string.Format("({0})", string.Join(",", parameterTypeNames));
            }
            return name;
        } 
        private static string ProcessTypeName(string typeName) 
        {
            //handle nullable
            var result = nullableTypeNameRegex.Match(typeName);
            if (result.Success)
            {
                return string.Format("{0}{{{1}}}", result.Groups[1].Value, result.Groups[2].Value);
            } 
            return typeName;
        } 
    }

把XML 文檔的位置在Application_Start 中將IDocumentationProvider服務替換為我們的自定義服務。

var config = GlobalConfiguration.Configuration;
config.Services.Replace(typeof(IDocumentationProvider), new XmlCommentDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/MvcApplication2.XML")));

有個ApiExplorerSettingsAttribute 可以控制API是否在幫助頁面上出現:

/// <summary>
/// DELETE api/values/5
/// </summary>
/// <param name="id"></param> 
[ApiExplorerSettings(IgnoreApi = true)]
public void Delete(int id)
{
}

還可以控制整個ApiController 的文檔是否發布出來,只需要通過在類級別應用ApiExplorerSettingsAttribute

 [ApiExplorerSettings(IgnoreApi = true)]
 public class MySpecialController : ApiController

通過IAPIExplorer 這個API我們可以為我們的Web API 做出很棒的文檔了,而且這個接口的設計也是可擴展的。可以制作Web頁面也可以制作一個HelpController來做,推薦封裝成一個HelpController,這樣就可以適應WebAPi的Web Host或者是Self Host了。 

Part 1: Basic Help Page customizations

Changing the help page URI

Providing API documentations

Customizing the view

Part 2: Providing custom samples on the Help Page

Setting custom sample objects

Setting the samples when the action returns an HttpResponseMessage

Part 3: Advanced Help Page customizations

Adding additional information to the HelpPageApiModel

Creating new sample display templates

Making ASP.NET Web API Help Page work on self-hosted services

Extending Web API Help Page with information from attributes

Using curl to POST request into ASP.NET Web Api service


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM