WebApi版本控制加Swagger

烂柯 发布于 2023-02-07 238 次阅读


概述

随着对系统的改进,API的迭代或调整是不可避免的。当它有可能破坏现有的客户端集成时,我们可以通过接口版本控制和swaggerr减少这种变化对终端集成的影响。

一、引用

#版本控制
Install-Package Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer
#swagger默认添加
Install-Package Swashbuckle.AspNetCore

二、配置版本控制

1、添加版本控制服务信息

program.cs

...
//添加接口版本信息
builder.Services.AddApiVersioning(options =>
{
    //允许 API 在响应标头中返回版本
    options.ReportApiVersions = true;
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
//可配置header
//options.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
//    new HeaderApiVersionReader("X-Accept-version"),
//    new MediaTypeApiVersionReader("X-Accept-version"));
});
builder.Services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl= true;
});
...

ApiVersionReader 使我们的客户可以选择是将参数放在 URL 中还是请求标头中:

  • UrlSegmentApiVersionReader:允许从 URL 获取版本号,如:/api/v1/metod
  • HeaderApiVersionReader : 从标头参数中获取版本号,如:X-Accept-version:1.0
  • 8soCfP12Ph19mi914zQaZz2KsGGtcANVhVVfKAnmVRqM Content-Type 或 Accept 标志中,如:Accept/Content-Type: application/json; X-Accept-version=1.0

2、添加接口特性

WeatherForecastController.cs

...
    /// <summary>
    /// 天气接口
    /// </summary>
    [ApiVersion("1.0")]
    [ApiController]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class WeatherForecastController : ControllerBase
...

三、配置swagger

这里配置swagger,通过注入容器配置选项的方式完成配置

1、新建swagger配置类

SwaggerConfigure.cs

using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;

namespace ApiVersionTest;

public class SwaggerConfigure : IConfigureOptions<SwaggerOptions>
{
    public void Configure(SwaggerOptions options)
    {
        options.PreSerializeFilters.Add((swagger, req) =>
        {
            //添加目标服务器地址
            swagger.Servers = new List<OpenApiServer>() { new() { Url = $"{req.Scheme}://{req.Host}" } };
        });
    }
}
public class SwaggerGenConfigure : IConfigureOptions<SwaggerGenOptions>
{
    private readonly IApiVersionDescriptionProvider _provider;
    public SwaggerGenConfigure(IApiVersionDescriptionProvider provider)
    {
        _provider = provider;
    }

    public void Configure(SwaggerGenOptions options)
    {
        foreach (ApiVersionDescription desc in _provider.ApiVersionDescriptions)
        {
            options.SwaggerDoc(desc.GroupName, new OpenApiInfo
            {
                Title = $"Version Test API {desc.GroupName}",
                Version = desc.ApiVersion.ToString(),
            });
        }
        //添加token验证输入地方
        //string headerName = "Authorization";
        //options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        //{
        //    Description = $"JWT授权(数据将在请求头中进行传输) 直接在下框中输入{headerName}",
        //    Name = headerName, //jwt默认的参数名称
        //    In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中)
        //    Type = SecuritySchemeType.ApiKey
        //});
        //options.AddSecurityRequirement(new OpenApiSecurityRequirement
        //{
        //    {
        //        new OpenApiSecurityScheme
        //        {
        //            Reference = new OpenApiReference()
        //            {
        //                Id = "Bearer",
        //                Type = ReferenceType.SecurityScheme
        //            }
        //        },
        //        Array.Empty<string>()
        //    }
        //});
        //添加文档描述
        var docXml = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.xml");
        foreach (var doc in docXml)
            options.IncludeXmlComments(doc, true);
    }
}

public class SwaggerUiConfigure : IConfigureOptions<SwaggerUIOptions>
{
    private readonly IApiVersionDescriptionProvider _provider;
    public SwaggerUiConfigure(IApiVersionDescriptionProvider provider)
    {
        _provider = provider;
    }
    public void Configure(SwaggerUIOptions options)
    {
        foreach (ApiVersionDescription desc in _provider.ApiVersionDescriptions)
        {
            options.SwaggerEndpoint($"{desc.GroupName}/swagger.json", $"Version Test API {desc.GroupName}");
            //控制器展示方式(是否折叠)
            options.DocExpansion(DocExpansion.None);
            //模型展示深度
            //options.DefaultModelsExpandDepth(-1);

        }
    }
}

2、注入swagger配置信息

Program.cs

...
builder.Services.AddEndpointsApiExplorer();
if (builder.Environment.IsDevelopment())
{
    //添加swagger配置信息
    builder.Services.AddSingleton<IConfigureOptions<SwaggerGenOptions>, SwaggerGenConfigure>();
    builder.Services.AddSingleton<IConfigureOptions<SwaggerOptions>, SwaggerConfigure>();
    builder.Services.AddSingleton<IConfigureOptions<SwaggerUIOptions>, SwaggerUiConfigure>();
    builder.Services.AddSwaggerGen();
}
var app = builder.Build();
...

四、测试及源码

源码:https://github.com/VectorlanKe/ApiVersionTest

运行展示swagger,如下

image-20230207163221060

烂柯

最后更新于 2023-03-02