diff --git a/SimApi.csproj b/SimApi.csproj index 165c706..c50873a 100644 --- a/SimApi.csproj +++ b/SimApi.csproj @@ -9,7 +9,7 @@ AspNetCore一个方便的API文档,捕获异常,统一输入输出的API类库 Simcu.SimApi enable - net8.0;net9.0 + net8.0;net9.0;net10.0 true @@ -20,11 +20,11 @@ - + - - + + diff --git a/SimApiExtensions.cs b/SimApiExtensions.cs index 9e7056e..3853b5a 100644 --- a/SimApiExtensions.cs +++ b/SimApiExtensions.cs @@ -9,7 +9,7 @@ using Hangfire.Redis.StackExchange; using SimApi.Helpers; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using SimApi.Middlewares; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Mvc; diff --git a/SwaggerFilters/AesBodyOperationFilter.cs b/SwaggerFilters/AesBodyOperationFilter.cs index 59b2164..62822c5 100644 --- a/SwaggerFilters/AesBodyOperationFilter.cs +++ b/SwaggerFilters/AesBodyOperationFilter.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; using System.Linq; +using Microsoft.OpenApi; using SimApi.Attributes; namespace SimApi.SwaggerFilters; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; diff --git a/SwaggerFilters/GlobalDynamicObjectSchemaFilter.cs b/SwaggerFilters/GlobalDynamicObjectSchemaFilter.cs index a32783c..e344da7 100644 --- a/SwaggerFilters/GlobalDynamicObjectSchemaFilter.cs +++ b/SwaggerFilters/GlobalDynamicObjectSchemaFilter.cs @@ -1,27 +1,26 @@ using System; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; using System.Collections; using System.Collections.Generic; -using System.Reflection; -using Microsoft.OpenApi.Any; +using System.Text.Json.Nodes; namespace SimApi.SwaggerFilters; public class GlobalDynamicObjectSchemaFilter : ISchemaFilter { - public void Apply(OpenApiSchema schema, SchemaFilterContext context) + public void Apply(IOpenApiSchema schema, SchemaFilterContext context) { if (!IsDynamicObjectType(context.Type)) return; - schema.AdditionalPropertiesAllowed = true; - schema.AdditionalProperties = new OpenApiSchema + var oaSchema = schema as OpenApiSchema; + oaSchema.AdditionalPropertiesAllowed = true; + oaSchema.AdditionalProperties = new OpenApiSchema { - Type = "object", // 表示 value 可以是任意类型(兼容所有类型) - Nullable = true + Type = JsonSchemaType.Object, // 表示 value 可以是任意类型(兼容所有类型) }; // 2. 覆盖默认示例,使用包含多种类型的示例 - schema.Example = CreateMultiTypeExample(); + oaSchema.Example = CreateMultiTypeExample(); } // 判断是否为需要处理的“动态对象”类型 @@ -33,30 +32,39 @@ public class GlobalDynamicObjectSchemaFilter : ISchemaFilter { return true; } + if (type == typeof(object)) { return true; } + return type.Name.Contains("AnonymousType") && type.Namespace == null; } // 创建包含多种类型的示例(覆盖默认的 string 示例) - private OpenApiObject CreateMultiTypeExample() + private JsonNode CreateMultiTypeExample() { - return new OpenApiObject + return new JsonObject { - ["stringProp"] = new OpenApiString("example string"), // 字符串 - ["numberProp"] = new OpenApiInteger(123), // 数字 - ["boolProp"] = new OpenApiBoolean(true), // 布尔值 - ["objectProp"] = new OpenApiObject // 嵌套对象 + // 字符串类型:JsonValue.Create 包装字符串 + ["stringProp"] = JsonValue.Create("example string"), + // 数字类型:支持 int/long/double 等,JsonValue 自动适配 + ["numberProp"] = JsonValue.Create(123), + // 布尔类型 + ["boolProp"] = JsonValue.Create(true), + // 嵌套对象:JsonObject 对应 OpenApiObject + ["objectProp"] = new JsonObject { - ["nestedKey"] = new OpenApiString("nested value") + ["nestedKey"] = JsonValue.Create("nested value") }, - ["arrayProp"] = new OpenApiArray // 数组 + // 数组类型:JsonArray 对应 OpenApiArray + ["arrayProp"] = new JsonArray { - new OpenApiInteger(1), - new OpenApiString("two") - } + JsonValue.Create(1), // 数组内数字 + JsonValue.Create("two") // 数组内字符串 + }, + // 可选:添加 null 值示例(若需要) + ["nullProp"] = null }; } } \ No newline at end of file diff --git a/SwaggerFilters/SimApiAuthOperationFilter.cs b/SwaggerFilters/SimApiAuthOperationFilter.cs index 4744e29..f5ec8ee 100644 --- a/SwaggerFilters/SimApiAuthOperationFilter.cs +++ b/SwaggerFilters/SimApiAuthOperationFilter.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; using SimApi.Attributes; @@ -18,28 +18,24 @@ namespace SimApi.SwaggerFilters || // 控制器上有 [SimApiAuth](继承到所有方法) context.MethodInfo.DeclaringType?.GetCustomAttributes(true).Any() == true; - if (requiresAuth) + if (!requiresAuth) return; + + // 关键修复:正确构造 OpenApiSecuritySchemeReference(匹配键类型要求) + var securitySchemeRef = new OpenApiSecuritySchemeReference( + referenceId: "SimApiAuth", // 必须与 AddSecurityDefinition 的 ID 一致 + hostDocument: null, + externalResource: null + ); + + // 给 Security 赋值(确保键类型是 OpenApiSecuritySchemeReference) + operation.Security ??= new List(); + operation.Security.Add(new OpenApiSecurityRequirement { - // 添加授权要求:关联步骤 2 中定义的 "SimApiAuth" 安全方案 - operation.Security = new List { - new OpenApiSecurityRequirement - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "SimApiAuth" // 必须与 AddSecurityDefinition 的第一个参数一致 - } - }, - [] // 无需指定作用域(scope)时留空 - } - } - }; - } - // 未标记 [SimApiAuth] 的接口:不添加安全要求,Swagger 不显示锁图标 + securitySchemeRef, + [] + } + }); } } } \ No newline at end of file diff --git a/SwaggerFilters/SimApiResponseOperationFilter.cs b/SwaggerFilters/SimApiResponseOperationFilter.cs index d0056ea..d57d851 100644 --- a/SwaggerFilters/SimApiResponseOperationFilter.cs +++ b/SwaggerFilters/SimApiResponseOperationFilter.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; using System.Threading.Tasks; diff --git a/SwaggerFilters/SimApiSignOperationFilter.cs b/SwaggerFilters/SimApiSignOperationFilter.cs index e584d79..098693a 100644 --- a/SwaggerFilters/SimApiSignOperationFilter.cs +++ b/SwaggerFilters/SimApiSignOperationFilter.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using SimApi.Attributes; using SimApi.ModelBinders; using Swashbuckle.AspNetCore.SwaggerGen; @@ -67,20 +67,24 @@ public class SimApiSignOperationFilter(IServiceProvider serviceProvider) : IOper signParameters.AddRange(keyProvider.SignFields.Where(x => x != keyProvider.AppIdName) .Select(f => (f, string.Empty, true))); + operation.Parameters ??= new List(); + foreach (var (name, description, required) in signParameters) { if (operation.Parameters?.Any(p => p.Name == name) == true) { var tmp = operation.Parameters?.FirstOrDefault(p => p.Name == name); - if (tmp != null) + if (tmp is OpenApiParameter concreteParam) { - tmp.Required = required; - tmp.Description = description; + // 重新赋值只读属性(通过实例化新对象覆盖,或直接修改具体类的可写属性) + concreteParam.Required = required; // OpenApiParameter 的 Required 有 setter + concreteParam.Description = description; } + continue; } - operation.Parameters ??= new List(); + operation.Parameters ??= new List(); operation.Parameters.Add(new OpenApiParameter { Name = name, @@ -89,7 +93,7 @@ public class SimApiSignOperationFilter(IServiceProvider serviceProvider) : IOper Required = required, Schema = new OpenApiSchema { - Type = "string" // 签名相关参数通常为字符串类型 + Type = JsonSchemaType.String // 签名相关参数通常为字符串类型 } }); }