具有不同名称的Api版本 示例

问题描述

我正在为我的项目使用asp dotnet core 3.1。目前,我正在通过1.0@H_502_2@或2.1@H_502_2@对我的操作进行版本控制,以此作为建议的操作方式。但是我想通过schooljob@H_502_2@或其他一些随机字符串值来对我的操作进行版本控制。我进行了很多研究,一些网站声称可以代替1_0@H_502_2@做1.0@H_502_2@ 但没有说怎么做。另外,我不知道是否可以将版本更改为schooljob@H_502_2@。

我真正想要做的是将我的网址从...someUrl/1.0/getTeachers@H_502_2@更改为...someUrl/schooljob/getTeachers@H_502_2@,以便最终可以在Swagger中更好地对其进行分组。

// SchoolController.cs
[ApiVersion("1.0")]  //I want to change it as [ApiVersion("schooljob")]
[ApiController]
[Route("{version:apiVersion}")]
public class SchoolController : AbstractController
{
   ...

   [HttpPost("schooljob/getstudents")]
   public JsonResult GetStudents([FromBody]Student student)
   { ... }
}
@H_502_2@
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    c.SwaggerDoc("schooljob",new OpenApiInfo
    {
        Version = "schooljob",Title = "School Job"
    });
    // c.AddSecurityDeFinition... and other swagger configurations
}   
public void Configure(IApplicationBuilder app,IWebHostEnvironment env,IServiceProvider serviceProvider)
{
    app.UseSwagger(c =>
    {
        c.RouteTemplate = "mainproject/swagger/{documentname}/swagger.json";
    });
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/mainproject/swagger/schooljob/swagger.json","School Job");
        c.RoutePrefix = "mainproject/swagger";
    });
}
@H_502_2@

解决方法

简短答案--您无法通过这种方式定义API版本。它具有无法更改的规定格式。这对于整理,排序和比较很重要。例如,1.0 > 1.0-beta

看起来 就像您要对API进行分组一样。默认行为是将格式化的API版本文本用作API描述的组名称。这是通往其他数据库(例如Swashbuckle或NSwag)进行分组的桥梁。有几种方法可以更改此行为。您可以将其更改为API Explorer扩展名( IApiDescriptionProvider )或OpenAPI / Swagger文档生成器扩展名。要获得所需的结果,您只需要对结果重新排序/分组即可。

大多数分组是通过API版本完成的,但是当然可以按资源或类别进行分组。由于API版本控制会覆盖默认的组名,因此您需要重新提取source属性中定义的原始组名或使用自定义属性。您可能可以根据模板约定或其他元数据进行构建。

示例

首先,您需要一种方法以所需的方式比较2个 ApiDescription 实例:

public class MyComparer : IComparer<ApiDescription>
{
    public int Compare(ApiDescription x,ApiDescription y)
    {
        if (x == null)
        {
            return y == null ? 0 : -1;
        }

        if (y == null)
        {
            return 1;
        }

        var comparer = StringComparer.OrdinalIgnoreCase;
        var result = comparer.Compare(x.GroupName,y.GroupName);

        // compare by group name,then api version
        return result == 0 ? x.GetApiVersion().CompareTo(y.GetApiVersion()) : result;
    }
}

然后,您可以创建一个自定义的 IApiDescriptionProvider ,用于处理发现的描述:

public class MyApiDescriptionProvider : IApiDescriptionProvider
{
    // important: you may need to increase the value to run later in the sequence
    public int Order => 0;

    public void OnProvidersExecuting(ApiDescriptionProviderContext context) { }

    public void OnProvidersExecuted(ApiDescriptionProviderContext context)
    {
        var sorted = context.Results.ToList();

        sorted.Sort(new MyComparer());
        context.Results.Clear();

        for (var i = 0; i < sorted.Count; i++)
        {
            context.Results.Add(sorted[i]);
        }
    }
}

最后,在设置中注册您的提供商:

services.TryAddEnumerable(
  ServiceDescriptor.Transient<IApiDescriptionProvider,MyApiDescriptionProvider>() );