如何在外部库类的Web API中添加帮助

时间:2014-07-03 08:53:59

标签: asp.net-web-api2 asp.net-web-api-helppages

早上好,

我有一个由两个项目组成的解决方案。一个是类库,包含将在其他项目中使用的公共类。另一个是WebAPI 2.1项目。

我正在使用自动帮助页面生成器生成API的帮助文件,但我注意到,当它引用Common项目中的类时,它不使用摘要。

有没有办法让它这样做?我在线搜索但我找不到任何解决方案。我也尝试在Common项目中安装帮助页面生成器,但无济于事。

1 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,这只是因为文档提供程序只接受一个xml文档,该文档是从当前项目生成的文档(如果您按照您可能记得的说明添加:

config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/[YOUR XML DOCUMENT]"));

其他类及其元数据将添加到不同的xml文档中。我所做的是修改了xml文档提供程序以接受多个xml文档路径,并在每个文档中搜索与所查询的类相关的元数据。您需要从您引用的各个dll添加xml文档,但这肯定解决了我的问题。请参阅下文,了解XmlDocumentationProvider的变体:

public class XmlMultiDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
{
    private List<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 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="documentPath">The physical path to XML document.</param>
    public XmlMultiDocumentationProvider(params string[] documentPath)
    {
        if (documentPath == null)
        {
            throw new ArgumentNullException("documentPath");
        }
        _documentNavigator = new List<XPathNavigator>();
        foreach (string s in documentPath)
        {
            XPathDocument xpath = new XPathDocument(s);
            _documentNavigator.Add(xpath.CreateNavigator());
        }
    }

    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);
        XPathNavigator propertyNode = null;
        foreach(XPathNavigator navigator in _documentNavigator )
        {
          XPathNavigator temp  = navigator.SelectSingleNode(selectExpression);
          if (temp != null)
          {
              propertyNode = temp;
              break;
          }
        }
        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));
            foreach (XPathNavigator navigator in _documentNavigator)
            {
                XPathNavigator temp = navigator.SelectSingleNode(selectExpression);
                if (temp != null)
                {
                    return temp;
                }
            }

        }

        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);
        foreach (XPathNavigator navigator in _documentNavigator)
        {
            XPathNavigator temp = navigator.SelectSingleNode(selectExpression);
            if (temp != null)
            {
                return temp;
            }
        }
        return 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;
    }
}

您可以自行决定是仅仅使用整个课程。只需记住在HelpPageConfig中替换 - &gt; SetDocumentationProvider调用类名并添加各种xml文档的路径。