【问题标题】:NSwag: Generate C# Client from multiple Versions of an APINSwag:从 API 的多个版本生成 C# 客户端
【发布时间】:2018-11-09 06:33:41
【问题描述】:

我们正在对我们的 API 进行版本控制,并在 ASP.NET Core 1.1 中使用 Swashbuckle 生成 Swagger 规范。我们可以根据这些 JSON 规范文件生成两个 API 文档:

<!-- language: c# -->
services.AddSwaggerGen(setupAction =>
{
    setupAction.SwaggerDoc("0.1", new Info { Title = "Api", Version = "0.1", Description = "API v0.1" });
    setupAction.SwaggerDoc("0.2", new Info { Title = "Api", Version = "0.2", Description = "API v0.2" });

    // more configuration omitted
}

我们将所有操作都包含在两个规范文件中,除非它使用[MapToApiVersion] 和ApiExplorerSettings(GroupName ="&lt;version&gt;")] 属性映射到特定版本。仅属于旧版本的方法也用[Obsolete] 属性修饰:

<!-- language: c# -->
[MapToApiVersion("0.1")]
[ApiExplorerSettings(GroupName = "0.1")]
[Obsolete]

但是,我们只希望从两个规范文件的联合中生成一个 C# 客户端,其中所有方法都包含在客户端中,0.1 和 0.2,但实际上所有过时的方法都标记为过时。

我已经研究了 NSwag(我们已经使用了很长一段时间了)以及 AutoRest。 AutoRest 似乎是support a merging scenario,但由于架构验证错误,我无法让它工作(而且我不确定我们的特定场景是否会得到实际支持)。

到目前为止,我对这个排序的最后一个想法是以某种方式将规范合并为一个,然后将其提供给 NSwag。

我们在这里有什么遗漏吗? NSwag 能以某种方式实现吗?

【问题讨论】:

  • 所以如果我理解正确,您目前正在使用 Swashbuckle 并希望迁移到 NSwag/AutoRest?
  • 没有。我们正在使用 Swashbuckle.AspNetCore 生成规范 (JSON),并使用 NSwag 生成 C# 客户端。如果可能,我们不想迁移任何东西。
  • 我认为你可以在 Swashbuckle 上做到这一点,看看这个:swagger-net-test-multiapiversions.azurewebsites.net/swagger/ui/…
  • @HelderSepu 看起来很像我需要的东西。我猜,默认情况下,我会生成客户端。您是否有指向特定文档或示例代码的链接?谢谢!

标签: c# swagger swashbuckle autorest nswag


【解决方案1】:

我写了一篇类似问题的文章https://medium.com/dev-genius/nswag-charp-client-from-multiple-api-versions-7c79a3de4622

首先,创建一个模式。如我所见,有两种方法:

  • 存在多个版本的架构
  • 每个版本都有自己的架构

接下来,为每个支持的版本创建客户端,并将它们包装在包装器客户端下:

public class AppApiClient
{
    public IV1Client V1 { get; }
    public IV2Client V2 { get; }

    public AppApiClient(HttpClient httpClient)
    {
        V1 = new V1Client(httpClient);
        V2 = new V2Client(httpClient);
    }
}

【讨论】:

  • 虽然我的问题不再相关,但我觉得这正是我所需要的。真的非常感谢!
【解决方案2】:

这是我的想法,从 cmets 扩展而来:

使用 swashbuckle,您可以根据需要生成任意数量的 SwaggerDoc,此案例的想法是生成 3 个保持与您拥有的相同的 2 个版本,然后再添加一个将拥有一切的版本。

c.MultipleApiVersions(
    (apiDesc, targetApiVersion) => 
      targetApiVersion.Equals("default") || // Include everything by default
      apiDesc.Route.RouteTemplate.StartsWith(targetApiVersion), // Only include matching routes for other versions
    (vc) =>
    {
        vc.Version("default", "Swagger_Test");
        vc.Version("v1_0", "Swagger_Test V1_0");
        vc.Version("v2_0", "Swagger_Test V2_0");
    });

这是一个工作示例:
http://swagger-net-test-multiapiversions.azurewebsites.net/swagger/ui/index?filter=Api

该项目的全部代码都在 GitHub 上:
https://github.com/heldersepu/Swagger-Net-Test/tree/MultiApiVersions

【讨论】:

  • 谢谢!但是,您的示例似乎来自完整的 .NET Framework 的 Swashbuckle,但我正在使用 Swashbuckle.ASpNetCore 研究 ASP.NET Core。在那里,我无法复制您的解决方案。
【解决方案3】:

包:

安装包 Swashbuckle.AspNetCore

安装包 Microsoft.AspNetCore.Mvc.Versioning

ValueV1Controller.cs

[ApiVersion("1")]
[Route("api/v{version:apiVersion}/Values")]
public class ValuesV1Controller : Controller
{
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

ValueV2Controller.cs

[ApiVersion("2")]
[Route("api/v{version:apiVersion}/Values")]
public class ValuesV2Controller : Controller
{
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1.2", "value2.2" };
    }
}

Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddApiVersioning();
        // Register the Swagger generator, defining 1 or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "My API - V1", Version = "v1" });
            c.SwaggerDoc("v2", new Info { Title = "My API - V2", Version = "v2" });

            c.DocInclusionPredicate((docName, apiDesc) =>
            {
                var versions = apiDesc.ControllerAttributes()
                    .OfType<ApiVersionAttribute>()
                    .SelectMany(attr => attr.Versions);

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

            c.OperationFilter<RemoveVersionParameters>();
            c.DocumentFilter<SetVersionInPaths>();
        });
    }

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

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), 
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v2/swagger.json", "My API V2");
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });

        app.UseMvc();
    }
}

public class RemoveVersionParameters : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        var versionParameter = operation.Parameters?.SingleOrDefault(p => p.Name == "version");
        if (versionParameter != null)
            operation.Parameters.Remove(versionParameter);
    }
}

public class SetVersionInPaths : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {
        swaggerDoc.Paths = swaggerDoc.Paths
            .ToDictionary(
                path => path.Key.Replace("v{version}", swaggerDoc.Info.Version),
                path => path.Value
            );
    }
}

【讨论】:

  • 这对我有用,对 Core 3.1 做了一些修改。这个链接帮助我完成了 3.1 的更改。 (参见页面上的 cmets)dev.to/htissink/… - 另外,我不需要使用 DocInclusionPredicate,因为没有它对我来说一切正常。它实际上打破了它。
猜你喜欢
  • 2021-01-15
  • 2020-09-29
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-29
相关资源
最近更新 更多