-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix minimal api json options not being respected #3378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
b8f3dda
010792e
a7f843a
c48911f
0281a56
b0baf6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| using Microsoft.AspNetCore.Http.Json; | ||
| using Microsoft.Extensions.Options; | ||
|
|
||
| namespace Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection; | ||
|
|
||
| internal sealed class ConfigureMinimalApiSwaggerGenJsonOptions(IOptions<JsonOptions> jsonOptions) : IConfigureOptions<SwaggerGenJsonOptions> | ||
| { | ||
| public void Configure(SwaggerGenJsonOptions options) | ||
| { | ||
| options.SerializerOptions = jsonOptions.Value.SerializerOptions; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| using Microsoft.AspNetCore.Mvc; | ||
| using Microsoft.Extensions.Options; | ||
|
|
||
| namespace Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection; | ||
|
|
||
| internal sealed class ConfigureMvcSwaggerGenJsonOptions(IOptions<JsonOptions> jsonOptions) : IConfigureOptions<SwaggerGenJsonOptions> | ||
| { | ||
| public void Configure(SwaggerGenJsonOptions options) | ||
| { | ||
| options.SerializerOptions = jsonOptions.Value.JsonSerializerOptions; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| using System.Text.Json; | ||
| using Microsoft.Extensions.Options; | ||
|
|
||
| namespace Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection; | ||
|
|
||
| internal sealed class ConfigureSwaggerGenJsonOptions : IPostConfigureOptions<SwaggerGenJsonOptions> | ||
| { | ||
| private readonly IEnumerable<IConfigureOptions<Microsoft.AspNetCore.Http.Json.JsonOptions>> _minimalApiConfigureOptions; | ||
| private readonly IEnumerable<IPostConfigureOptions<Microsoft.AspNetCore.Http.Json.JsonOptions>> _minimalApiPostConfigureOptions; | ||
| private readonly Microsoft.AspNetCore.Http.Json.JsonOptions _minimalApiJsonOptions; | ||
| private readonly Microsoft.AspNetCore.Mvc.JsonOptions _mvcJsonOptions; | ||
|
|
||
| public ConfigureSwaggerGenJsonOptions( | ||
| IEnumerable<IConfigureOptions<Microsoft.AspNetCore.Http.Json.JsonOptions>> minimalApiConfigureOptions, | ||
| IEnumerable<IPostConfigureOptions<Microsoft.AspNetCore.Http.Json.JsonOptions>> minimalApiPostConfigureOptions, | ||
| IOptions<Microsoft.AspNetCore.Http.Json.JsonOptions> minimalApiJsonOptions, | ||
| IOptions<Microsoft.AspNetCore.Mvc.JsonOptions> mvcJsonOptions) | ||
| { | ||
| _minimalApiConfigureOptions = minimalApiConfigureOptions; | ||
| _minimalApiPostConfigureOptions = minimalApiPostConfigureOptions; | ||
| _minimalApiJsonOptions = minimalApiJsonOptions.Value; | ||
| _mvcJsonOptions = mvcJsonOptions.Value; | ||
| } | ||
|
|
||
| public void PostConfigure(string name, SwaggerGenJsonOptions options) | ||
| { | ||
| if (options.SerializerOptions != null) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| /* | ||
| * There is no surefire way to do this. | ||
| * However, both JsonOptions are defaulted in the same way. | ||
| * If neither is configured it makes no difference which one is chosen. | ||
| * If both are configured, then we just need to make a choice. | ||
| * As Minimal APIs are newer if someone is configuring them | ||
| * it's probably more likely that is what they're using. | ||
| * | ||
| * If either JsonOptions is null we will try to create a new instance as | ||
| * a last resort as this is an expensive operation. | ||
| */ | ||
|
|
||
| var serializerOptions = _mvcJsonOptions.JsonSerializerOptions; | ||
|
|
||
| if (_minimalApiConfigureOptions.Any() || _minimalApiPostConfigureOptions.Any()) | ||
| { | ||
| serializerOptions = _minimalApiJsonOptions.SerializerOptions; | ||
| } | ||
|
|
||
| options.SerializerOptions = serializerOptions; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| using System.Text.Json; | ||
|
|
||
| namespace Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection; | ||
|
|
||
| /// <summary> | ||
| /// Configures the <see cref="JsonSerializerOptions"/> to be used by <see cref="JsonSerializerDataContractResolver"/>. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have two implementations of Maybe something like:
|
||
| /// </summary> | ||
| public class SwaggerGenJsonOptions | ||
| { | ||
| /// <summary> | ||
| /// Gets or sets the JSON serializer options to use. | ||
| /// </summary> | ||
| public JsonSerializerOptions SerializerOptions { get; set; } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection.SwaggerGenJsonOptions | ||
| Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection.SwaggerGenJsonOptions.SerializerOptions.get -> System.Text.Json.JsonSerializerOptions | ||
| Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection.SwaggerGenJsonOptions.SerializerOptions.set -> void | ||
| Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection.SwaggerGenJsonOptions.SwaggerGenJsonOptions() -> void |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| | ||
| static Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.AddSwaggerGenMinimalApisJsonOptions(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection | ||
| static Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.AddSwaggerGenMvcJsonOptions(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| | ||
| static Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.AddSwaggerGenMinimalApisJsonOptions(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection | ||
| static Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.AddSwaggerGenMvcJsonOptions(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| using Microsoft.AspNetCore.Hosting; | ||
| using Microsoft.Extensions.FileProviders; | ||
|
|
||
| namespace Swashbuckle.AspNetCore.SwaggerGen.Test.Fixtures; | ||
|
|
||
| internal sealed class DummyHostEnvironment : IWebHostEnvironment | ||
| { | ||
| public string WebRootPath { get; set; } | ||
| public IFileProvider WebRootFileProvider { get; set; } | ||
| public string ApplicationName { get; set; } | ||
| public IFileProvider ContentRootFileProvider { get; set; } | ||
| public string ContentRootPath { get; set; } | ||
| public string EnvironmentName { get; set; } | ||
| } |
ItsVeryWindy marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| using System.Text.Json; | ||
| using System.Text.Json.Serialization; | ||
| using Microsoft.AspNetCore.Hosting; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Options; | ||
| using Swashbuckle.AspNetCore.SwaggerGen.DependencyInjection; | ||
| using Swashbuckle.AspNetCore.SwaggerGen.Test.Fixtures; | ||
|
|
||
| using MinimalApiJsonOptions = Microsoft.AspNetCore.Http.Json.JsonOptions; | ||
| using MvcJsonOptions = Microsoft.AspNetCore.Mvc.JsonOptions; | ||
|
|
||
| namespace Swashbuckle.AspNetCore.SwaggerGen.Test; | ||
|
|
||
| public class SwaggerGenJsonOptionsTests | ||
martincostello marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| [Fact] | ||
| public static void Ensure_SwaggerGenJsonOptions_Uses_MinimalApi_JsonOptions_When_Overridden() | ||
| { | ||
| var services = new ServiceCollection(); | ||
| services.AddSingleton<IWebHostEnvironment, DummyHostEnvironment>(); | ||
| services.AddSwaggerGen(); | ||
| services.AddMvcCore().AddJsonOptions(o => o.JsonSerializerOptions.AllowTrailingCommas = true); | ||
| services.AddSwaggerGenMinimalApisJsonOptions(); | ||
ItsVeryWindy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| using var provider = services.BuildServiceProvider(); | ||
|
|
||
| var minimalApiJsonOptions = provider.GetService<IOptions<MinimalApiJsonOptions>>().Value.SerializerOptions; | ||
| var swaggerGenSerializerOptions = provider.GetService<IOptions<SwaggerGenJsonOptions>>().Value.SerializerOptions; | ||
| Assert.Equal(minimalApiJsonOptions, swaggerGenSerializerOptions); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void Ensure_SwaggerGenJsonOptions_Uses_Mvc_JsonOptions_When_Overridden() | ||
| { | ||
| var services = new ServiceCollection(); | ||
| services.AddSingleton<IWebHostEnvironment, DummyHostEnvironment>(); | ||
| services.AddSwaggerGen(); | ||
| services.ConfigureHttpJsonOptions(o => o.SerializerOptions.AllowTrailingCommas = true); | ||
| services.AddSwaggerGenMvcJsonOptions(); | ||
|
|
||
| using var provider = services.BuildServiceProvider(); | ||
|
|
||
| var mvcJsonOptions = provider.GetService<IOptions<MvcJsonOptions>>().Value.JsonSerializerOptions; | ||
| var swaggerGenSerializerOptions = provider.GetService<IOptions<SwaggerGenJsonOptions>>().Value.SerializerOptions; | ||
| Assert.Equal(mvcJsonOptions, swaggerGenSerializerOptions); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void Ensure_SwaggerGenJsonOptions_Uses_Mvc_JsonOptions_When_Not_Using_Minimal_Apis() | ||
ItsVeryWindy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| var services = new ServiceCollection(); | ||
| services.AddSingleton<IWebHostEnvironment, DummyHostEnvironment>(); | ||
| services.AddSwaggerGen(); | ||
| services.AddMvcCore().AddJsonOptions(o => o.JsonSerializerOptions.AllowTrailingCommas = true); | ||
|
|
||
| using var provider = services.BuildServiceProvider(); | ||
|
|
||
| var mvcJsonOptions = provider.GetService<IOptions<MvcJsonOptions>>().Value.JsonSerializerOptions; | ||
| var swaggerGenSerializerOptions = provider.GetService<IOptions<SwaggerGenJsonOptions>>().Value.SerializerOptions; | ||
| Assert.Equal(mvcJsonOptions, swaggerGenSerializerOptions); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void Ensure_SwaggerGenJsonOptions_Uses_MinimalApi_JsonOptions_When_Configured() | ||
ItsVeryWindy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| var services = new ServiceCollection(); | ||
| services.AddSingleton<IWebHostEnvironment, DummyHostEnvironment>(); | ||
| services.AddSwaggerGen(); | ||
| services.ConfigureHttpJsonOptions(o => o.SerializerOptions.AllowTrailingCommas = true); | ||
| services.AddMvcCore().AddJsonOptions(o => o.JsonSerializerOptions.AllowTrailingCommas = true); | ||
|
|
||
| using var provider = services.BuildServiceProvider(); | ||
|
|
||
| var minimalApiJsonOptions = provider.GetService<IOptions<MinimalApiJsonOptions>>().Value.SerializerOptions; | ||
| var swaggerGenSerializerOptions = provider.GetService<IOptions<SwaggerGenJsonOptions>>().Value.SerializerOptions; | ||
| Assert.Equal(minimalApiJsonOptions, swaggerGenSerializerOptions); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.