You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swagger中处理<see /> XML文档标签?

我刚好处理过类似的场景,给你几个实用的解决方案,从根本上解决Swagger不识别<see/>标签的问题,顺便解释下你之前手动修改XML没生效的原因:

方案一:用Swagger自定义过滤器自动处理<see/>标签(推荐)

与其手动修改XML文件,不如让Swagger在生成文档时自动解析替换<see/>标签。你可以实现Swashbuckle的IDocumentFilter,遍历所有API注释、模型描述,把<see cref="XXX"/>替换成友好的显示文本(比如用反引号包裹成代码样式)。

举个具体的实现例子:

  1. 创建一个过滤器类:
public class SeeTagDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // 处理所有路径的API操作
        foreach (var path in swaggerDoc.Paths.Values)
        {
            ProcessOperation(path.Get);
            ProcessOperation(path.Post);
            ProcessOperation(path.Put);
            ProcessOperation(path.Delete);
            // 按需添加其他HTTP方法
        }

        // 处理模型的描述
        foreach (var schema in swaggerDoc.Components.Schemas.Values)
        {
            if (!string.IsNullOrEmpty(schema.Description))
            {
                schema.Description = ReplaceSeeTags(schema.Description);
            }
        }
    }

    private void ProcessOperation(OpenApiOperation operation)
    {
        if (operation == null) return;

        operation.Summary = ReplaceSeeTags(operation.Summary);
        operation.Description = ReplaceSeeTags(operation.Description);

        // 处理参数描述
        foreach (var param in operation.Parameters)
        {
            param.Description = ReplaceSeeTags(param.Description);
        }

        // 处理响应描述
        foreach (var response in operation.Responses.Values)
        {
            response.Description = ReplaceSeeTags(response.Description);
        }
    }

    private string ReplaceSeeTags(string input)
    {
        if (string.IsNullOrEmpty(input)) return input;

        // 正则匹配所有<see cref="XXX"/>标签
        var regex = new Regex(@"<see\s+cref=""([^""]+)""\s*/>", RegexOptions.IgnoreCase);
        return regex.Replace(input, match =>
        {
            var crefValue = match.Groups[1].Value;
            // 处理cref的前缀(比如T:表示类型,M:表示方法),只保留名称部分
            var displayName = crefValue.Split(':').Last();
            // 用反引号包裹,让Swagger显示为代码样式
            return $"`{displayName}`";
        });
    }
}
  1. 在Swagger注册时添加这个过滤器(.NET 6+ 为例,Program.cs中):
builder.Services.AddSwaggerGen(c =>
{
    // 加载你的XML注释文件
    var xmlFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlFilePath = Path.Combine(AppContext.BaseDirectory, xmlFileName);
    c.IncludeXmlComments(xmlFilePath);

    // 注册自定义过滤器
    c.DocumentFilter<SeeTagDocumentFilter>();
});

这个方案的好处是:不需要修改原始XML文件,避免编译覆盖的问题,而且所有注释处理都集成在Swagger的生成流程中,重启应用后立即生效。

方案二:解决手动修改XML后Swagger不生效的问题

如果你还是想通过修改XML文件来处理,先搞清楚之前失败的原因:

  • 编译覆盖:如果你的XML是项目编译时自动生成的(项目属性→生成→勾选"XML文档文件"),那么每次编译都会重新生成XML,覆盖你手动修改的内容。解决办法是用Post-build事件自动替换:
    打开项目属性→生成事件→Post-build事件命令行,添加:
    (Get-Content "$(TargetDir)$(TargetName).xml") -replace '<see cref="([^"]+)"/>', '`$1`' | Set-Content "$(TargetDir)$(TargetName).xml"
    
    这样每次编译完成后,自动替换XML中的<see/>标签,不会被后续编译覆盖。
  • 未重启应用:Swashbuckle在应用启动时加载XML文件,修改XML后必须重启应用才能让Swagger重新读取。
  • 缓存问题:如果你的应用启用了输出缓存,或者Swashbuckle有缓存,需要清除相关缓存或者重启应用。

额外优化

如果需要更精细的处理(比如只显示类名而不是完整命名空间),可以修改过滤器中的ReplaceSeeTags方法,比如:

var displayName = crefValue.Split(':').Last().Split('.').Last();

这样T:MyApp.Models.MyObject会被替换成MyObject。

内容的提问来源于stack exchange,提问作者ataraxia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:30:33