ABP swagger集成

安装

Install-Package Volo.Abp.Swashbuckle

在modle文件中,引用此模块

kotlin 复制代码
[DependsOn(
    //...other dependencies
    typeof(AbpSwashbuckleModule) // <-- Add module dependency like that
)]
public class YourModule : AbpModule
{
}

自定义swagger配置

typescript 复制代码
public static class SwaggerConfigurationHelper
{
    // 配置Swagger
    public static void Configure(
        ServiceConfigurationContext context,
        string apiTitle
    )
    {
        context.Services.AddSwaggerGen(options =>
        {
            // 隐藏ABP默认的端点
            options.HideAbpEndpoints();

            // 添加Swagger文档
            options.SwaggerDoc("v1", new OpenApiInfo { Title = apiTitle, Version = "v1" });

            // 包含所有API
            options.DocInclusionPredicate((docName, description) => true);

            // 添加文档过滤器,将所有的API路径转为小写
            options.DocumentFilter<LowerCaseDocumentFilter>();

            // 添加操作过滤器,设置操作ID
            options.OperationFilter<SetOperationIdOperationFilter>();

            // 添加模式过滤器,设置属性为必需的
            options.SchemaFilter<AssignPropertyRequiredFilter>();

            // 自动扫描XML注释
            AutoScanXmlComments(options, "Arim.*.xml");
        });
    }

    // 配置Swagger并添加OAuth认证
    public static void ConfigureWithAuth(
        ServiceConfigurationContext context,
        string authority,
        Dictionary<string, string> scopes,
        string apiTitle,
        string apiVersion = "v1",
        string apiName = "v1"
    )
    {
        context.Services.AddAbpSwaggerGenWithOAuth(
            authority: authority,
            scopes: scopes,
            options =>
            {
                options.SwaggerDoc(apiName, new OpenApiInfo { Title = apiTitle, Version = apiVersion });
                options.DocInclusionPredicate((docName, description) => true);

                options.DocumentFilter<LowerCaseDocumentFilter>();
                options.OperationFilter<SetOperationIdOperationFilter>();
                options.SchemaFilter<AssignPropertyRequiredFilter>();
                AutoScanXmlComments(options, "Arim.*.xml");
            });
    }

    // 自动扫描XML注释文件并将其包含在Swagger文档中
    private static void AutoScanXmlComments(SwaggerGenOptions options, string pattern)
    {
        var basePath = AppContext.BaseDirectory;
        Regex reg = new Regex(WildcardToRegex(pattern));
        var comments = Directory.GetFiles(basePath, "*.*", SearchOption.TopDirectoryOnly)
            .Where(p => reg.IsMatch(Path.GetFileName(p))).ToList();
        foreach (var comment in comments)
        {
            options.IncludeXmlComments(comment);
        }
    }

    // 将通配符模式转换为正则表达式
    private static string WildcardToRegex(string pattern)
    {
        return "^" + Regex.Escape(pattern).Replace("\*", ".*").Replace("\?", ".") + "$";
    }
}

从给定的 SwaggerConfigurationHelper 类中,我们可以看到以下自定义的部分:

  1. HideAbpEndpoints() :
    • 这是一个扩展方法,用于隐藏 ABP 框架的默认端点。这样,当你在 Swagger UI 中查看 API 文档时,不会看到 ABP 框架的内置端点。
  1. AutoScanXmlComments:
    • 这是一个私有方法,用于自动扫描 XML 注释文件并将其包含在 Swagger 文档中。这样,你在代码中为方法或属性添加的 XML 注释将显示在 Swagger UI 中。
    • 它使用正则表达式来匹配文件名,并只包括匹配的文件。
  1. WildcardToRegex:
    • 这是一个私有方法,用于将通配符模式转换为正则表达式。这在 AutoScanXmlComments 方法中被使用,以匹配 XML 注释文件的名称。
  1. ConfigureWithAuth:
    • 这是一个公共方法,用于配置带有 OAuth 身份验证的 Swagger 文档。它允许你为 Swagger UI 设置 OAuth 身份验证,这样你可以在 Swagger UI 中进行身份验证并测试需要身份验证的 API 端点。

