diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/DependencyInjection/SwaggerGenServiceCollectionExtensions.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/DependencyInjection/SwaggerGenServiceCollectionExtensions.cs index dddfb6a37a..09083330ca 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/DependencyInjection/SwaggerGenServiceCollectionExtensions.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/DependencyInjection/SwaggerGenServiceCollectionExtensions.cs @@ -69,17 +69,28 @@ private JsonSerializerOptions ResolveOptions() JsonSerializerOptions serializerOptions; /* - * First try to get the options configured for MVC, + * First try to get the options configured for MVC, but only when MVC is actually + * registered: IOptions resolves in any application, so in a Minimal + * APIs application it hands back MVC's own defaults and hides whatever the application + * configured through ConfigureHttpJsonOptions, * then try to get the options configured for Minimal APIs if available, * then try the default JsonSerializerOptions if available, * otherwise create a new instance as a last resort as this is an expensive operation. */ serializerOptions = - _serviceProvider.GetService>()?.Value?.JsonSerializerOptions + (IsMvcRegistered() ? _serviceProvider.GetService>()?.Value?.JsonSerializerOptions : null) ?? _serviceProvider.GetService>()?.Value?.SerializerOptions ?? JsonSerializerOptions.Default; return serializerOptions; } + + /// + /// Whether the application registered MVC, through AddControllers(), AddMvcCore() + /// or AddMvc(). IControllerFactory is registered by all three, and by nothing a + /// Minimal APIs application uses, including AddEndpointsApiExplorer(). + /// + private bool IsMvcRegistered() + => _serviceProvider.GetService() is not null; } } diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt index 715720dfb4..244e470993 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt @@ -1213,12 +1213,11 @@ }, "DateTimeKind": { "enum": [ - 0, - 1, - 2 + "Unspecified", + "Utc", + "Local" ], - "type": "integer", - "format": "int32" + "type": "string" }, "Fruit": { "type": "object", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt index 715720dfb4..244e470993 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt @@ -1213,12 +1213,11 @@ }, "DateTimeKind": { "enum": [ - 0, - 1, - 2 + "Unspecified", + "Utc", + "Local" ], - "type": "integer", - "format": "int32" + "type": "string" }, "Fruit": { "type": "object", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt index ebc52e9617..7117cd625b 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt @@ -1101,12 +1101,11 @@ }, "DateTimeKind": { "enum": [ - 0, - 1, - 2 + "Unspecified", + "Utc", + "Local" ], - "type": "integer", - "format": "int32" + "type": "string" }, "Fruit": { "type": "object", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt index ebc52e9617..7117cd625b 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt @@ -1101,12 +1101,11 @@ }, "DateTimeKind": { "enum": [ - 0, - 1, - 2 + "Unspecified", + "Utc", + "Local" ], - "type": "integer", - "format": "int32" + "type": "string" }, "Fruit": { "type": "object", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt index ebc52e9617..7117cd625b 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=WebApi.Program_swaggerRequestUri=v1.verified.txt @@ -1101,12 +1101,11 @@ }, "DateTimeKind": { "enum": [ - 0, - 1, - 2 + "Unspecified", + "Utc", + "Local" ], - "type": "integer", - "format": "int32" + "type": "string" }, "Fruit": { "type": "object", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt index ebc52e9617..7117cd625b 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.TypesAreRenderedCorrectly.verified.txt @@ -1101,12 +1101,11 @@ }, "DateTimeKind": { "enum": [ - 0, - 1, - 2 + "Unspecified", + "Utc", + "Local" ], - "type": "integer", - "format": "int32" + "type": "string" }, "Fruit": { "type": "object", diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_0f40865eabf6c897/NSwagOpenApiClient.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_0f40865eabf6c897/NSwagOpenApiClient.verified.cs index a167ef80ce..37cdba9a2c 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_0f40865eabf6c897/NSwagOpenApiClient.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_0f40865eabf6c897/NSwagOpenApiClient.verified.cs @@ -2118,9 +2118,11 @@ public partial class AsParametersRecord public System.TimeSpan ParamEight { get; set; } [Newtonsoft.Json.JsonProperty("paramNine", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public DateTimeKind ParamNine { get; set; } [Newtonsoft.Json.JsonProperty("paramTen", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public DateTimeKind ParamTen { get; set; } [Newtonsoft.Json.JsonProperty("paramEleven", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -2153,11 +2155,14 @@ public partial class CurrenciesRate public enum DateTimeKind { - _0 = 0, + [System.Runtime.Serialization.EnumMember(Value = @"Unspecified")] + Unspecified = 0, - _1 = 1, + [System.Runtime.Serialization.EnumMember(Value = @"Utc")] + Utc = 1, - _2 = 2, + [System.Runtime.Serialization.EnumMember(Value = @"Local")] + Local = 2, } diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_26cad9664eb2cfd7/NSwagOpenApiClient.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_26cad9664eb2cfd7/NSwagOpenApiClient.verified.cs index a167ef80ce..37cdba9a2c 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_26cad9664eb2cfd7/NSwagOpenApiClient.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_26cad9664eb2cfd7/NSwagOpenApiClient.verified.cs @@ -2118,9 +2118,11 @@ public partial class AsParametersRecord public System.TimeSpan ParamEight { get; set; } [Newtonsoft.Json.JsonProperty("paramNine", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public DateTimeKind ParamNine { get; set; } [Newtonsoft.Json.JsonProperty("paramTen", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public DateTimeKind ParamTen { get; set; } [Newtonsoft.Json.JsonProperty("paramEleven", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -2153,11 +2155,14 @@ public partial class CurrenciesRate public enum DateTimeKind { - _0 = 0, + [System.Runtime.Serialization.EnumMember(Value = @"Unspecified")] + Unspecified = 0, - _1 = 1, + [System.Runtime.Serialization.EnumMember(Value = @"Utc")] + Utc = 1, - _2 = 2, + [System.Runtime.Serialization.EnumMember(Value = @"Local")] + Local = 2, } diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs index e258019dbe..94c09271bb 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs @@ -94,9 +94,23 @@ public partial class AsParametersRequestBuilderGetQueryParameters [QueryParameter("paramFour")] public DateTimeOffset? ParamFour { get; set; } #pragma warning restore CS1591 + [Obsolete("This property is deprecated, use ParamNineAsDateTimeKind instead")] +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER +#nullable enable + #pragma warning disable CS1591 + [QueryParameter("paramNine")] + public string? ParamNine { get; set; } + #pragma warning restore CS1591 +#nullable restore +#else + #pragma warning disable CS1591 + [QueryParameter("paramNine")] + public string ParamNine { get; set; } + #pragma warning restore CS1591 +#endif #pragma warning disable CS1591 [QueryParameter("paramNine")] - public int? ParamNine { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamNineAsDateTimeKind { get; set; } #pragma warning restore CS1591 /// Description [QueryParameter("paramOne")] @@ -109,9 +123,23 @@ public partial class AsParametersRequestBuilderGetQueryParameters [QueryParameter("paramSix")] public Date? ParamSix { get; set; } #pragma warning restore CS1591 + [Obsolete("This property is deprecated, use ParamTenAsDateTimeKind instead")] +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER +#nullable enable + #pragma warning disable CS1591 + [QueryParameter("paramTen")] + public string? ParamTen { get; set; } + #pragma warning restore CS1591 +#nullable restore +#else + #pragma warning disable CS1591 + [QueryParameter("paramTen")] + public string ParamTen { get; set; } + #pragma warning restore CS1591 +#endif #pragma warning disable CS1591 [QueryParameter("paramTen")] - public int? ParamTen { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamTenAsDateTimeKind { get; set; } #pragma warning restore CS1591 #pragma warning disable CS1591 [QueryParameter("paramThree")] diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Models/AsParametersRecord.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Models/AsParametersRecord.verified.cs index b703f26d0a..f49e82266f 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Models/AsParametersRecord.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Models/AsParametersRecord.verified.cs @@ -22,7 +22,7 @@ public partial class AsParametersRecord : IParsable /// The paramFour property public DateTimeOffset? ParamFour { get; set; } /// The paramNine property - public int? ParamNine { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamNine { get; set; } /// The paramOne property public Guid? ParamOne { get; set; } /// The paramSeven property @@ -30,7 +30,7 @@ public partial class AsParametersRecord : IParsable /// The paramSix property public Date? ParamSix { get; set; } /// The paramTen property - public int? ParamTen { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamTen { get; set; } /// The paramThree property public DateTimeOffset? ParamThree { get; set; } /// The paramTwelve property @@ -59,11 +59,11 @@ public virtual IDictionary> GetFieldDeserializers() { "paramEleven", n => { ParamEleven = n.GetDoubleValue(); } }, { "paramFive", n => { ParamFive = n.GetDateValue(); } }, { "paramFour", n => { ParamFour = n.GetDateTimeOffsetValue(); } }, - { "paramNine", n => { ParamNine = n.GetIntValue(); } }, + { "paramNine", n => { ParamNine = n.GetEnumValue(); } }, { "paramOne", n => { ParamOne = n.GetGuidValue(); } }, { "paramSeven", n => { ParamSeven = n.GetTimeValue(); } }, { "paramSix", n => { ParamSix = n.GetDateValue(); } }, - { "paramTen", n => { ParamTen = n.GetIntValue(); } }, + { "paramTen", n => { ParamTen = n.GetEnumValue(); } }, { "paramThree", n => { ParamThree = n.GetDateTimeOffsetValue(); } }, { "paramTwelve", n => { ParamTwelve = n.GetDoubleValue(); } }, { "paramTwo", n => { ParamTwo = n.GetGuidValue(); } }, @@ -80,11 +80,11 @@ public virtual void Serialize(ISerializationWriter writer) writer.WriteDoubleValue("paramEleven", ParamEleven); writer.WriteDateValue("paramFive", ParamFive); writer.WriteDateTimeOffsetValue("paramFour", ParamFour); - writer.WriteIntValue("paramNine", ParamNine); + writer.WriteEnumValue("paramNine", ParamNine); writer.WriteGuidValue("paramOne", ParamOne); writer.WriteTimeValue("paramSeven", ParamSeven); writer.WriteDateValue("paramSix", ParamSix); - writer.WriteIntValue("paramTen", ParamTen); + writer.WriteEnumValue("paramTen", ParamTen); writer.WriteDateTimeOffsetValue("paramThree", ParamThree); writer.WriteDoubleValue("paramTwelve", ParamTwelve); writer.WriteGuidValue("paramTwo", ParamTwo); diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Models/DateTimeKindObject.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Models/DateTimeKindObject.verified.cs new file mode 100644 index 0000000000..d7639d15ed --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_37257a4c78cad6df/Models/DateTimeKindObject.verified.cs @@ -0,0 +1,24 @@ +// +using System.Runtime.Serialization; +using System; +namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum DateTimeKindObject + #pragma warning restore CS1591 + { + [EnumMember(Value = "Unspecified")] + #pragma warning disable CS1591 + Unspecified, + #pragma warning restore CS1591 + [EnumMember(Value = "Utc")] + #pragma warning disable CS1591 + Utc, + #pragma warning restore CS1591 + [EnumMember(Value = "Local")] + #pragma warning disable CS1591 + Local, + #pragma warning restore CS1591 + } +} diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs index e258019dbe..94c09271bb 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Annotations/AsParameters/AsParametersRequestBuilder.verified.cs @@ -94,9 +94,23 @@ public partial class AsParametersRequestBuilderGetQueryParameters [QueryParameter("paramFour")] public DateTimeOffset? ParamFour { get; set; } #pragma warning restore CS1591 + [Obsolete("This property is deprecated, use ParamNineAsDateTimeKind instead")] +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER +#nullable enable + #pragma warning disable CS1591 + [QueryParameter("paramNine")] + public string? ParamNine { get; set; } + #pragma warning restore CS1591 +#nullable restore +#else + #pragma warning disable CS1591 + [QueryParameter("paramNine")] + public string ParamNine { get; set; } + #pragma warning restore CS1591 +#endif #pragma warning disable CS1591 [QueryParameter("paramNine")] - public int? ParamNine { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamNineAsDateTimeKind { get; set; } #pragma warning restore CS1591 /// Description [QueryParameter("paramOne")] @@ -109,9 +123,23 @@ public partial class AsParametersRequestBuilderGetQueryParameters [QueryParameter("paramSix")] public Date? ParamSix { get; set; } #pragma warning restore CS1591 + [Obsolete("This property is deprecated, use ParamTenAsDateTimeKind instead")] +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER +#nullable enable + #pragma warning disable CS1591 + [QueryParameter("paramTen")] + public string? ParamTen { get; set; } + #pragma warning restore CS1591 +#nullable restore +#else + #pragma warning disable CS1591 + [QueryParameter("paramTen")] + public string ParamTen { get; set; } + #pragma warning restore CS1591 +#endif #pragma warning disable CS1591 [QueryParameter("paramTen")] - public int? ParamTen { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamTenAsDateTimeKind { get; set; } #pragma warning restore CS1591 #pragma warning disable CS1591 [QueryParameter("paramThree")] diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Models/AsParametersRecord.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Models/AsParametersRecord.verified.cs index b703f26d0a..f49e82266f 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Models/AsParametersRecord.verified.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Models/AsParametersRecord.verified.cs @@ -22,7 +22,7 @@ public partial class AsParametersRecord : IParsable /// The paramFour property public DateTimeOffset? ParamFour { get; set; } /// The paramNine property - public int? ParamNine { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamNine { get; set; } /// The paramOne property public Guid? ParamOne { get; set; } /// The paramSeven property @@ -30,7 +30,7 @@ public partial class AsParametersRecord : IParsable /// The paramSix property public Date? ParamSix { get; set; } /// The paramTen property - public int? ParamTen { get; set; } + public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.DateTimeKindObject? ParamTen { get; set; } /// The paramThree property public DateTimeOffset? ParamThree { get; set; } /// The paramTwelve property @@ -59,11 +59,11 @@ public virtual IDictionary> GetFieldDeserializers() { "paramEleven", n => { ParamEleven = n.GetDoubleValue(); } }, { "paramFive", n => { ParamFive = n.GetDateValue(); } }, { "paramFour", n => { ParamFour = n.GetDateTimeOffsetValue(); } }, - { "paramNine", n => { ParamNine = n.GetIntValue(); } }, + { "paramNine", n => { ParamNine = n.GetEnumValue(); } }, { "paramOne", n => { ParamOne = n.GetGuidValue(); } }, { "paramSeven", n => { ParamSeven = n.GetTimeValue(); } }, { "paramSix", n => { ParamSix = n.GetDateValue(); } }, - { "paramTen", n => { ParamTen = n.GetIntValue(); } }, + { "paramTen", n => { ParamTen = n.GetEnumValue(); } }, { "paramThree", n => { ParamThree = n.GetDateTimeOffsetValue(); } }, { "paramTwelve", n => { ParamTwelve = n.GetDoubleValue(); } }, { "paramTwo", n => { ParamTwo = n.GetGuidValue(); } }, @@ -80,11 +80,11 @@ public virtual void Serialize(ISerializationWriter writer) writer.WriteDoubleValue("paramEleven", ParamEleven); writer.WriteDateValue("paramFive", ParamFive); writer.WriteDateTimeOffsetValue("paramFour", ParamFour); - writer.WriteIntValue("paramNine", ParamNine); + writer.WriteEnumValue("paramNine", ParamNine); writer.WriteGuidValue("paramOne", ParamOne); writer.WriteTimeValue("paramSeven", ParamSeven); writer.WriteDateValue("paramSix", ParamSix); - writer.WriteIntValue("paramTen", ParamTen); + writer.WriteEnumValue("paramTen", ParamTen); writer.WriteDateTimeOffsetValue("paramThree", ParamThree); writer.WriteDoubleValue("paramTwelve", ParamTwelve); writer.WriteGuidValue("paramTwo", ParamTwo); diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Models/DateTimeKindObject.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Models/DateTimeKindObject.verified.cs new file mode 100644 index 0000000000..d7639d15ed --- /dev/null +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_59c743f9eff9e6b2/Models/DateTimeKindObject.verified.cs @@ -0,0 +1,24 @@ +// +using System.Runtime.Serialization; +using System; +namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models +{ + [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")] + #pragma warning disable CS1591 + public enum DateTimeKindObject + #pragma warning restore CS1591 + { + [EnumMember(Value = "Unspecified")] + #pragma warning disable CS1591 + Unspecified, + #pragma warning restore CS1591 + [EnumMember(Value = "Utc")] + #pragma warning disable CS1591 + Utc, + #pragma warning restore CS1591 + [EnumMember(Value = "Local")] + #pragma warning disable CS1591 + Local, + #pragma warning restore CS1591 + } +} diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenServiceCollectionExtensionsTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenServiceCollectionExtensionsTests.cs new file mode 100644 index 0000000000..2e9f11596f --- /dev/null +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenServiceCollectionExtensionsTests.cs @@ -0,0 +1,99 @@ +using System.Text.Json; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using NSubstitute; + +namespace Swashbuckle.AspNetCore.SwaggerGen.Test; + +public static class SwaggerGenServiceCollectionExtensionsTests +{ + [Fact] + public static void AddSwaggerGen_UsesMinimalApiJsonOptions_WhenMvcIsNotRegistered() + { + // IOptions resolves even in an application that never registered MVC, + // so without a registration check its camelCase default would win over what the + // application actually configured for Minimal APIs. + var services = CreateServices(); + services.ConfigureHttpJsonOptions((options) => options.SerializerOptions.PropertyNamingPolicy = MinimalApiNamingPolicy); + services.AddSwaggerGen(); + + var contract = ResolveDataContract(services); + + Assert.Equal("HelloWorld-minimal-api", Assert.Single(contract.ObjectProperties).Name); + } + + [Fact] + public static void AddSwaggerGen_UsesMvcJsonOptions_WhenMvcIsRegistered() + { + var services = CreateServices(); + services.AddControllers().AddJsonOptions((options) => options.JsonSerializerOptions.PropertyNamingPolicy = MvcNamingPolicy); + services.AddSwaggerGen(); + + var contract = ResolveDataContract(services); + + Assert.Equal("HelloWorld-mvc", Assert.Single(contract.ObjectProperties).Name); + } + + [Fact] + public static void AddSwaggerGen_PrefersMvcJsonOptions_WhenBothAreRegistered() + { + // A document describes every endpoint with one set of serializer options, so when an + // application registers both, MVC keeps precedence as it always has. + var services = CreateServices(); + services.ConfigureHttpJsonOptions((options) => options.SerializerOptions.PropertyNamingPolicy = MinimalApiNamingPolicy); + services.AddControllers().AddJsonOptions((options) => options.JsonSerializerOptions.PropertyNamingPolicy = MvcNamingPolicy); + services.AddSwaggerGen(); + + var contract = ResolveDataContract(services); + + Assert.Equal("HelloWorld-mvc", Assert.Single(contract.ObjectProperties).Name); + } + + [Fact] + public static void AddSwaggerGen_UsesCamelCase_WhenNothingIsConfigured() + { + // Both option types default to the web defaults, so neither branch is observable here. + var services = CreateServices(); + services.AddSwaggerGen(); + + var contract = ResolveDataContract(services); + + Assert.Equal("helloWorld", Assert.Single(contract.ObjectProperties).Name); + } + + private static JsonNamingPolicy MinimalApiNamingPolicy { get; } = new SuffixNamingPolicy("-minimal-api"); + + private static JsonNamingPolicy MvcNamingPolicy { get; } = new SuffixNamingPolicy("-mvc"); + + private static ServiceCollection CreateServices() + { + var services = new ServiceCollection(); + services.AddOptions(); + services.AddLogging(); + + var hostEnvironment = Substitute.For(); + hostEnvironment.ApplicationName.Returns(typeof(SwaggerGenServiceCollectionExtensionsTests).Assembly.GetName().Name); + services.AddSingleton(hostEnvironment); + services.AddSingleton(hostEnvironment); + + return services; + } + + private static DataContract ResolveDataContract(IServiceCollection services) + { + using var provider = services.BuildServiceProvider(); + var resolver = provider.GetRequiredService(); + return resolver.GetDataContractForType(typeof(Dto)); + } + + private sealed class SuffixNamingPolicy(string suffix) : JsonNamingPolicy + { + public override string ConvertName(string name) => name + suffix; + } + + private class Dto + { + public string HelloWorld { get; set; } + } +}