十念 发表于 2024-11-20 17:21:40

在 C#/.NET Core 的 Web API 中使用 Swagger 按模块和版本分组并实现排序

前言

在开发 RESTful API 时,良好的文档是必不可少的。Swagger 是一种广泛使用的 API 文档工具,可以资助我们生成交互式的 API 文档。然而,当项目规模增大,API 数目浩繁时,我们必要将 API 按照模块和版本进行分组,以便更好地管理和查找。本文将先容怎样在 .NET Core Web API 中使用 Swagger 按模块和版本分组,并使用自界说特性实现这一目的。
步骤一:安装 Swashbuckle.AspNetCore

首先,我们必要安装 Swashbuckle.AspNetCore 包,这是 .NET Core 中用于集成 Swagger 的库。可以在项目的根目录下运行以下下令进行安装:
dotnet add package Swashbuckle.AspNetCore
步骤二:创建自界说特性

为了实现按模块和版本分组,我们必要创建一个自界说特性 ApiDescriptionAttribute。这个特性将用于标志我们的控制器,并包含模块名称、版本号和描述信息。
using Microsoft.AspNetCore.Mvc.ApiExplorer;

namespace WebApplication.ApiAttributes
{
    public class ApiDescriptionAttribute : Attribute, IApiDescriptionGroupNameProvider
    {
      public ApiDescriptionAttribute(string title, string? version = null, string? desc = null, int position = int.MaxValue)
      {
            GroupName = version != null ? $"{title}-{version}" : title;
            Title = title;
            Version = version;
            Description = desc;
            Position = position;
      }

      /// <summary>
      /// 分组名称
      /// </summary>
      public string? GroupName { get; set; }
      /// <summary>
      /// Swagger 标题
      /// </summary>
      public string? Title { get; set; }
      /// <summary>
      /// 版本号
      /// </summary>
      public string? Version { get; set; }
      /// <summary>
      /// 描述
      /// </summary>
      public string? Description { get; set; }
      /// <summary>
      /// 分组顺序
      /// </summary>
      public int Position { get; set; }
    }
}
步骤三:配置 Swagger 生成文档

接下来,我们必要在 Program.cs 中配置 Swagger,使其能够根据我们的自界说特性生成多个文档。
public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);
   
    // 添加服务到容器
    builder.Services.AddControllers();
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen(options =>
    {
      // 根据模块和版本生成多个文档
      var apiAssembly = Assembly.GetExecutingAssembly();
      var apiDescriptions = apiAssembly.GetTypes()
            .Where(t => t.GetCustomAttributes<ApiDescriptionAttribute>().Any())
            .Select(t => t.GetCustomAttribute<ApiDescriptionAttribute>())
            .Distinct();

      foreach (var desc in apiDescriptions)
      {
            if (desc != null)
            {
                if (string.IsNullOrEmpty(desc.Version))
                {
                  options.SwaggerDoc($"{desc.Title}", new OpenApiInfo { Title = $"{desc.Title} API", Version = desc.Version, Description = desc.Description, });
                }
                else
                {
                  options.SwaggerDoc($"{desc.Title}-{desc.Version}", new OpenApiInfo
                  {
                        Title = $"{desc.Title} API",
                        Version = desc.Version,
                        Description = desc.Description,
                  });
                }
            }
      }
      //没有加特性的分到这个NoGroup上
      options.SwaggerDoc("NoGroup", new OpenApiInfo
      {
            Title = "无分组"
      });
      //判断接口归于哪个分组
      options.DocInclusionPredicate((docName, apiDescription) =>
      {
            if (docName == "NoGroup")
            {
                //当分组为NoGroup时,只要没加特性的都属于这个组
                return string.IsNullOrEmpty(apiDescription.GroupName);
            }
            else
            {
                return apiDescription.GroupName == docName;
            }
      });
    });

    var app = builder.Build();

    // 配置 HTTP 请求管道
    if (app.Environment.IsDevelopment())
    {
      app.UseSwagger();
      app.UseSwaggerUI(options =>
      {
            // 根据模块和版本生成多个文档
            var apiAssembly = Assembly.GetExecutingAssembly();
            var apiDescriptions = apiAssembly.GetTypes()
                .Where(t => t.GetCustomAttributes<ApiDescriptionAttribute>().Any())
                .Select(t => t.GetCustomAttribute<ApiDescriptionAttribute>())
                .OrderBy(t => t?.Position ?? int.MaxValue).ThenBy(t => t?.Title).ThenBy(t => t?.Version)
                .Distinct();

            foreach (var desc in apiDescriptions)
            {
                if (desc != null)
                {
                  if (string.IsNullOrEmpty(desc.Version))
                  {
                        options.SwaggerEndpoint($"/swagger/{desc.Title}/swagger.json", $"{desc.Title} API");
                  }
                  else
                  {
                        options.SwaggerEndpoint($"/swagger/{desc.Title}-{desc.Version}/swagger.json", $"{desc.Title} API {desc.Version}");
                  }
                }
            }

            options.SwaggerEndpoint("/swagger/NoGroup/swagger.json", "无分组");
      });
    }

    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.MapControllers();
    app.Run();
}
步骤四:标志控制器和方法

