1.新建ASP.NET 項目,模板選擇如圖 2.選擇Web API,並選擇不進行身份驗證方式 成功後我們看到這個結果。 至於其它三種身份驗證方式,不太適合我的使用。而且這種方式也可以在代碼里去實現身份驗證,比較符合已有資料庫的情況,這裡不寫。 3.給項目進行配置修改 3.1 修改對應項目生成路徑。 ...
1.新建ASP.NET 項目,模板選擇如圖
2.選擇Web API,並選擇不進行身份驗證方式
成功後我們看到這個結果。
至於其它三種身份驗證方式,不太適合我的使用。而且這種方式也可以在代碼里去實現身份驗證,比較符合已有資料庫的情況,這裡不寫。
3.給項目進行配置修改
3.1 修改對應項目生成路徑。
這是單項目結構的,如果有多個項目並且有引用,把其它項目生成XML的地址改為介面項目的地址,當然也可以生成後再拷貝過去。
3.2修改WebAPITest\Areas\HelpPage\App_Start\HelpPageConfig.cs裡面的代碼。
反註釋
config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
裡面的文檔改成我們上面生成的文檔名稱,打開help介面就能看到註釋了。
如果是引用了多個項目,就麻煩點。
先把剛剛這句改一下
config.SetDocumentationProvider(new XmlDocumentationProvider( HttpContext.Current.Server.MapPath("~/App_Data")));
看見XmlDocumentationProvider這個類沒有?轉到定義過去看看
/// <summary> /// A custom <see cref="IDocumentationProvider"/> that reads the API documentation from an XML documentation file. /// </summary> public class XmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider { 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 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 XmlDocumentationProvider(string documentPath) { if (documentPath == null) { throw new ArgumentNullException("documentPath"); } XPathDocument xpath = new XPathDocument(documentPath); _documentNavigator = 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 = _documentNavigator.SelectSingleNode(selectExpression); 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 _documentNavigator.SelectSingleNode(selectExpression); } 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 _documentNavigator.SelectSingleNode(selectExpression); } 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; } }
我們把它改下
public class XmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider { // private XPathNavigator _documentNavigator; private List<XPathNavigator> _documentNavigators = new List<XPathNavigator>(); 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 XmlDocumentationProvider(string documentPath) //{ // if (documentPath == null) // { // throw new ArgumentNullException("documentPath"); // } // XPathDocument xpath = new XPathDocument(documentPath); // _documentNavigator = xpath.CreateNavigator(); //} /// <summary> /// Initializes a new instance of the <see cref="XmlDocumentationProvider"/> class. /// </summary> /// <param name="appDataPath">The physical path to XML document.</param> public XmlDocumentationProvider(string appDataPath) { if (appDataPath == null) { throw new ArgumentNullException("appDataPath"); } var files = new[] { "AuthSystem.xml", "AuthSystem.SQL.xml", "AuthSystem.Common.XML" }; foreach (var file in files) { XPathDocument xpath = new XPathDocument(Path.Combine(appDataPath, file)); _documentNavigators.Add(xpath.CreateNavigator()); } } private XPathNavigator SelectSingleNode(string selectExpression) { foreach (var navigator in _documentNavigators) { var propertyNode = navigator.SelectSingleNode(selectExpression); if (propertyNode != null) return propertyNode; } return null; } 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 = SelectSingleNode(selectExpression); 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 SelectSingleNode(selectExpression); } 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 SelectSingleNode(selectExpression); } 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; } }
原理就是從只讀一個文檔改成讀取多個文檔。這樣就能在help中看到我們寫的註釋(summary)了。
效果圖就不貼了,免得浪費大家流量哈哈。