简体   繁体   English

NSwag:从多个版本的 API 生成 C# 客户端

[英]NSwag: Generate C# Client from multiple Versions of an API

We are versioning our API and generating the Swagger specification using Swashbuckle in ASP.NET Core 1.1.我们正在对 API 进行版本控制,并使用 ASP.NET Core 1.1 中的 Swashbuckle 生成 Swagger 规范。 We can generate two API docs based on those JSON specification files:我们可以基于这些 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
}

We are including all actions in both spec files, unless it is mapped to a specific version using the [MapToApiVersion] and ApiExplorerSettings(GroupName ="<version>")] attributes.我们将所有操作都包含在两个规范文件中,除非它使用[MapToApiVersion]ApiExplorerSettings(GroupName ="<version>")]属性映射到特定版本。 Methods belonging to an older version only are also decorated with the [Obsolete] attribute:仅属于旧版本的方法也用[Obsolete]属性修饰:

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

However, we want to have only one C# Client generated from the Union of both spec files, where all methods are included in the Client, 0.1 as well as 0.2, but all obsolete methods marked, in fact, as obsolete.但是,我们只想从两个规范文件的联合生成一个 C# 客户端,其中所有方法都包含在客户端中,0.1 和 0.2,但实际上所有过时的方法都标记为过时。

I have looked into both NSwag (which we are using for quite some time now) as well as AutoRest.我已经研究了 NSwag(我们已经使用了很长一段时间)以及 AutoRest。 AutoRest seems to support a merging scenario , but I could not get it to work because of schema validation errors (and I am more than unsure whether our specific scenario would be actually supported). AutoRest 似乎支持合并场景,但由于模式验证错误,我无法让它工作(我非常不确定我们的特定场景是否会得到实际支持)。

My last idea as of now to get this sorted is to somehow JSON-merge the specs into one and then feed it to NSwag.到目前为止,我对这个进行排序的最后一个想法是以某种方式将规范 JSON 合并为一个,然后将其提供给 NSwag。

Do we miss anything here?我们在这里错过了什么吗? Is this somehow possible to realize with NSwag?这是否可以通过 NSwag 实现?

I wrote an article about similar problem https://medium.com/dev-genius/nswag-charp-client-from-multiple-api-versions-7c79a3de4622我写了一篇关于类似问题的文章https://medium.com/dev-genius/nswag-charp-client-from-multiple-api-versions-7c79a3de4622

First of all, create a schema.首先,创建一个模式。 As I see, there are two approaches:如我所见,有两种方法:

  • one schema where multiple versions are living存在多个版本的一种模式
  • own schema for each version每个版本都有自己的架构

Next, create clients for each supported version and wrap them under the wrapper client:接下来,为每个支持的版本创建客户端并将它们包装在包装器客户端下:

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

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

Here is my idea, expanding from the comments:这是我的想法,从评论中扩展:

With swashbuckle you can generate as many SwaggerDoc as you like, the idea on this case is to generate 3 keep the same 2 versions that you have and add one more that will have everything.使用 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");
    });

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

And the entire code for that project is on GitHub:该项目的全部代码都在 GitHub 上:
https://github.com/heldersepu/Swagger-Net-Test/tree/MultiApiVersions https://github.com/heldersepu/Swagger-Net-Test/tree/MultiApiVersions

Packages:套餐:

Install-Package Swashbuckle.AspNetCore安装包 Swashbuckle.AspNetCore

Install-Package Microsoft.AspNetCore.Mvc.Versioning安装包 Microsoft.AspNetCore.Mvc.Versioning

在此处输入图片说明

ValueV1Controller.cs 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 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
            );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 NSwag for C# 我们如何在同一个客户端项目中为不同的 API 创建多个客户端类 - With NSwag for C# how do we create multiple client classes for different API in the same client project 使用 Nswag 控制台(来自 NPM 包)以生成 C# 客户端 - Use Nswag Console (from NPM package) in order to generate C# client 使用 NSwag 生成 C# 客户端错误地在同一个文件中创建了 2x 个同名的部分类 - Using NSwag to generate a C# client incorrectly creates 2x partial classes with the same name, in the same file 在 NSwag 中是否可以只生成 C# 客户端接口并使用一些自定义属性注释它们的方法? - Is it possible in NSwag to generate just C# client interfaces and annotate their methods with some custom attributes? 生成 NSwag 客户端作为构建的一部分 - Generate NSwag client as part of the build NSwag:生成 C# 客户端导致代码无效 - NSwag: Generation of a C# client results in invalid code C# OpenApi Nswag 客户端生成复合体 Class 为空 - C# OpenApi Nswag Client Generation Complex Class is empty C# 带有 NSwag 的多态模型 - C# Polymorphic models with NSwag NSwag:你如何使用自定义值 Object 类型 C# -&gt; Swagger -&gt; ZD7EFA19FBE7D23D772FDZ客户端560FBE7D23D7724客户端? - NSwag: How do you Use Custom Value Object Types in C# -> Swagger -> C# client? C#多版本更新程序 - C# multiple versions updater
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM