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 就是其中之一:

使用该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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏冷冷

Spring Cloud Gateway 数据库存储路由信息的扩展方案

GatewayControllerEndpoint 基于actuate端点的默认实现,支持JVM 级别的动态路由,不能序列化存储

4172
来自专栏noteless

springmvc 项目完整示例02 项目创建-eclipse创建动态web项目 配置文件 junit单元测试

spring原理案例-基本项目搭建 01 spring framework 下载 官网下载spring jar包

1882
来自专栏张善友的专栏

SignalR QuickStart

SignalR 是一个集成的客户端与服务器库,基于浏览器的客户端和基于 ASP.NET 的服务器组件可以借助它来进行双向多步对话。 换句话说,该对话可不受限制地...

2246
来自专栏软件工程师成长笔记

CXF实现webService服务

Web Service也叫XML Web Service,WebService是一种可以接收从Internet或者Internet上的其它系统中传递过来的请求,...

2043
来自专栏本立2道生

Win32对话框程序(1)

之前学C语言是一直都是在控制台下面操作的,面对的都是黑框框,严重的打击了学习的兴趣。后来在TC下进行C语言课程设计,做了图形界面编程,但都是点线面画的…… 

1771
来自专栏程序员互动联盟

Windows SDK编程基本框架

在Windows平台下,最常见最流行的编程就是MFC编程了,在网上可以搜索出大把的MFC编程相关的文章,今天我们来讨论另外一种windows下的编程模式,即W...

33013
来自专栏智能大石头

线程池ThreadPool及Task调度机制分析

近1年,偶尔发生应用系统启动时某些操作超时的问题,特别在使用4核心Surface以后。笔记本和台式机比较少遇到,服务器则基本上没有遇到过。

1180
来自专栏木宛城主

ASP.NET MVC随想录——漫谈OWIN

什么是OWIN OWIN是Open Web Server Interface for .NET的首字母缩写,他的定义如下: OWIN在.NET Web Ser...

22211
来自专栏王大锤

再谈RunLoop

2934
来自专栏高性能服务器开发

关于windows完成端口(IOCP)的一些理解(五)

系列目录 关于windows完成端口(IOCP)的一些理解(一) 关于windows完成端口(IOCP)的一些理解(二) 关于windows完成端口(IOCP)...

47411

扫码关注云+社区

领取腾讯云代金券