diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs index d7d3fa38c9..1a7bf31e09 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/OpenApiSchemaExtensions.cs @@ -173,6 +173,10 @@ private static void ApplyDataTypeAttribute(OpenApiSchema schema, DataTypeAttribu { schema.Format = format; } + else if (dataTypeAttribute.DataType == AnnotationsDataType.Custom) + { + schema.Format = dataTypeAttribute.CustomDataType; + } } private static void ApplyMinLengthAttribute(OpenApiSchema schema, MinLengthAttribute minLengthAttribute) diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs index f08b229f36..42648e4542 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/Fixtures/FakeController.cs @@ -34,6 +34,9 @@ public void ActionWithParameterWithBindNeverAttribute([BindNever] string param) public void ActionWithParameterWithRequiredAttribute([Required] string param) { } + public void ActionWithParameterWithCustomDataTypeAttribute([DataType("uuid")] string param) + { } + public void ActionWithParameterWithBindRequiredAttribute([BindRequired] string param) { } diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/OpenApiSchemaExtensionsTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/OpenApiSchemaExtensionsTests.cs index f01aab9e26..75e4f5fd8c 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/OpenApiSchemaExtensionsTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/OpenApiSchemaExtensionsTests.cs @@ -134,6 +134,21 @@ public static void ApplyValidationAttributes_Handles_Invalid_RangeAttribute_Valu Assert.Null(schema.Maximum); } + [Fact] + public static void ApplyValidationAttributes_Handles_DataTypeAttribute_CustomDataType_Correctly() + { + // Arrange + string customDataType = "uuid"; + var dataTypeAttribute = new DataTypeAttribute(customDataType); + var schema = new OpenApiSchema(); + + // Act + schema.ApplyValidationAttributes([dataTypeAttribute]); + + // Assert + Assert.Equal(customDataType, schema.Format); + } + private sealed class CultureSwitcher : IDisposable { private readonly CultureInfo _previous; diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/VerifyTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/VerifyTests.cs index 62c405ec63..913f5d677f 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/VerifyTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/VerifyTests.cs @@ -622,6 +622,33 @@ public async Task ApiParameterIsBoundToPath() await Verify(document); } + [Fact] + public async Task ActionWithCustomDataTypeQueryParameter() + { + var subject = Subject( + apiDescriptions: + [ + ApiDescriptionFactory.Create( + methodInfo: typeof(FakeController).GetMethod(nameof(FakeController.ActionWithParameterWithCustomDataTypeAttribute)), + groupName: "v1", + httpMethod: "POST", + relativePath: "resource", + parameterDescriptions: + [ + new ApiParameterDescription + { + Name = "param", + Source = BindingSource.Query + } + ]) + ] + ); + + var document = subject.GetSwagger("v1"); + + await Verify(document); + } + [Theory] [InlineData(nameof(FakeController.ActionWithParameterWithRequiredAttribute))] [InlineData(nameof(FakeController.ActionWithParameterWithBindRequiredAttribute))] diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/10_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/10_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt new file mode 100644 index 0000000000..07033d171c --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/10_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt @@ -0,0 +1,37 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "Test API", + "version": "V1" + }, + "paths": { + "/resource": { + "post": { + "tags": [ + "Fake" + ], + "parameters": [ + { + "name": "param", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "components": { }, + "tags": [ + { + "name": "Fake" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/8_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/8_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt new file mode 100644 index 0000000000..07033d171c --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/8_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt @@ -0,0 +1,37 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "Test API", + "version": "V1" + }, + "paths": { + "/resource": { + "post": { + "tags": [ + "Fake" + ], + "parameters": [ + { + "name": "param", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "components": { }, + "tags": [ + { + "name": "Fake" + } + ] +} \ No newline at end of file diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/9_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/9_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt new file mode 100644 index 0000000000..07033d171c --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/snapshots/9_0/VerifyTests.ActionWithCustomDataTypeQueryParameter.verified.txt @@ -0,0 +1,37 @@ +{ + "openapi": "3.0.4", + "info": { + "title": "Test API", + "version": "V1" + }, + "paths": { + "/resource": { + "post": { + "tags": [ + "Fake" + ], + "parameters": [ + { + "name": "param", + "in": "query", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "components": { }, + "tags": [ + { + "name": "Fake" + } + ] +} \ No newline at end of file