除了上述内容,还有一些基本的 Swagger 配置,如设置 API 文档的标题和版本、添加文档、操作和模式过滤器等。

但是,除了你已经提到的三个过滤器(LowerCaseDocumentFilter、SetOperationIdOperationFilter 和 AssignPropertyRequiredFilter)外,没有其他明显的自定义过滤器或操作。

总的来说,这个 SwaggerConfigurationHelper 类提供了一种结构化的方式来配置 Swagger 文档,使其与 ABP 框架和其他自定义需求兼容。

自定义过滤器-处理路径

这是你提供的 LowerCaseDocumentFilter 过滤器的详细分析,我为关键部分添加了中文注释:

csharp 复制代码
public class LowerCaseDocumentFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        // 将Swagger文档中的所有路径转换为小写,并保留路径参数的大写形式
        var paths = swaggerDoc.Paths.ToDictionary(
            entry => string.Join('/', entry.Key.Split('/').Select(x =>
                                                                  // 如果路径段是一个路径参数(以"{"开头),则保持其原始大小写形式
                                                                  x.StartsWith("{") && x.Length > 1 ?
                                                                  "{" + char.ToLowerInvariant(x[1]) + x.Substring(2) :
                                                                  // 否则,将路径段转换为小写
                                                                  x.ToLowerInvariant())),
            entry => entry.Value);

        // 清空原始的路径集合
        swaggerDoc.Paths = new OpenApiPaths();

        // 遍历处理后的路径集合
        foreach ((string key, OpenApiPathItem value) in paths)
        {
            // 遍历每个操作的所有参数
            foreach (OpenApiParameter param in value.Operations.SelectMany(o => o.Value.Parameters))
            {
                // 将参数名称转换为驼峰命名法
                param.Name = param.Name.ToCamelCase();
            }

            // 将处理后的路径和操作添加到Swagger文档中
            swaggerDoc.Paths.Add(key, value);
        }
    }
}

从这个过滤器的代码中可以看出,它的主要目的是将Swagger文档中的所有路径转换为小写,并将路径参数的名称转换为驼峰命名法。这个过滤器不会修改或覆盖 tags,因此它不会影响 RemoteService 的 Name 参数。

但是,这个过滤器会修改路径和参数的名称,这可能会导致与其他代码或配置的不一致。如果你的应用程序或前端代码依赖于特定的路径或参数名称,那么这个过滤器可能会导致问题。

我将通过一个例子来说明 LowerCaseDocumentFilter 过滤器的作用和可能的影响。

假设情景:

你有一个API端点,其路径和参数如下:

GET /api/UserProfile/GetByUserName?UserName=JohnDoe

在应用 LowerCaseDocumentFilter 过滤器之前:

Swagger文档中的表示为:

GET /api/UserProfile/GetByUserName?UserName=JohnDoe

在应用 LowerCaseDocumentFilter 过滤器之后:

Swagger文档中的表示变为:

GET /api/userprofile/getbyusername?userName=JohnDoe

分析:

  1. 路径的变化:原始的路径 /api/UserProfile/GetByUserName 被转换为全小写的 /api/userprofile/getbyusername。
  2. 参数的变化:原始的参数 UserName 被转换为驼峰命名法的 userName。

可能的影响:

  1. 前端代码的影响:如果前端代码或其他客户端直接从Swagger文档生成API调用代码,那么它们可能会使用修改后的路径和参数名称。这可能导致与服务器的实际API不匹配,从而导致请求失败。
  2. 文档的一致性:虽然小写路径和驼峰命名法参数在某些情况下可能更具可读性,但它们可能与其他文档或教程中的示例不一致。
  3. API的版本控制:如果你决定在未来的版本中移除这个过滤器,那么已经生成的客户端代码可能会因为路径和参数名称的变化而中断。

虽然 LowerCaseDocumentFilter 过滤器可以帮助统一Swagger文档中的命名约定,但它也可能导致与实际API的不一致。在使用此过滤器之前,建议仔细考虑其潜在影响,并确保所有相关的代码和文档都与修改后的Swagger文档保持一致。

