有个比较怪的需求,就是把我现在所有能够访问的接口都展示出来
比如我有一个 home 的控制器,我需要将此控制器的提供的接口获取到,成为一个List,然后还要获取到接口的注释一并返回
像这样
api: api/home/index
summary: 首页接口
controller: home
controllerSummary: 首页控制器
但是summary在编译时是不会被编译的,所以获取到这个比较困难
具体解决方法如下
生成注释的XML文档
右键项目,点击属性,新建一个xml 文件用于存放 注释信息(与swagger 获取注释信息一样的)
生成项目后就能看到,所有注释都被放在了这个文件中
获取所有的API 列表
使用 此接口 IActionDescriptorCollectionProvider
private IActionDescriptorCollectionProvider _actionProvider;
public ResService(IActionDescriptorCollectionProvider actionProvider)
{
_actionProvider = actionProvider;
}
public async Task<dynamic> GetPortResListAsync()
{
var list = new List<Dictionary<string, object>>();
//获取所有的api 接口
var actionDescs = _actionProvider.ActionDescriptors.Items.Cast<ControllerActionDescriptor>().Select(x => new
{
DisplayName = x.DisplayName.TrimEnd("(NK.WebApi)".ToCharArray()).Trim(), //这里是跟XML文件做匹配的关键字段,需要将末尾括号里的内容移除掉
RouteTemplate = x.AttributeRouteInfo.Template,//接口名称
Controller = x.ControllerName,//控制器名
ContrillereFullName = x.ControllerTypeInfo.FullName//控制器全路径
}).ToList();
// 指定 XML 文件路径
string filePath = "./NK.WebApi.xml";
try
{
// 创建 XmlReaderSettings 对象并禁用 DTD 处理(可选)
var readerSettings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Ignore
};
// 使用 XmlReader 加载 XML 文件
using (XmlReader xmlReader = XmlReader.Create(filePath, readerSettings))
{
// 创建 XmlDocument 对象并加载 XML 数据
var xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
//获取所有的注释信息
var xmlItem = xmlDoc.ChildNodes.Item(1).ChildNodes.Item(1).ChildNodes;
//循环所有接口
foreach (var node in actionDescs)
{
Dictionary<string, object> data = new Dictionary<string, object>();
XmlNode ApiNode = null;
string summary = string.Empty;//接口注释
string controllerSummary =string.Empty;//控制器注释
foreach (XmlNode xmlNode in xmlItem)
{
//拿到XML 中 匹配字段的属性
var tempName = xmlNode.Attributes[0].InnerText.TrimStart("M:".ToCharArray()).TrimStart("P:".ToCharArray()).TrimStart("T:".ToCharArray());
//去除末尾括号以及括号中的内容
tempName = Regex.Replace(tempName, @"\([^()]*\)$", "");
if (node.DisplayName== tempName)
{
//匹配成功后,获取对应的注释信息
summary = xmlNode.ChildNodes.Item(0).InnerText.Trim();
ApiNode = xmlNode;
break;
}
}
//获取控制器的注释
foreach (XmlNode xmlNode in xmlItem)
{
//拿到XML 中 匹配字段的属性
var tempName = xmlNode.Attributes[0].InnerText.TrimStart("M:".ToCharArray()).TrimStart("P:".ToCharArray()).TrimStart("T:".ToCharArray());
//去除末尾括号以及括号中的内容
tempName = Regex.Replace(tempName, @"\([^()]*\)$", "");
//与控制器的fullName 做匹配
if (node.ContrillereFullName == tempName)
{
//匹配成功后,获取对应的注释信息
controllerSummary = xmlNode.ChildNodes.Item(0).InnerText.Trim();
break;
}
}
//成功匹配则加入列表并返回
if (!ApiNode.IsNullOrEmpty())
{
data.Add("API", node.RouteTemplate);
data.Add("Summary", summary);
data.Add("Controller", node.Controller);
data.Add("ControllerSummary", controllerSummary);
list.Add(data);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"XML 加载错误:{ex.Message}");
}
return list;
}
返回的数据就是这样的,注释变了之后,此接口的数据也会及时变