ASP.NET Core API:如何在SwaggerUI中显示XML remarks内容
解决Swashbuckle.AspNetCore 6.5.0中Remarks未渲染的问题
完全可以通过**架构过滤器(ISchemaFilter)处理实体类、属性的Remarks,通过文档过滤器(IDocumentFilter)**处理参数类的Remarks,将这些内容追加到SwaggerUI的对应描述中。以下是具体实现步骤:
一、先启用项目Xml注释
在项目属性的「生成」选项卡中,勾选「XML文档文件」,指定生成路径(默认会输出到项目编译目录),确保类、属性、参数的<remarks>注释能被提取。
二、用架构过滤器处理实体类与属性的Remarks
这个过滤器会拦截Schema生成过程,从Xml注释中提取类和属性的Remarks,追加到对应描述里。
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; using System.Xml.Linq; public class XmlRemarksSchemaFilter : ISchemaFilter { private readonly XDocument _xmlDoc; public XmlRemarksSchemaFilter(string xmlDocPath) { if (File.Exists(xmlDocPath)) { _xmlDoc = XDocument.Load(xmlDocPath); } } public void Apply(OpenApiSchema schema, SchemaFilterContext context) { // 处理实体类的Remarks var type = context.Type; var typeCommentNode = _xmlDoc?.Descendants("member") .FirstOrDefault(m => m.Attribute("name")?.Value == $"T:{type.FullName}"); if (typeCommentNode != null) { var remarks = typeCommentNode.Element("remarks")?.Value.Trim(); if (!string.IsNullOrEmpty(remarks)) { schema.Description = string.IsNullOrEmpty(schema.Description) ? $"**类说明:** {remarks}" : $"{schema.Description}\n\n**类说明:** {remarks}"; } } // 处理实体属性的Remarks foreach (var prop in schema.Properties) { var propInfo = type.GetProperty(prop.Key); if (propInfo == null) continue; var propCommentNode = _xmlDoc?.Descendants("member") .FirstOrDefault(m => m.Attribute("name")?.Value == $"P:{type.FullName}.{propInfo.Name}"); if (propCommentNode != null) { var remarks = propCommentNode.Element("remarks")?.Value.Trim(); if (!string.IsNullOrEmpty(remarks)) { prop.Value.Description = string.IsNullOrEmpty(prop.Value.Description) ? $"**属性说明:** {remarks}" : $"{prop.Value.Description}\n\n**属性说明:** {remarks}"; } } } } }
三、用文档过滤器处理参数类的Remarks
这个过滤器会遍历OpenApi文档中的所有参数,找到参数对应的类,提取其Remarks追加到参数描述中。
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; using System.Xml.Linq; public class XmlRemarksDocumentFilter : IDocumentFilter { private readonly XDocument _xmlDoc; public XmlRemarksDocumentFilter(string xmlDocPath) { if (File.Exists(xmlDocPath)) { _xmlDoc = XDocument.Load(xmlDocPath); } } public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { foreach (var pathItem in swaggerDoc.Paths.Values) { foreach (var operation in pathItem.Operations.Values) { foreach (var parameter in operation.Parameters) { // 匹配参数对应的类型 var paramDesc = context.ApiDescriptions .FirstOrDefault(d => d.HttpMethod == operation.Method.ToString() && d.RelativePath == pathItem.Path) ?.ParameterDescriptions .FirstOrDefault(p => p.Name == parameter.Name); if (paramDesc?.Type == null) continue; // 提取参数类的Remarks var typeCommentNode = _xmlDoc?.Descendants("member") .FirstOrDefault(m => m.Attribute("name")?.Value == $"T:{paramDesc.Type.FullName}"); if (typeCommentNode != null) { var remarks = typeCommentNode.Element("remarks")?.Value.Trim(); if (!string.IsNullOrEmpty(remarks)) { parameter.Description = string.IsNullOrEmpty(parameter.Description) ? $"**参数类说明:** {remarks}" : $"{parameter.Description}\n\n**参数类说明:** {remarks}"; } } } } } } }
四、注册过滤器到Swagger配置
在Program.cs(或Startup.cs)中,将两个过滤器注册到Swagger生成器,并传入Xml文档路径:
var xmlDocPath = Path.Combine(AppContext.BaseDirectory, "YourProjectName.xml"); builder.Services.AddSwaggerGen(c => { if (File.Exists(xmlDocPath)) { // 加载基础Xml注释 c.IncludeXmlComments(xmlDocPath); // 注册架构过滤器 c.SchemaFilter<XmlRemarksSchemaFilter>(xmlDocPath); // 注册文档过滤器 c.DocumentFilter<XmlRemarksDocumentFilter>(xmlDocPath); } });
五、效果验证
以你提供的Customer和QueryOptions类为例,配置完成后重启项目,打开SwaggerUI就能看到:
Customer实体的类Remarks会显示在Schema描述区域- 每个属性的Remarks会追加到对应属性的描述末尾
QueryOptions作为接口参数时,其类Remarks会显示在参数描述中
内容的提问来源于stack exchange,提问作者Jason Butera
相关产品推荐
相关产品推荐