自定义过滤器-operationId规则

这是一个名为 SetOperationIdOperationFilter 的 Swagger 过滤器,它实现了 IOperationFilter 接口。该过滤器的主要目的是为 Swagger 文档中的操作设置一个特定的 OperationId。下面是对这个过滤器的详细分析和中文注释:

csharp 复制代码
public class SetOperationIdOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        // 检查当前的 ActionDescriptor 是否为 ControllerActionDescriptor 类型
        // 如果不是,则直接返回,不进行任何操作
        if (!(context.ApiDescription.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor))
        {
            return;
        }

        // 遍历 API 描述中的所有参数描述
        foreach (var pd in context.ApiDescription.ParameterDescriptions)
        {
            // 在 operation 的参数列表中查找与当前参数描述名称相同的参数
            var p = operation.Parameters.FirstOrDefault(s => s.Name == pd.Name);

            // 如果找到了该参数,并且该参数的位置是在 Query 中,并且该参数的类型是可空的
            // 则设置该参数的 Required 属性为 false
            if (p != null && p.In == ParameterLocation.Query && Nullable.GetUnderlyingType(pd.Type) != null)
            {
                p.Required = false;
            }
        }

        // 设置 operation 的 OperationId 为当前方法的名称,并移除其中的 "Async" 字符串
        operation.OperationId = context.MethodInfo.Name.Replace("Async", string.Empty);
    }
}

分析:

  1. 设置 OperationId:该过滤器的主要功能是为 Swagger 文档中的每个操作设置一个 OperationId。这个 OperationId 是基于当前操作对应的方法名称,但会移除其中的 "Async" 字符串。
  2. 处理 Query 参数:对于每个操作,该过滤器还会检查其所有的 Query 参数。如果某个 Query 参数的类型是可空的(例如 int? 或 DateTime?),则该参数在 Swagger 文档中将被标记为非必需的。

从给定的代码中,我们没有看到任何与 RemoteService Name 直接相关的操作。该过滤器主要关注的是设置 OperationId 和处理 Query 参数的可选性。因此,它不会覆盖或影响 RemoteService Name 的配置。

让我们通过一个具体的例子来说明 SetOperationIdOperationFilter 过滤器的作用。

假设我们有一个名为 ProductAppService 的应用服务,其中有一个异步方法 GetProductListAsync,该方法接受一个可选的查询参数 categoryId(类型为 int?):

swift 复制代码
public class ProductAppService : ApplicationService
{
    public async Task<List<ProductDto>> GetProductListAsync(int? categoryId)
    {
        // ... 获取产品列表的逻辑 ...
    }
}

在应用 SetOperationIdOperationFilter 过滤器之前:

  • Swagger 文档中的操作可能会有一个自动生成的 OperationId,例如 GetProductListAsync。
  • categoryId 参数可能会被标记为必需的,尽管它在方法中是可选的。

在应用 SetOperationIdOperationFilter 过滤器之后:

  1. 设置 OperationId:OperationId 会从 GetProductListAsync 更改为 GetProductList,因为过滤器会移除 "Async" 后缀。
  2. 处理 Query 参数:categoryId 参数现在会被正确地标记为非必需的,因为它是一个可空的 int。

Swagger UI 中的显示效果:

  • 在操作列表中,你会看到一个名为 GetProductList 的操作,而不是 GetProductListAsync。
  • 当你点击该操作以查看详细信息时,你会看到一个名为 categoryId 的查询参数,旁边有一个标记表示它是非必需的。

这样,通过使用 SetOperationIdOperationFilter 过滤器,Swagger 文档为开发者和 API 使用者提供了更清晰、更准确的信息。

自定义过滤器-添加实体属性是否必需

这个过滤器 AssignPropertyRequiredFilter 的主要目的是为 Swagger 文档中的模型属性设置 required 标记。它基于属性的类型和其他条件来确定哪些属性是必需的。

让我们逐步分析这个过滤器并为其添加中文注释:

