标签:
原文:weiapi2.2 HelpPage自动生成接口说明文档和接口测试成果在开发Webapi项目时每写完一个要领时,是不是需要添加相应的成果说明和测试案例呢?为了更简单便利的写说明接口文档和接口测试HelpPage供给了一个便利的途径。
她的大抵道理是:在编译时会生成.dll措施集和.xml措施集说明文件,通过xml文件获取Controller名称、action名称、参数信息和备注信息等。这样接口说明文档就可以放到备注信息了,小我私家感受确实粗暴简单 。那接口测试在哪呢?这里用到nuget第三方措施包:webapitestclient
先上效果图吧!
案例是用VS2013创建的,已创建好HelpPage,但wepapi版本是1.0 。wepapi2成果增强,为更上节奏进入nuget升级。
其他的互相依赖项也会升级!
设置xml说明文档路径:
web项目属性设置生成的xml路径:
遗憾webapitestclient只撑持最低版本的HelpPage,升级webapi还得改削部分代码!说明:webapi1可以获取action的备注说明但不能获取controller的备注说明 webapi2是可以。
升级后,,XmlDocumentationProvider类需要会多出两个实现要领:Controller和action描述要领.
XmlDocumentationProvider.cspublic class XmlDocumentationProvider : IDocumentationProvider { private XPathNavigator _documentNavigator; private const string TypeExpression = "/doc/members/member[@name=‘T:{0}‘]"; private const string MethodExpression = "/doc/members/member[@name=‘M:{0}‘]"; private const string ParameterExpression = "param[@name=‘{0}‘]"; /// <summary> /// Initializes a new instance of the <see cref="XmlDocumentationProvider"/> class. /// </summary> /// <param>The physical path to XML document.</param> public XmlDocumentationProvider(string documentPath=http://www.mamicode.com/"") { //if (documentPath.IsNullOrWhiteSpace()) // documentPath = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["webApiDescription"]); if (documentPath == null) { throw new ArgumentNullException("documentPath"); } XPathDocument xpath = new XPathDocument(documentPath); _documentNavigator =http://www.mamicode.com/ xpath.CreateNavigator(); } private XPathNavigator GetTypeNode(Type type) { string controllerTypeName =http://www.mamicode.com/ GetTypeName(type); string selectExpression =http://www.mamicode.com/ String.Format(CultureInfo.InvariantCulture, TypeExpression, controllerTypeName); return _documentNavigator.SelectSingleNode(selectExpression); } private static string GetTagValue(XPathNavigator parentNode, string tagName) { if (parentNode != null) { XPathNavigator node =http://www.mamicode.com/ parentNode.SelectSingleNode(tagName); if (node != null) { return node.Value.Trim(); } } return null; } public virtual string GetDocumentation(HttpControllerDescriptor controllerDescriptor) { XPathNavigator typeNode =http://www.mamicode.com/ GetTypeNode(controllerDescriptor.ControllerType); return GetTagValue(typeNode, "summary"); } public virtual string GetDocumentation(HttpActionDescriptor actionDescriptor) { XPathNavigator methodNode =http://www.mamicode.com/ GetMethodNode(actionDescriptor); if (methodNode != null) { XPathNavigator summaryNode = methodNode.SelectSingleNode("summary"); if (summaryNode != null) { return summaryNode.Value.Trim(); } } return null; } public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor) { ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor; if (reflectedParameterDescriptor != null) { XPathNavigator methodNode =http://www.mamicode.com/ GetMethodNode(reflectedParameterDescriptor.ActionDescriptor); if (methodNode != null) { string parameterName =http://www.mamicode.com/ reflectedParameterDescriptor.ParameterInfo.Name; XPathNavigator parameterNode =http://www.mamicode.com/ methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, ParameterExpression, parameterName)); if (parameterNode != null) { return parameterNode.Value.Trim(); } } } return null; } public string GetResponseDocumentation(HttpActionDescriptor actionDescriptor) { XPathNavigator methodNode =http://www.mamicode.com/ GetMethodNode(actionDescriptor); return GetTagValue(methodNode, "returns"); } private XPathNavigator GetMethodNode(HttpActionDescriptor actionDescriptor) { ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor; if (reflectedActionDescriptor != null) { string selectExpression =http://www.mamicode.com/ String.Format(CultureInfo.InvariantCulture, MethodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo)); return _documentNavigator.SelectSingleNode(selectExpression); } return null; } private static string GetMemberName(MethodInfo method) { string name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", method.DeclaringType.FullName, method.Name); ParameterInfo[] parameters =http://www.mamicode.com/ method.GetParameters(); if (parameters.Length != 0) { string[] parameterTypeNames = parameters.Select(param => GetTypeName(param.ParameterType)).ToArray(); name += String.Format(CultureInfo.InvariantCulture, "({0})", String.Join(",", parameterTypeNames)); } return name; } private static string GetTypeName(Type type) { if (type.IsGenericType) { // Format the generic type name to something like: Generic{System.Int32,System.String} Type genericType =http://www.mamicode.com/ type.GetGenericTypeDefinition(); Type[] genericArguments =http://www.mamicode.com/ type.GetGenericArguments(); string typeName =http://www.mamicode.com/ genericType.FullName; // Trim the generic parameter counts from the name typeName = typeName.Substring(0, typeName.IndexOf(‘`‘)); string[] argumentTypeNames = genericArguments.Select(t => GetTypeName(t)).ToArray(); return String.Format(CultureInfo.InvariantCulture, "{0}{{{1}}}", typeName, String.Join(",", argumentTypeNames)); } return type.FullName; } }
改削获取Controller信息:
HelpController.cs
Index.cshtml
ApiGroup.cshtml