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

.NET项目Swagger无法正确显示1.0版本接口信息求助

问题排查:Swagger无法显示API 1.0版本接口信息

问题描述

C# WebAPI项目已定义API版本1.0、1.1和1.2-rc1,所有版本接口均可正常调用,但Swagger文档仅能正确展示1.1和1.2-rc1版本的接口,1.0版本页面提示**"No operations defined in spec!"**。

核心原因

当前Swagger配置仅手动添加了各版本的Swagger文档元信息,但未正确配置接口与对应版本文档的关联规则;同时手动维护版本列表的方式无法与Asp.Versioning自动生成的API版本描述完全匹配,导致Swagger无法识别1.0版本的接口归属。

解决方案

1. 依赖自动生成的API版本描述

通过IApiVersionDescriptionProvider获取Asp.Versioning自动生成的版本信息,替代手动维护版本列表的方式,确保版本名称与接口分组完全一致。

2. 配置接口与Swagger文档的关联规则

添加DocInclusionPredicate,明确每个接口对应的Swagger文档分组,让Swagger能正确将接口归类到对应版本的文档中。

3. 规范API版本定义(可选但推荐)

将版本定义从字符串改为ApiVersion对象,避免字符串解析误差,提升版本管理的严谨性。

代码修改示例

Program.cs 修改

using Asp.Versioning;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;

namespace TestSwagger
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            builder.Services.AddControllers();
            builder.Services.AddEndpointsApiExplorer();

            builder.Services.AddApiVersioning(options =>
            {
                options.AssumeDefaultVersionWhenUnspecified = false;
                options.ReportApiVersions = true;
                options.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader());
            })
            .AddApiExplorer(options =>
            {
                options.GroupNameFormat = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
            });

            // 注入IApiVersionDescriptionProvider用于后续配置
            builder.Services.AddSwaggerGen((options, sp) =>
            {
                var apiVersionDescriptionProvider = sp.GetRequiredService<IApiVersionDescriptionProvider>();
                
                // 遍历自动生成的版本描述创建Swagger文档
                foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
                {
                    options.SwaggerDoc(
                        description.GroupName,
                        new OpenApiInfo
                        {
                            Version = description.ApiVersion.ToString(),
                            Title = $"A Test API {description.GroupName}",
                            Description = "An dotnet core web api test ",
                            TermsOfService = new Uri("https://localhost/terms"),
                            Contact = new OpenApiContact { Name = "Contact", Url = new Uri("http://localhost/contact") },
                            License = new OpenApiLicense { Name = "License", Url = new Uri("http://localhost/license") }
                        });
                }

                // 配置接口与Swagger文档的关联规则
                options.DocInclusionPredicate((docName, apiDesc) =>
                {
                    var actionApiVersions = apiDesc.ActionDescriptor.EndpointMetadata
                        .OfType<ApiVersionAttribute>()
                        .SelectMany(attr => attr.Versions);

                    return actionApiVersions.Any(v => $"v{v.ToString()}" == docName);
                });
            });

            var app = builder.Build();

            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                var apiVersionDescriptionProvider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
                
                app.UseSwaggerUI(action =>
                {
                    // 使用自动生成的版本描述添加Swagger端点
                    foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
                    {
                        action.SwaggerEndpoint(
                            $"/swagger/{description.GroupName}/swagger.json",
                            $"A small test API {description.GroupName}");
                    }
                    action.DisplayRequestDuration();
                });
            }

            app.UseHttpsRedirection();
            app.UseAuthorization();
            app.MapControllers();
            app.Run();
        }
    }
}

DefinedApiVersion.cs 修改(可选)

using Asp.Versioning;
using System.Reflection;

namespace TestSwagger
{
    public static class DefinedApiVersion
    {
        public static readonly ApiVersion V1_0 = new ApiVersion(1, 0);
        public static readonly ApiVersion V1_1 = new ApiVersion(1, 1);
        public static readonly ApiVersion V1_2 = new ApiVersion(1, 2, "rc1");

        public static List<string> GetAllApiVersionValues()
        {
            return typeof(DefinedApiVersion)
                .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
                .Where(x => x.IsLiteral && x.FieldType == typeof(ApiVersion))
                .Select(x => ((ApiVersion)x.GetRawConstantValue()).ToString())
                .ToList();
        }
    }
}

TestController.cs 修改(对应上面的版本定义)

using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;

namespace TestSwagger.Controllers
{
    [ApiVersion(DefinedApiVersion.V1_0)]
    [ApiVersion(DefinedApiVersion.V1_1)]
    [ApiVersion(DefinedApiVersion.V1_2)]
    [ApiController]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class TestController : ControllerBase
    {
        [MapToApiVersion(DefinedApiVersion.V1_0)]
        [MapToApiVersion(DefinedApiVersion.V1_1)]
        [MapToApiVersion(DefinedApiVersion.V1_2)]
        [HttpGet("Method1")]
        public string Method1() => "1";

        [MapToApiVersion(DefinedApiVersion.V1_1)]
        [MapToApiVersion(DefinedApiVersion.V1_2)]
        [HttpGet("Method2")]
        public string Method2() => "2";

        [MapToApiVersion(DefinedApiVersion.V1_2)]
        [HttpGet("Method3")]
        public string Method3() => "3";
    }
}

验证

修改后启动项目,Swagger页面中1.0版本应能正常显示Method1接口,与实际调用结果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 13:39:56