csharp 复制代码
public class AssignPropertyRequiredFilter : ISchemaFilter
{
    // 应用过滤器到指定的模型定义
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        // 如果模型没有属性,直接返回
        if (schema.Properties == null || schema.Properties.Count == 0)
        {
            return;
        }

        // 获取模型的所有公共实例属性
        var typeProperties = context.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var property in schema.Properties)
        {
            // 检查源类型的属性是否可为空
            if (IsSourceTypePropertyNullable(typeProperties, property.Key))
            {
                continue;
            }

            // 根据属性的类型和格式来确定是否需要将其标记为必需
            switch (property.Value.Type)
            {
                case "boolean":
                case "integer":
                case "number":
                    AddPropertyToRequired(schema, property.Key);
                    break;
                case "string":
                    switch (property.Value.Format)
                    {
                        case "date-time":
                        case "uuid":
                            AddPropertyToRequired(schema, property.Key);
                            break;
                    }
                    // 如果属性有枚举值,说明它是一个 Enum 类型,也应该被标记为必需
                    if (property.Value.Enum != null && property.Value.Enum.Any())
                    {
                        AddPropertyToRequired(schema, property.Key);
                    }
                    break;
                case "array":
                    AddPropertyToRequired(schema, property.Key);
                    break;
            }
        }
    }

    // 检查类型是否是可为空的
    private bool IsNullable(Type type)
    {
        return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
    }

    // 检查源类型的属性是否可为空
    private bool IsSourceTypePropertyNullable(PropertyInfo[] typeProperties, string propertyName)
    {
        return typeProperties.Any(info => info.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)
                                  && IsNullable(info.PropertyType));
    }

    // 将属性添加到模型的必需属性列表中
    private void AddPropertyToRequired(OpenApiSchema schema, string propertyName)
    {
        if (schema.Required == null)
        {
            schema.Required = new HashSet<string>();
        }

        if (!schema.Required.Contains(propertyName))
        {
            schema.Required.Add(propertyName);
        }
    }
}

假设我们有以下模型:

csharp 复制代码
public class ProductDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime? ManufactureDate { get; set; }
    public ProductType Type { get; set; }
}

其中 ProductType 是一个枚举。

在应用此过滤器后,Swagger 文档中的 ProductDto 模型定义将标记 Id、Name 和 Type 为必需属性,而 ManufactureDate 由于是可空的,所以不会被标记为必需。

此过滤器不会覆盖 RemoteService 的 Name 属性。

SetOperationIdOperationFilter 和 AssignPropertyRequiredFilter 在某种程度上都涉及到处理参数或属性的可空性。但它们的关注点和处理方式是不同的。

  1. SetOperationIdOperationFilter:
    • 主要关注点:为每个操作设置一个唯一的 operationId。
    • 附带功能:检查所有的 Query 参数。如果某个 Query 参数的类型是可空的,则该参数在 Swagger 文档中将被标记为非必需的。
    • 作用范围:仅限于 API 操作的 Query 参数。
  1. AssignPropertyRequiredFilter:
    • 主要关注点:为模型的属性设置 required 标记。
    • 功能:检查模型中的每个属性。基于属性的类型、格式和其他条件,确定哪些属性应该被标记为必需的。
    • 作用范围:模型的属性。

举例说明:

假设我们有以下 API 操作:

csharp 复制代码
[HttpGet]
public ProductDto GetProduct(int? id, DateTime? manufactureDate)
{
    // ...
}

和以下模型:

csharp 复制代码
public class ProductDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime ManufactureDate { get; set; }
}

在应用 SetOperationIdOperationFilter 后:

  • id 和 manufactureDate 作为 Query 参数,由于它们都是可空的,所以在 Swagger 文档中它们都将被标记为非必需的。

在应用 AssignPropertyRequiredFilter 后:

  • ProductDto 的 Id 和 Name 属性将被标记为必需的,因为它们不是可空的。而 ManufactureDate 也将被标记为必需的,因为它是一个非可空的 DateTime 类型。

