【问题标题】:C# versioned WebApi documentation using Swashbuckle / Swagger使用 Swashbuckle / Swagger 的 C# 版本化 WebApi 文档
【发布时间】:2020-09-17 13:41:17
【问题描述】:

我有一个包含多个版本的 C# WebApi,我想使用 Swashbuckle/Swagger 和 .net core 3.1 记录这些版本。我已经尝试按照我可以找到的指南进行操作,但我似乎遗漏了一些东西,因为 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

【问题讨论】:

  • 你有app.UseMvc()吗?
  • 顺便看你的链接,只需要Swashbuckle.AspNetCoreNuGet包
  • @Krusty app.UseMvc() 不是必需的,当我尝试使用它时出现以下错误:“System.InvalidOperationException: '端点路由不支持'IApplicationBuilder.UseMvc(... )'。要使用 'IApplicationBuilder.UseMvc',请在 'ConfigureServices(...).' 中设置 'MvcOptions.EnableEndpointRouting = false'。无论如何,我的 API 工作正常,只有 swagger 文档有问题,所以我真的认为问题不存在。
  • 我不是 100% 确定,但是 Swagger 需要 UseMvc 来生成 API 页面。您可以通过添加 .AddMvc(options => { options.EnableEndpointRouting = false; }) 来修复该异常,在紫色框中已确认:docs.microsoft.com/en-us/aspnet/core/tutorials/…
  • @Krusty 我已经能够在没有 UseMvc 的情况下成功生成 swagger API 页面——只要我不使用 API 版本。但可以肯定的是,我尝试将 UseMvc() 添加到我的示例中,但它对我原来的问题没有帮助。

标签: c# swagger asp.net-core-webapi swashbuckle swashbuckle.aspnetcore


【解决方案1】:

这是一个如下所示的工作演示:

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");
    });
}

【讨论】:

  • 谢谢,这似乎工作得好多了!只是几个问题:1)你能解释为什么需要额外的代码吗?我在网上阅读的文档和示例不需要额外的代码,那么为什么在这种情况下需要呢? 2) 使用您的代码,“v1”端点返回一些 v2 API,反之亦然,“v2”端点返回一些“v1”API。这很可能不是故意的?
  • 附加代码用于通过ApiVersionAttribute告诉swagger版本是什么。以及为什么v1端点返回一些v2 api,那是因为在您的ByPathSameClassController中添加了两个ApiVersionAttribute。跨度>
猜你喜欢
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 1970-01-01
相关资源
最近更新 更多