ASP.NET Core – Swagger API Versioning

前言

Versioning 会导致 Swagger 直接坏掉. 因为 1 个文档无法支持多个版本. 所以需要每一个版本做一个文档.

 

主要参考

Integrating ASP.NET Core Api Versions with Swagger UI

What every ASP.NET Core Web API project needs - Part 2 - API versioning and Swagger

Docs – aspnet-api-versioning(最新版本,上面的是旧版本的参考)

Stack Overflow – iServiceCollection' does not contain a definition for 'addVersionedApiExplorer'

 

安装 Versioning.ApiExplorer

dotnet add package Asp.Versioning.Mvc.ApiExplorer

 

Program.cs

复制代码
var apiVersioningBuilder = builder.Services.AddApiVersioning(options =>
{
  options.AssumeDefaultVersionWhenUnspecified = true;
  options.DefaultApiVersion = new ApiVersion(1, 0);
  options.ReportApiVersions = true;
}).AddMvc();

apiVersioningBuilder.AddApiExplorer(options =>
{
  options.GroupNameFormat = "'v'VVV";
  options.SubstituteApiVersionInUrl = true;
});
复制代码

AddApiVersioning 后会返回一个 versioning builder,利用它来继续 setup Swagger 的部分。

做一个 ConfigureSwaggerOptions.cs

之前的 XML, OpenApiInfo 放进去, 关键就是让它变成动态创建, 依赖 version.

复制代码
using System.Reflection;
using Asp.Versioning.ApiExplorer;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace WebApi;

public class ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) : IConfigureNamedOptions<SwaggerGenOptions>
{
  private readonly IApiVersionDescriptionProvider provider = provider;

  public void Configure(SwaggerGenOptions options)
  {
    foreach (var description in provider.ApiVersionDescriptions)
    {
      options.SwaggerDoc(description.GroupName, CreateVersionInfo(description));

      var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
      var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
      options.IncludeXmlComments(xmlPath);
    }
  }

  public void Configure(string? name, SwaggerGenOptions options)
  {
    Configure(options);
  }

  private static OpenApiInfo CreateVersionInfo(ApiVersionDescription description)
  {
    var version = description.ApiVersion.ToString();
    var info = new OpenApiInfo()
    {
      Title = "Project Web API",
      Version = $"v{version}",
      Description = $"DB&Project Web API version {version}",
      Contact = new OpenApiContact
      {
        Name = "Derrick Yam",
        Email = "hengkeat87@gmail.com",
      },
    };
    if (description.IsDeprecated)
    {
      info.Description += " This API version has been deprecated.";
    }
    return info;
  }
}
复制代码

配置

builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();

最后是 UI, 需要注入 IApiVersionDescriptionProvider

app.UseSwaggerUI(options =>
{
    foreach (var description in app.Services.GetRequiredService<IApiVersionDescriptionProvider>().ApiVersionDescriptions)
    {
        options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", $"Project Web API v{description.ApiVersion}");
        options.DocExpansion(DocExpansion.None);
    }
});

这样就可以了

 

posted @   兴杰  阅读(359)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
历史上的今天:
2018-10-25 Angular 学习笔记 (Material Datepicker)
点击右上角即可分享
微信分享提示