总之,这两个过滤器虽然都涉及到处理可空性,但它们的作用范围和处理方式是不同的。

使用其自定义配置

在HttpApiHostModule中

首先, ConfigureServices 方法:

csharp 复制代码
public override void ConfigureServices(ServiceConfigurationContext context)
{
    // 调用SwaggerConfigurationHelper中的ConfigureWithAuth方法来配置Swagger文档,使其支持OAuth身份验证。
    SwaggerConfigurationHelper.ConfigureWithAuth(
        context: context, // 当前的服务配置上下文
        authority: configuration["AuthServer:Authority"], // OAuth2.0授权服务器的URL
        scopes: new Dictionary<string, string> // 请求的OAuth2.0作用域和它们在Swagger UI中的描述
        {
            { "LadleService", "Ladle Service API" }
        },
        apiTitle: "Ladle Service API" // Swagger文档的标题
    );
}

接下来,我们来分析 OnApplicationInitialization 方法:

csharp 复制代码
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
    // 启用Swagger中间件,这样你可以访问Swagger生成的JSON文档。
    app.UseSwagger();

    // 启用Swagger UI中间件,这样你可以使用一个友好的界面来查看和测试API。
    app.UseSwaggerUI(options =>
                     {
                         var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
                         // 设置Swagger UI要加载的JSON文档的URL。
                         options.SwaggerEndpoint("/swagger/v1/swagger.json", "Ladle Service API");

                         // 设置Swagger UI的OAuth2.0客户端ID和客户端密钥,这样你可以在Swagger UI中进行身份验证。
                         options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
                         options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
                     });
}

是否覆盖了 remoteService name ?

从给定的代码中,我们没有看到任何与remoteService name直接相关的内容。这些代码主要关注于配置Swagger和Swagger UI,特别是使其支持OAuth2.0身份验证。如果remoteService name是在其他地方定义的,那么这些代码不会覆盖它。

作用举例:

假设你有一个名为LadleService的API,它需要OAuth2.0身份验证。你希望在开发过程中使用Swagger UI来查看和测试这个API。

  1. 在ConfigureServices方法中,你配置Swagger文档以支持OAuth2.0,并指定了授权服务器的URL和请求的作用域。
  2. 在OnApplicationInitialization方法中,你启用了Swagger和Swagger UI中间件,并配置了Swagger UI以使用特定的OAuth2.0客户端ID和客户端密钥进行身份验证。
  3. 当你访问Swagger UI时,你会看到一个身份验证按钮。点击它,你将被重定向到授权服务器进行身份验证。
  4. 一旦身份验证成功,你就可以在Swagger UI中查看和测试需要身份验证的API端点了。

配置

首先,我们需要使用AddAbpSwaggerGen扩展来配置我们模块的ConfigureServices方法中的Swagger

typescript 复制代码
public override void ConfigureServices(ServiceConfigurationContext context)
{
    var services = context.Services;

    //... other configurations.

    services.AddAbpSwaggerGen(
        //SwaggerGenOptions对象options
        options =>
        {
            //指定要公开给 Swagger 的 API 的版本和元数据信息
            options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
            //指定哪些 API 文档应该包含在 Swagger 中。返回值为 true 表示包含在 Swagger 中,false 则表示不包含
            options.DocInclusionPredicate((docName, description) => true);
            //模式 ID
            options.CustomSchemaIds(type => type.FullName);

            //向 Swagger 规范中添加安全定义。安全定义描述了如何对 API 进行身份验证和授权。
            options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme. Example: "Authorization: Bearer {token}"",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey
            });

            //将安全要求添加到 Swagger 规范文件中。安全要求描述了每个操作所需要的安全定义
            options.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "Bearer"}
                    },
                    new string[] {}
                }
            });

            //包括指定的 XML 文件中的注释信息
            options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "YourProjectName.Web.xml"));

        	//添加一个枚举过滤器,用于将枚举类型值转换为字符串形式
            options.AddEnumsWithValuesFixFilters();

            //将 AbpServiceController 和 AbpController 服务和控制器的动作路由添加到 Swagger 规范中。这可以帮助生成文档并提供自定义 UI
            options.AddAbpActionConventionalRoute(new AbpControllerAssemblySetting(false));

            //设置 Swagger UI 的路由前缀
            options.RoutePrefix = string.Empty;

            //在Swagger UI上隐藏ABP端点
            options.HideAbpEndpoints();
        }
    );
}

