0


在 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

。这个特性将用于标记我们的控制器,并包含模块名称、版本号和描述信息。

usingMicrosoft.AspNetCore.Mvc.ApiExplorer;namespaceWebApplication.ApiAttributes{publicclassApiDescriptionAttribute:Attribute,IApiDescriptionGroupNameProvider{publicApiDescriptionAttribute(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>publicstring? GroupName {get;set;}/// <summary>/// Swagger 标题/// </summary>publicstring? Title {get;set;}/// <summary>/// 版本号/// </summary>publicstring? Version {get;set;}/// <summary>/// 描述/// </summary>publicstring? Description {get;set;}/// <summary>/// 分组顺序/// </summary>publicint Position {get;set;}}}

步骤三:配置 Swagger 生成文档

接下来,我们需要在

Program.cs

中配置 Swagger,使其能够根据我们的自定义特性生成多个文档。

publicstaticvoidMain(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}",newOpenApiInfo{ Title =$"{desc.Title} API", Version = desc.Version, Description = desc.Description,});}else{
                    options.SwaggerDoc($"{desc.Title}-{desc.Version}",newOpenApiInfo{
                        Title =$"{desc.Title} API",
                        Version = desc.Version,
                        Description = desc.Description,});}}}//没有加特性的分到这个NoGroup上
        options.SwaggerDoc("NoGroup",newOpenApiInfo{
            Title ="无分组"});//判断接口归于哪个分组
        options.DocInclusionPredicate((docName, apiDescription)=>{if(docName =="NoGroup"){//当分组为NoGroup时,只要没加特性的都属于这个组returnstring.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

来标记控制器和方法。以下是一些示例:

usingMicrosoft.AspNetCore.Mvc;usingWebApplication.ApiAttributes;namespaceWebApplication.Controllers{[ApiDescription("ModuleA","v1","A模组测试")][Route("api/[controller]")][ApiController]publicclassModuleA1Controller:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Module A, Version 1");}}}
namespaceWebApplication.Controllers{[ApiDescription("ModuleA","v2")][Route("api/[controller]")][ApiController]publicclassModuleA2Controller:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Module A, Version 2");}}}
namespaceWebApplication.Controllers{[ApiDescription("ModuleB")][Route("api/[controller]")][ApiController]publicclassModuleBController:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Module B, 仅有Title");}}}
namespaceWebApplication.Controllers{[ApiDescription("ModuleC")][Route("api/[controller]")][ApiController]publicclassModuleC1Controller:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Module C1, 多Controller共用分组");}}}
namespaceWebApplication.Controllers{[ApiDescription("ModuleC")][Route("api/[controller]")][ApiController]publicclassModuleC2Controller:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Module C2, 多Controller共用分组");}}}
namespaceWebApplication.Controllers{[ApiDescription("ModuleD",desc:"D模组测试")][Route("api/[controller]")][ApiController]publicclassModuleDController:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Module D, 指定参数设置");}}}
namespaceWebApplication.Controllers{[Route("api/[controller]")][ApiController]publicclassModuleNoGroupController:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Module NoGroup");}}}
namespaceWebApplication.Controllers{[ApiDescription("Position A",desc:"指定顺序",position:1)][Route("api/[controller]")][ApiController]publicclassPositionAController:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Position A, 指定Swagger分组顺序");}}}
namespaceWebApplication.Controllers{[ApiDescription("Position Z",desc:"指定顺序",position:0)][Route("api/[controller]")][ApiController]publicclassPositionZController:ControllerBase{[HttpGet]publicIActionResultGet(){returnOk("Position Z, 指定Swagger分组顺序");}}}
namespaceWebApplication.Controllers{[Route("[controller]")][ApiDescription("天气","v1","天气预报")]publicclassWeatherForecastController:ControllerBase{privatestaticreadonlystring[] Summaries =new[]{"Freezing","Bracing","Chilly","Cool","Mild","Warm","Balmy","Hot","Sweltering","Scorching"};privatereadonlyILogger<WeatherForecastController> _logger;publicWeatherForecastController(ILogger<WeatherForecastController> logger){
            _logger = logger;}[HttpGet(Name ="GetWeatherForecast")]publicIEnumerable<WeatherForecast>Get(){return Enumerable.Range(1,5).Select(index =>newWeatherForecast{
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20,55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]}).ToArray();}}}

Swagger截图


总结

通过以上步骤,我们可以在 .NET Core Web API 项目中使用 Swagger 按模块和版本分组。这种实现方法使用了自定义特性来标记控制器,并在

Program.cs

中配置了 Swagger 以生成多个文档。这样,在 Swagger UI 中,我们可以根据模块和版本分别查看 API 文档,从而更好地管理和查找 API。这种方法不仅提升了文档的可读性,也增强了项目的可维护性,使开发者和使用者能更方便地交互与理解 API。

标签: c# .netcore

本文转载自: https://blog.csdn.net/qq_31463571/article/details/141166730
版权归原作者 吾家有猫名探花 所有, 如有侵权,请联系我们删除。

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

还没有评论