使用我们创建的 ApiDescriptionAttribute 来标志控制器和方法。以下是一些示例:
using Microsoft.AspNetCore.Mvc;
using WebApplication.ApiAttributes;

namespace WebApplication.Controllers
{
   
    ")]
   
    public class ModuleA1Controller : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Module A, Version 1");
      }
    }
}
namespace WebApplication.Controllers
{
   
    ")]
   
    public class ModuleA2Controller : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Module A, Version 2");
      }
    }
}
namespace WebApplication.Controllers
{
   
    ")]
   
    public class ModuleBController : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Module B, 仅有Title");
      }
    }
}
namespace WebApplication.Controllers
{
   
    ")]
   
    public class ModuleC1Controller : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Module C1, 多Controller共用分组");
      }
    }
}
namespace WebApplication.Controllers
{
   
    ")]
   
    public class ModuleC2Controller : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Module C2, 多Controller共用分组");
      }
    }
}
namespace WebApplication.Controllers
{
   
    ")]
   
    public class ModuleDController : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Module D, 指定参数设置");
      }
    }
}
namespace WebApplication.Controllers
{
    ")]
   
    public class ModuleNoGroupController : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Module NoGroup");
      }
    }
}
namespace WebApplication.Controllers
{
   
    ")]
   
    public class PositionAController : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Position A, 指定Swagger分组顺序");
      }
    }
}
namespace WebApplication.Controllers
{
   
    ")]
   
    public class PositionZController : ControllerBase
    {
      
      public IActionResult Get()
      {
            return Ok("Position Z, 指定Swagger分组顺序");
      }
    }
}
namespace WebApplication.Controllers
{
    ")]
   
    public class WeatherForecastController : ControllerBase
    {
      private static readonly string[] Summaries = new[]
      {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
      };

      private readonly ILogger<WeatherForecastController> _logger;

      public WeatherForecastController(ILogger<WeatherForecastController> logger)
      {
            _logger = logger;
      }

      
      public IEnumerable<WeatherForecast> Get()
      {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries
            })
            .ToArray();
      }
    }
}
https://i-blog.csdnimg.cn/direct/7f831d92064946199fa4a248b46c094c.png
总结

通过以上步骤,我们可以在 .NET Core Web API 项目中使用 Swagger 按模块和版本分组。这种实现方法使用了自界说特性来标志控制器,并在 Program.cs 中配置了 Swagger 以生成多个文档。如许,在 Swagger UI 中,我们可以根据模块和版本分别检察 API 文档,从而更好地管理和查找 API。这种方法不但提拔了文档的可读性,也增强了项目的可维护性,使开发者和使用者能更方便地交互与明白 API。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 在 C#/.NET Core 的 Web API 中使用 Swagger 按模块和版本分组并实现排序