然后我们可以通过调用我们模块的OnApplicationInitialization方法中的UseAbpSwaggerUI方法来使用SwaggerUI

csharp 复制代码
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
    var app = context.GetApplicationBuilder();

    //... other configarations.

    //启用 Swagger 中间件
    app.UseSwagger();
    // 使用 ABP 框架提供的 Swagger UI 中间件,并指定 Swagger JSON 文件的端点
    app.UseAbpSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API");
    });
    
    //... other configarations.
}
  1. app.UseSwagger(); 将启用 Swagger 中间件,以便可以在应用程序中访问生成的 Swagger 文档。该中间件将在管道中添加一个路由处理程序,用于返回 Swagger JSON 文件以供客户端使用。
  2. app.UseAbpSwaggerUI(options => { ... }); 将使用 ABP 框架提供的 Swagger UI 中间件。该中间件将在管道中添加另一个路由处理程序,用于呈现 Swagger UI。您可以使用 options 对象来配置 Swagger UI 的选项。
  3. options.SwaggerEndpoint("/swagger/v1/swagger.json", "ABPTest API"); 指定要公开给 Swagger 的 API 的 Swagger JSON 文件的端点。在这种情况下,我们将 Swagger JSON 文件设置为 /swagger/v1/swagger.json,并在 Swagger UI 中显示的 API 标题为"ABPTest API"。

请注意,在上述代码中,我们假定一个名为"v1"的 Swagger 文档已经被定义并且存在于应用程序中。如果你在 ABP 应用程序中使用了多个 Swagger 文档,则需要在 options.SwaggerEndpoint 方法中指定不同的端点和标题。

CustomSchemaIds

SwaggerGenOptions.CustomSchemaIdsSwashbuckle.AspNetCore.SwaggerGen 中的一个属性,用于指定如何生成 Swagger 文档中的模式 ID。它可以用于在文档中引用类型名称。

当您在使用 ABP 框架时,在某些情况下可能需要自定义模式 ID。例如,如果您正在使用 DTO 和应用程序服务,则默认情况下,每个 DTO 的模式 ID 都将是其完全限定类名。这可能会导致问题,因为在 Swagger UI 中,每个 DTO 都将显示为"YourCompanyName.YourProjectName.Service.Dto.YourDtoName",这可能不是用户想要看到的。

使用 CustomSchemaIds 属性,您可以更改模式 ID 的生成方式。

示例:

ini 复制代码
options.CustomSchemaIds(x => x.FullName.Replace("+", ""));

在上述示例中,我们使用了一个 lambda 表达式,将模式 ID 更改为类型的完整名称,并且删除了任何出现的加号字符。这将使 Swagger UI 中的 DTO 显示为"YourDtoName"而不是完全限定的类名。

请注意,修改模式 ID 可能会影响 SwaggerUI 中其他部分(如请求和响应模型),并且也可能与模型绑定等功能相关联。因此,请确保仔细测试任何更改。

使用Swagger与OAUTH

ABP框架默认使用OpenIddict

typescript 复制代码
public override void ConfigureServices(ServiceConfigurationContext context)
{
    var services = contex.Services;

    //... other configarations.

    services.AddAbpSwaggerGenWithOAuth(
        "https://localhost:44341",             // authority issuer发行者
        new Dictionary<string, string>         //
        {                                      // scopes作用域
            {"Test", "Test API"}               //
        },                                     //
        options =>
        {
            options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
            options.DocInclusionPredicate((docName, description) => true);
            options.CustomSchemaIds(type => type.FullName);
        }
    );
}

然后我们可以通过调用我们模块的OnApplicationInitialization方法中的UseAbpSwaggerUI方法来使用SwaggerUI

