1. 首页>
  2. 技术文章>
  3. donet mvc api2生成的api接口文档没有action的描述

donet mvc api2生成的api接口文档没有action的描述

5/29/17 8:38:59 AM 浏览 1506 评论 0

web api2 asp.net web api asp.net

有一个web api2的项目,用vs2017的时候,自动生成的api帮助文档,没有自动生成control的action方法的summary,需要做下面两步:

1) 项目属性 > 生成 > 输出 ,勾选“XML 文档文件”,输入“App_Data\XmlDocument.xml”

2) 不要注释掉下面的代码:

//// Uncomment the following to use the documentation from XML documentation file.
config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));

这样处理之后,虽然action已经根据summary生成API说明了,但一些实体还不行,因为实体我们是放在另一个类库中,所以还需要像上面1步骤一样,生成一个xml文件,然后需要修改HelpPageConfig:

config.SetDocumentationProvider(

    new MultipleXmlDocumentationProvider(

     HttpContext.Current.Server.MapPath("~/bin/MyCode.Domain.xml"),

     HttpContext.Current.Server.MapPath("~/bin/MyCode.WebApi.xml")

    )

   );

而这个MultipleXmlDocumentationProvider我从网上下载了一个,出处已经忘记了,代码如下:

using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Web.Http.Controllers;
using System.Web.Http.Description;
using System.Xml.XPath;
using Wolf.Project.WebApi.Areas.HelpPage.ModelDescriptions;
using System.Collections.Generic;
using System.IO;
namespace Wolf.Project.WebApi.Areas.HelpPage
{
 public class MultipleXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
 {
  private IList<XPathNavigator> _documentNavigators;
  private const string TypeExpression = "/doc/members/member[@name='T:{0}']";
  private const string MethodExpression = "/doc/members/member[@name='M:{0}']";
  private const string PropertyExpression = "/doc/members/member[@name='P:{0}']";
  private const string FieldExpression = "/doc/members/member[@name='F:{0}']";
  private const string ParameterExpression = "param[@name='{0}']";
  /// <summary>
  /// Initializes a new instance of the <see cref="XmlDocumentationProvider"/> class.
  /// </summary>
  /// <param name="documentPaths">List of physical paths to XML documents.</param>
  public MultipleXmlDocumentationProvider(params string[] documentPaths)
  {
   if (!documentPaths.Any())
   {
    throw new ArgumentNullException("documentPaths");
   }
   //读取全部XML文档
   var documents = documentPaths.Where(p => File.Exists(p)).ToList();
   _documentNavigators = documents.Select(p => new XPathDocument(p).CreateNavigator()).ToList();
  }
  public string GetDocumentation(HttpControllerDescriptor controllerDescriptor)
  {
   XPathNavigator typeNode = GetTypeNode(controllerDescriptor.ControllerType);
   return GetTagValue(typeNode, "summary");
  }
  public virtual string GetDocumentation(HttpActionDescriptor actionDescriptor)
  {
   XPathNavigator methodNode = GetMethodNode(actionDescriptor);
   return GetTagValue(methodNode, "summary");
  }
  public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
  {
   ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
   if (reflectedParameterDescriptor != null)
   {
    XPathNavigator methodNode = GetMethodNode(reflectedParameterDescriptor.ActionDescriptor);
    if (methodNode != null)
    {
     string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
     XPathNavigator parameterNode = methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, ParameterExpression, parameterName));
     if (parameterNode != null)
     {
      return parameterNode.Value.Trim();
     }
    }
   }
   return null;
  }
  public string GetResponseDocumentation(HttpActionDescriptor actionDescriptor)
  {
   XPathNavigator methodNode = GetMethodNode(actionDescriptor);
   return GetTagValue(methodNode, "returns");
  }
  public string GetDocumentation(MemberInfo member)
  {
   string memberName = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", GetTypeName(member.DeclaringType), member.Name);
   string expression = member.MemberType == MemberTypes.Field ? FieldExpression : PropertyExpression;
   string selectExpression = String.Format(CultureInfo.InvariantCulture, expression, memberName);
   var propertyNode = _documentNavigators.Select(n => n.SelectSingleNode(selectExpression)).FirstOrDefault(n => n != null);
   return GetTagValue(propertyNode, "summary");
  }
  public string GetDocumentation(Type type)
  {
   XPathNavigator typeNode = GetTypeNode(type);
   return GetTagValue(typeNode, "summary");
  }
  private XPathNavigator GetMethodNode(HttpActionDescriptor actionDescriptor)
  {
   ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
   if (reflectedActionDescriptor != null)
   {
    string selectExpression = String.Format(CultureInfo.InvariantCulture, MethodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo));
    return _documentNavigators.Select(n => n.SelectSingleNode(selectExpression)).FirstOrDefault(n => n != null);
   }
   return null;
  }
  private static string GetMemberName(MethodInfo method)
  {
   string name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", GetTypeName(method.DeclaringType), method.Name);
   ParameterInfo[] parameters = 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 GetTagValue(XPathNavigator parentNode, string tagName)
  {
   if (parentNode != null)
   {
    XPathNavigator node = parentNode.SelectSingleNode(tagName);
    if (node != null)
    {
     return node.Value.Trim();
    }
   }
   return null;
  }
  private XPathNavigator GetTypeNode(Type type)
  {
   string controllerTypeName = GetTypeName(type);
   string selectExpression = String.Format(CultureInfo.InvariantCulture, TypeExpression, controllerTypeName);
   return _documentNavigators.Select(n => n.SelectSingleNode(selectExpression)).FirstOrDefault(n => n != null);
  }
  private static string GetTypeName(Type type)
  {
   string name = type.FullName;
   if (type.IsGenericType)
   {
    // Format the generic type name to something like: Generic{System.Int32,System.String}
    Type genericType = type.GetGenericTypeDefinition();
    Type[] genericArguments = type.GetGenericArguments();
    string genericTypeName = genericType.FullName;
    // Trim the generic parameter counts from the name
    genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf('`'));
    string[] argumentTypeNames = genericArguments.Select(t => GetTypeName(t)).ToArray();
    name = String.Format(CultureInfo.InvariantCulture, "{0}{{{1}}}", genericTypeName, String.Join(",", argumentTypeNames));
   }
   if (type.IsNested)
   {
    // Changing the nested type name from OuterType+InnerType to OuterType.InnerType to match the XML documentation syntax.
    name = name.Replace("+", ".");
   }
   return name;
  }
 }
}


网友讨论