From 8c8379201485aa0fe36d3f0961dd00301e5075c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa=20de=20la=20Noceda=20Arg=C3=BCelles?= Date: Thu, 20 Jun 2024 23:51:23 +0200 Subject: [PATCH 1/5] Adding support for .Net8 Model State Attributes --- .../SchemaGenerator/OpenApiSchemaExtensions.cs | 16 ++++++++++++++++ .../NewtonsoftSchemaGeneratorTests.cs | 3 +++ .../JsonSerializerSchemaGeneratorTests.cs | 3 +++ .../Fixtures/TypeWithValidationAttributes.cs | 11 ++++++++--- ...ypeWithValidationAttributesViaMetadataType.cs | 11 ++++++++--- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs index 0d8fc813a8..e90af0f727 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs @@ -47,6 +47,9 @@ public static void ApplyValidationAttributes(this OpenApiSchema schema, IEnumera else if (attribute is LengthAttribute lengthAttribute) ApplyLengthAttribute(schema, lengthAttribute); + else if (attribute is Base64StringAttribute base64Attribute) + ApplyBase64Attribute(schema); + #endif else if (attribute is RangeAttribute rangeAttribute) @@ -169,10 +172,23 @@ private static void ApplyLengthAttribute(OpenApiSchema schema, LengthAttribute l } } + private static void ApplyBase64Attribute(OpenApiSchema schema) + { + if (schema.Type == "string") + { + schema.Format = "byte"; + } + } + #endif private static void ApplyRangeAttribute(OpenApiSchema schema, RangeAttribute rangeAttribute) { +#if NET8_0_OR_GREATER + schema.ExclusiveMinimum = rangeAttribute.MinimumIsExclusive; + schema.ExclusiveMaximum = rangeAttribute.MaximumIsExclusive; +#endif + schema.Maximum = decimal.TryParse(rangeAttribute.Maximum.ToString(), out decimal maximum) ? maximum : schema.Maximum; diff --git a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs index 11d284ab6d..fc0a0e55d7 100644 --- a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs @@ -322,6 +322,9 @@ public void GenerateSchema_SetsValidationProperties_IfComplexTypeHasValidationAt Assert.Equal(3, schema.Properties["StringWithLength"].MaxLength); Assert.Equal(1, schema.Properties["ArrayWithLength"].MinItems); Assert.Equal(3, schema.Properties["ArrayWithLength"].MaxItems); + Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMinimum); + Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMaximum); + Assert.Equal("byte", schema.Properties["StringWithBase64"].Format); #endif Assert.Equal(1, schema.Properties["IntWithRange"].Minimum); Assert.Equal(10, schema.Properties["IntWithRange"].Maximum); diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs index 3771bfb46c..a540adfe18 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs @@ -345,6 +345,9 @@ public void GenerateSchema_SetsValidationProperties_IfComplexTypeHasValidationAt Assert.Equal(3, schema.Properties["StringWithLength"].MaxLength); Assert.Equal(1, schema.Properties["ArrayWithLength"].MinItems); Assert.Equal(3, schema.Properties["ArrayWithLength"].MaxItems); + Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMinimum); + Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMaximum); + Assert.Equal("byte", schema.Properties["StringWithBase64"].Format); #endif Assert.Equal(1, schema.Properties["IntWithRange"].Minimum); Assert.Equal(10, schema.Properties["IntWithRange"].Maximum); diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs index 9ee38bd305..891c6ac517 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs @@ -20,11 +20,16 @@ public class TypeWithValidationAttributes [Length(1, 3)] public string[] ArrayWithLength { get; set; } - -#endif - + [Range(1, 10, MinimumIsExclusive = true, MaximumIsExclusive = true)] + public int IntWithRange { get; set; } + [Base64String] + public string StringWithBase64 { get; set; } +#else [Range(1, 10)] public int IntWithRange { get; set; } +#endif + + [RegularExpression("^[3-6]?\\d{12,15}$")] public string StringWithRegularExpression { get; set; } diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs index 603605e3b5..280fd6ba86 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs @@ -17,6 +17,7 @@ public class TypeWithValidationAttributesViaMetadataType public string StringWithLength { get; set; } public string[] ArrayWithLength { get; set; } + public string StringWithBase64 { get; set; } #endif @@ -46,14 +47,18 @@ public class MetadataType [Length(1, 3)] public string StringWithLength { get; set; } - [Length(1, 3)] public string[] ArrayWithLength { get; set; } -#endif - + [Range(1, 10, MinimumIsExclusive = true, MaximumIsExclusive = true)] + public int IntWithRange { get; set; } + [Base64String] + public string StringWithBase64 { get; set; } +#else [Range(1, 10)] public int IntWithRange { get; set; } +#endif + [RegularExpression("^[3-6]?\\d{12,15}$")] public string StringWithRegularExpression { get; set; } From 454168b213feb3fb1421ff9416c088dabecb4b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa=20de=20la=20Noceda=20Arg=C3=BCelles?= Date: Fri, 21 Jun 2024 02:56:37 +0200 Subject: [PATCH 2/5] Do apply the format when Bas64Attribute, do not check the tyoe --- .../SchemaGenerator/OpenApiSchemaExtensions.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs index e90af0f727..285062df57 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs @@ -174,10 +174,7 @@ private static void ApplyLengthAttribute(OpenApiSchema schema, LengthAttribute l private static void ApplyBase64Attribute(OpenApiSchema schema) { - if (schema.Type == "string") - { - schema.Format = "byte"; - } + schema.Format = "byte"; } #endif From e41e240e2287bfb7c1e4fb341cbbb75445a53da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa=20de=20la=20Noceda=20Arg=C3=BCelles?= Date: Fri, 21 Jun 2024 09:50:43 +0200 Subject: [PATCH 3/5] Keep spacing consistent in compilation regions --- .../SchemaGenerator/OpenApiSchemaExtensions.cs | 2 ++ .../Fixtures/TypeWithValidationAttributes.cs | 5 +++-- .../TypeWithValidationAttributesViaMetadataType.cs | 7 ++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs index 285062df57..0c4391fe52 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs @@ -182,8 +182,10 @@ private static void ApplyBase64Attribute(OpenApiSchema schema) private static void ApplyRangeAttribute(OpenApiSchema schema, RangeAttribute rangeAttribute) { #if NET8_0_OR_GREATER + schema.ExclusiveMinimum = rangeAttribute.MinimumIsExclusive; schema.ExclusiveMaximum = rangeAttribute.MaximumIsExclusive; + #endif schema.Maximum = decimal.TryParse(rangeAttribute.Maximum.ToString(), out decimal maximum) diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs index 891c6ac517..99d05ca654 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs @@ -24,12 +24,13 @@ public class TypeWithValidationAttributes public int IntWithRange { get; set; } [Base64String] public string StringWithBase64 { get; set; } + #else + [Range(1, 10)] public int IntWithRange { get; set; } -#endif - +#endif [RegularExpression("^[3-6]?\\d{12,15}$")] public string StringWithRegularExpression { get; set; } diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs index 280fd6ba86..18c96ca157 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributesViaMetadataType.cs @@ -17,6 +17,7 @@ public class TypeWithValidationAttributesViaMetadataType public string StringWithLength { get; set; } public string[] ArrayWithLength { get; set; } + public string StringWithBase64 { get; set; } #endif @@ -47,18 +48,22 @@ public class MetadataType [Length(1, 3)] public string StringWithLength { get; set; } + [Length(1, 3)] public string[] ArrayWithLength { get; set; } [Range(1, 10, MinimumIsExclusive = true, MaximumIsExclusive = true)] public int IntWithRange { get; set; } + [Base64String] public string StringWithBase64 { get; set; } + #else + [Range(1, 10)] public int IntWithRange { get; set; } -#endif +#endif [RegularExpression("^[3-6]?\\d{12,15}$")] public string StringWithRegularExpression { get; set; } From 3f2cff252136ffaf670b1718e4760a11a2d376b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa=20de=20la=20Noceda=20Arg=C3=BCelles?= Date: Fri, 21 Jun 2024 10:18:49 +0200 Subject: [PATCH 4/5] More spacing fix --- .../Fixtures/TypeWithValidationAttributes.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs index 99d05ca654..9687d571ca 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithValidationAttributes.cs @@ -20,8 +20,10 @@ public class TypeWithValidationAttributes [Length(1, 3)] public string[] ArrayWithLength { get; set; } + [Range(1, 10, MinimumIsExclusive = true, MaximumIsExclusive = true)] public int IntWithRange { get; set; } + [Base64String] public string StringWithBase64 { get; set; } From 2adbc710d6ec4c3284e93e1345513302cef8acf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Garc=C3=ADa=20de=20la=20Noceda=20Arg=C3=BCelles?= Date: Fri, 21 Jun 2024 18:48:57 +0200 Subject: [PATCH 5/5] Add type comparision for StringWithBase64 --- .../SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs | 1 + .../SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs index fc0a0e55d7..2a1529888d 100644 --- a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs @@ -325,6 +325,7 @@ public void GenerateSchema_SetsValidationProperties_IfComplexTypeHasValidationAt Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMinimum); Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMaximum); Assert.Equal("byte", schema.Properties["StringWithBase64"].Format); + Assert.Equal("string", schema.Properties["StringWithBase64"].Type); #endif Assert.Equal(1, schema.Properties["IntWithRange"].Minimum); Assert.Equal(10, schema.Properties["IntWithRange"].Maximum); diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs index a540adfe18..bfe407c63b 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs @@ -348,6 +348,7 @@ public void GenerateSchema_SetsValidationProperties_IfComplexTypeHasValidationAt Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMinimum); Assert.Equal(true, schema.Properties["IntWithRange"].ExclusiveMaximum); Assert.Equal("byte", schema.Properties["StringWithBase64"].Format); + Assert.Equal("string", schema.Properties["StringWithBase64"].Type); #endif Assert.Equal(1, schema.Properties["IntWithRange"].Minimum); Assert.Equal(10, schema.Properties["IntWithRange"].Maximum);