不要忘记设置OAuthClientId和OAuthClientSecret。

csharp 复制代码
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
    var app = context.GetApplicationBuilder();

    //... other configarations.

    app.UseAbpSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API");

        var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
        options.OAuthClientId("Test_Swagger"); // clientId
        options.OAuthClientSecret("1q2w3e*");  // clientSecret
    });
    
    //... other configarations.
}

services.AddAbpSwaggerGenWithOAuth 是 ABP 框架中用于配置 Swagger 和 OAuth 的扩展方法。它将为您设置 Swagger 和 Swagger UI,并使用 OAuth 进行身份验证和授权。

使用 AddAbpSwaggerGenWithOAuth,您可以使用 JWT 或令牌身份验证对您的 API 进行保护,并在 Swagger UI 中启用"授权"按钮。通过单击"授权"按钮,您可以使用 OAuth 2.0 流程进行身份验证和授权。

以下是 AddAbpSwaggerGenWithOAuth 的代码示例:

csharp 复制代码
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;

namespace YourCompanyName.YourProjectName.Web
{
    [DependsOn(
        typeof(AbpAspNetCoreMvcModule)
    )]
    public class YourProjectNameWebModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            Configure<AbpSwaggerGenOptions>(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo {Title = "My API", Version = "v1"});
                options.DocInclusionPredicate((docName, description) => true);
                options.ConfigureOAuth2("TestAPI", "test_api_secret", "Test API");
            });

            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                options.ConventionalControllers.Create(typeof(YourProjectNameApplicationModule).Assembly);
            });
        }
    }
}

在上述示例中:

  • 我们使用 Configure<AbpSwaggerGenOptions> 方法来配置 Swagger 和 Swagger UI 的选项,包括 Swagger 文档的版本、文档包含谓词和 OAuth 2.0 配置。
  • Configure<AbpSwaggerGenOptions> 方法中,我们使用 options.ConfigureOAuth2 方法配置 OAuth 2.0。该方法接受三个参数:客户端名称、客户端密码和授权范围。在这种情况下,我们将客户端名称设置为"TestAPI",客户端密码设置为"test_api_secret",将授权范围设置为"Test API"。
  • Configure<AbpAspNetCoreMvcOptions> 中,我们通过调用 options.ConventionalControllers.Create 来创建 ABP 控制器。这将使 ABP 开始扫描应用程序模块并注册任何控制器类。

现在,您的 ABP 应用程序已经配置了 Swagger 和 OAuth 2.0,并可以使用 JWT 或令牌进行身份验证和授权。您可以运行应用程序并导航到 /swagger(或其他路径,具体取决于您的配置)以查看 Swagger UI。请注意,在 Swagger UI 的顶部,有一个"授权"按钮,您可以使用它来进行 OAuth 2.0 身份验证和授权。

查看swagger.json文件

swagger.json文件中可以看到方法的operationId

在swagger文档中,检查网络即可看到请求的json文件

ABP默认生成的json中本来就有重复的operationId,只不过前缀不同。相同tag下面,不能有重复的operationId

参考文档

www.cnblogs.com/broadm/p/17...

相关推荐
计算机学姐1 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
JustinNeil1 小时前
简化Java对象转换:高效实现大对象的Entity、VO、DTO互转与代码优化
后端
青灯文案11 小时前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
微尘82 小时前
C语言存储类型 auto,register,static,extern
服务器·c语言·开发语言·c++·后端
计算机学姐2 小时前
基于PHP的电脑线上销售系统
开发语言·vscode·后端·mysql·编辑器·php·phpstorm
码拉松3 小时前
千万不要错过,优惠券设计与思考初探
后端·面试·架构
白总Server4 小时前
MongoDB解说
开发语言·数据库·后端·mongodb·golang·rust·php
计算机学姐4 小时前
基于python+django+vue的家居全屋定制系统
开发语言·vue.js·后端·python·django·numpy·web3.py
程序员-珍5 小时前
SpringBoot v2.6.13 整合 swagger
java·spring boot·后端
海里真的有鱼5 小时前
好文推荐-架构
后端