使用Swashbuckle / Swagger的C#版本WebApi文档

问题描述

我有一个C#WebApi,它具有多个版本,我想使用.NET Core 3.1使用Swashbuckle / Swagger进行记录。我已经尝试按照我可以找到的指南进行操作,但是我似乎丢失了一些东西,因为大张旗鼓地显示一个空列表,例如我的项目不包含API。

这是设置:

Startup.cs

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddApiVersioning(o => { });

            var apiExplorer = services.AddVersionedApiExplorer(options => {
                options.GroupNameFormat = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
            });

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1.0",new OpenApiInfo()
                {
                    Title = "My API v1.0",Version = "v1.0"
                });

                options.SwaggerDoc("v1.1",new OpenApiInfo()
                {
                    Title = "My API v1.1",Version = "v1.1"
                });

                options.SwaggerDoc("v2.0",new OpenApiInfo()
                {
                    Title = "My API v2.0",Version = "v2.0"
                });
            });
        }

        public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => { endpoints.MapControllers(); });

            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.DefaultModelsExpandDepth(0);
                c.SwaggerEndpoint($"/swagger/v1.0/swagger.json","my API 1.0");
            });
        }

我有这样定义的控制器:

    [ApiController]
    [ApiVersion("1.0")]
    [Route("api/weather/ByQuerySeparateClasses")]
    public class ByQuerySeparateClassesV1Controller : ControllerBase
    {
        [HttpGet("read")]
        public WeatherResponse Get()
        {
            return new WeatherResponse() { Summary = "v1 by path,different controllers" };
        }
    }

    [ApiController]
    [ApiVersion("2.0")]
    [Route("api/weather/ByQuerySeparateClasses")]
    public class ByQuerySeparateClassesV2Controller : ControllerBase
    {
        [HttpGet("read")]
        public WeatherResponse Get()
        {
            return new WeatherResponse() { Summary = "v2 by path,different controllers" };
        }
    }

当我运行此API时,这是生成的JSON,一个空白列表,好像没有看到我的API。

GET http://localhost:5000/swagger/v1.0/swagger.json
{
  "openapi": "3.0.1","info": {
    "title": "My API v1.0","version": "v1.0"
  },"paths": { },"components": { }
}

我在做什么错?还是有任何提示可以进一步诊断发生了什么?

可以在此处找到完整的示例:https://github.com/mmgagnon/versioned-api-with-swagger

解决方法

这是一个工作示例,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddApiVersioning(o =>
    {               
        o.AssumeDefaultVersionWhenUnspecified = true;
        o.DefaultApiVersion = new ApiVersion(1,0);
        o.ApiVersionReader = new UrlSegmentApiVersionReader();
    });

    services.AddVersionedApiExplorer(options => {
        options.GroupNameFormat = "'v'VVV";
        options.SubstituteApiVersionInUrl = true;
    });

    services.AddSwaggerGen(options =>
    {
        //add this...
        options.DocInclusionPredicate((docName,apiDesc) =>
        {
            if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo))
            {
                return false;
            }

            IEnumerable<ApiVersion> versions = methodInfo.DeclaringType
                .GetCustomAttributes(true)
                .OfType<ApiVersionAttribute>()
                .SelectMany(a => a.Versions);

            return versions.Any(v => $"v{v.ToString()}" == docName);
        });
    
        options.SwaggerDoc("v1.0",new OpenApiInfo()
        {
            Title = "My API v1.0",Version = "v1.0"
        });

        options.SwaggerDoc("v1.1",new OpenApiInfo()
        {
            Title = "My API v1.1",Version = "v1.1"
        });

        options.SwaggerDoc("v2.0",new OpenApiInfo()
        {
            Title = "My API v2.0",Version = "v2.0"
        });
    });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseApiVersioning();
    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    app.UseSwagger(swagger => {
    });

    app.UseSwaggerUI(c =>
    {
        c.DefaultModelsExpandDepth(0);
        c.SwaggerEndpoint($"/swagger/v1.0/swagger.json","my API 1.0");
        c.SwaggerEndpoint($"/swagger/v2.0/swagger.json","my API 2.0");
    });
}