From b06654cc13574b66df655541a60688fd562baee7 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:39:07 +0100 Subject: [PATCH 01/26] Install .NET 10 in GHA workflows --- .github/workflows/build.yml | 3 +++ .github/workflows/codeql.yml | 1 + .github/workflows/qodana.yml | 1 + 3 files changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35313888ef..843f291fb2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,7 @@ jobs: dotnet-version: | 8.0.* 9.0.* + 10.0.* - name: Show installed versions shell: pwsh run: | @@ -159,6 +160,7 @@ jobs: dotnet-version: | 8.0.* 9.0.* + 10.0.* - name: Git checkout uses: actions/checkout@v5 - name: Restore tools @@ -218,6 +220,7 @@ jobs: dotnet-version: | 8.0.* 9.0.* + 10.0.* - name: Git checkout uses: actions/checkout@v5 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0ff1bb17be..35c8171615 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,6 +28,7 @@ jobs: dotnet-version: | 8.0.* 9.0.* + 10.0.* - name: Git checkout uses: actions/checkout@v5 - name: Initialize CodeQL diff --git a/.github/workflows/qodana.yml b/.github/workflows/qodana.yml index 6a91aebccc..83405f8027 100644 --- a/.github/workflows/qodana.yml +++ b/.github/workflows/qodana.yml @@ -27,6 +27,7 @@ jobs: dotnet-version: | 8.0.* 9.0.* + 10.0.* - name: Git checkout uses: actions/checkout@v5 with: From 117bbc689291c8871d022718d75ec60081dbfaed Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:38:22 +0100 Subject: [PATCH 02/26] Update to new R# major version --- .config/dotnet-tools.json | 2 +- .github/workflows/build.yml | 3 +++ cleanupcode.ps1 | 3 +++ inspectcode.ps1 | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 9f4b9f1d56..4cd65cb7fd 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2025.2.4", + "version": "2025.3.0.2", "commands": [ "jb" ], diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 843f291fb2..3e9f8edd9c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -170,6 +170,7 @@ jobs: run: | $inspectCodeOutputPath = Join-Path $env:RUNNER_TEMP 'jetbrains-inspectcode-results.xml' Write-Output "INSPECT_CODE_OUTPUT_PATH=$inspectCodeOutputPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + dotnet jb inspectcode --version dotnet jb inspectcode JsonApiDotNetCore.sln --build --dotnetcoresdk=$(dotnet --version) --output="$inspectCodeOutputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal - name: Upload output to artifacts uses: actions/upload-artifact@v4 @@ -239,12 +240,14 @@ jobs: $baseCommitHash = git rev-parse HEAD~1 Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request." + dotnet jb cleanupcode --version dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff - name: CleanupCode (on branch) if: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'workflow_dispatch' }} shell: pwsh run: | Write-Output 'Running code cleanup on all files.' + dotnet jb cleanupcode --version dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff publish: diff --git a/cleanupcode.ps1 b/cleanupcode.ps1 index b35d1cb215..d87c58a342 100644 --- a/cleanupcode.ps1 +++ b/cleanupcode.ps1 @@ -28,17 +28,20 @@ if ($revision) { if ($baseCommitHash -eq $headCommitHash) { Write-Output "Running code cleanup on staged/unstaged files." + dotnet jb cleanupcode --version dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified VerifySuccessExitCode } else { Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash, including staged/unstaged files." + dotnet jb cleanupcode --version dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash VerifySuccessExitCode } } else { Write-Output "Running code cleanup on all files." + dotnet jb cleanupcode --version dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN VerifySuccessExitCode } diff --git a/inspectcode.ps1 b/inspectcode.ps1 index 21e96eac67..e3ae50660b 100644 --- a/inspectcode.ps1 +++ b/inspectcode.ps1 @@ -10,6 +10,7 @@ if ($LastExitCode -ne 0) { $outputPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.xml') $resultPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.html') +dotnet jb inspectcode --version dotnet jb inspectcode JsonApiDotNetCore.sln --dotnetcoresdk=$(dotnet --version) --build --output="$outputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal if ($LastExitCode -ne 0) { From 72c62dd9a451c0d997b634970005531678e54177 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 21 Nov 2025 01:04:24 +0100 Subject: [PATCH 03/26] Change severity of new R# inspections to warning --- JsonApiDotNetCore.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/JsonApiDotNetCore.sln.DotSettings b/JsonApiDotNetCore.sln.DotSettings index 3576ab2bd8..e340302b69 100644 --- a/JsonApiDotNetCore.sln.DotSettings +++ b/JsonApiDotNetCore.sln.DotSettings @@ -72,8 +72,10 @@ WARNING SUGGESTION SUGGESTION + WARNING SUGGESTION WARNING + WARNING DO_NOT_SHOW WARNING WARNING From 6de8ade949c0049e5b41c1432c067b00d38d02e9 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:39:39 +0100 Subject: [PATCH 04/26] Resharper: use field keyword --- .../IntegrationTests/EagerLoading/Building.cs | 8 +++----- .../SerializerChangeTrackingTests.cs | 17 ++++++----------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs index 78ab514636..3e66be191c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs @@ -9,8 +9,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.EagerLoading; [Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.EagerLoading")] public sealed class Building : Identifiable { - private string? _tempPrimaryDoorColor; - [Attr] public string Number { get; set; } = null!; @@ -24,7 +22,7 @@ public string PrimaryDoorColor { get { - if (_tempPrimaryDoorColor == null && PrimaryDoor == null) + if (field == null && PrimaryDoor == null) { // The ASP.NET model validator reads the value of this required property, to ensure it is not null. // When creating a resource, BuildingDefinition ensures a value is assigned. But when updating a resource @@ -33,7 +31,7 @@ public string PrimaryDoorColor return null!; } - return _tempPrimaryDoorColor ?? PrimaryDoor!.Color; + return field ?? PrimaryDoor!.Color; } set { @@ -41,7 +39,7 @@ public string PrimaryDoorColor { // A request body is being deserialized. At this time, related entities have not been loaded yet. // We cache the assigned value in a private field, so it can be used later. - _tempPrimaryDoorColor = value; + field = value; } else { diff --git a/test/OpenApiNSwagClientTests/ChangeTracking/SerializerChangeTrackingTests.cs b/test/OpenApiNSwagClientTests/ChangeTracking/SerializerChangeTrackingTests.cs index fb1e1f4b19..b0ca3c51bc 100644 --- a/test/OpenApiNSwagClientTests/ChangeTracking/SerializerChangeTrackingTests.cs +++ b/test/OpenApiNSwagClientTests/ChangeTracking/SerializerChangeTrackingTests.cs @@ -802,13 +802,11 @@ public async Task Can_track_multiple_times_in_same_request_document() [UsedImplicitly(ImplicitUseTargetFlags.Members)] private sealed class ComplexType : NotifyPropertySet { - private DateTime? _nullableDateTime; - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] public DateTime? NullableDateTime { - get => _nullableDateTime; - set => SetProperty(ref _nullableDateTime, value); + get; + set => SetProperty(ref field, value); } public NestedType? NestedType { get; set; } @@ -817,21 +815,18 @@ public DateTime? NullableDateTime [UsedImplicitly(ImplicitUseTargetFlags.Members)] private sealed class NestedType : NotifyPropertySet { - private int? _nullableInt; - private string? _nullableString; - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] public int? NullableInt { - get => _nullableInt; - set => SetProperty(ref _nullableInt, value); + get; + set => SetProperty(ref field, value); } [JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)] public string? NullableString { - get => _nullableString; - set => SetProperty(ref _nullableString, value); + get; + set => SetProperty(ref field, value); } } From 3ff65835899f0cac2382238c8ab18c4c613bd564 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:35:24 +0100 Subject: [PATCH 05/26] Fix IDE0340: Use unbound generic type --- .../TreeNodes/TableSourceNode.cs | 2 +- .../DocumentationOpenApiOperationFilter.cs | 19 +++++++++---------- .../JsonApiDataContractResolver.cs | 2 +- .../Configuration/JsonApiValidationFilter.cs | 2 +- .../Configuration/ResourceGraphBuilder.cs | 2 +- .../Errors/InvalidModelStateException.cs | 2 +- .../Queries/Parsing/FilterParser.cs | 2 +- .../Queries/QueryLayerComposer.cs | 2 +- .../Queries/SparseFieldSetCache.cs | 2 +- ...parseFieldSetQueryStringParameterReader.cs | 2 +- .../Resources/IdentifiableExtensions.cs | 2 +- .../JsonConverters/ResourceObjectConverter.cs | 2 +- .../Serialization/Response/LinkBuilder.cs | 8 +++----- .../Response/ResponseModelAdapter.cs | 2 +- .../CompositeKeys/CarExpressionRewriter.cs | 2 +- .../ReadWrite/Creating/CreateResourceTests.cs | 6 +++--- ...reateResourceWithClientGeneratedIdTests.cs | 12 ++++++------ .../Updating/Resources/UpdateResourceTests.cs | 4 ++-- .../ResourceGraphBuilderTests.cs | 2 +- test/TestBuildingBlocks/Unknown.cs | 2 +- 20 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableSourceNode.cs b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableSourceNode.cs index 62ff5ad3ef..4b0fa2d5b5 100644 --- a/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableSourceNode.cs +++ b/src/Examples/DapperExample/TranslationToSql/TreeNodes/TableSourceNode.cs @@ -7,7 +7,7 @@ namespace DapperExample.TranslationToSql.TreeNodes; /// internal abstract class TableSourceNode(string? alias) : SqlTreeNode { - public const string IdColumnName = nameof(Identifiable.Id); + public const string IdColumnName = nameof(Identifiable<>.Id); public abstract IReadOnlyList Columns { get; } public string? Alias { get; } = alias; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs index caeb40e96b..b34b580f66 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs @@ -5,7 +5,6 @@ using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata.ActionMethods; -using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.Net.Http.Headers; @@ -18,15 +17,15 @@ namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] internal sealed class DocumentationOpenApiOperationFilter : IOperationFilter { - private const string GetPrimaryName = nameof(BaseJsonApiController, int>.GetAsync); - private const string GetSecondaryName = nameof(BaseJsonApiController, int>.GetSecondaryAsync); - private const string GetRelationshipName = nameof(BaseJsonApiController, int>.GetRelationshipAsync); - private const string PostResourceName = nameof(BaseJsonApiController, int>.PostAsync); - private const string PostRelationshipName = nameof(BaseJsonApiController, int>.PostRelationshipAsync); - private const string PatchResourceName = nameof(BaseJsonApiController, int>.PatchAsync); - private const string PatchRelationshipName = nameof(BaseJsonApiController, int>.PatchRelationshipAsync); - private const string DeleteResourceName = nameof(BaseJsonApiController, int>.DeleteAsync); - private const string DeleteRelationshipName = nameof(BaseJsonApiController, int>.DeleteRelationshipAsync); + private const string GetPrimaryName = nameof(BaseJsonApiController<,>.GetAsync); + private const string GetSecondaryName = nameof(BaseJsonApiController<,>.GetSecondaryAsync); + private const string GetRelationshipName = nameof(BaseJsonApiController<,>.GetRelationshipAsync); + private const string PostResourceName = nameof(BaseJsonApiController<,>.PostAsync); + private const string PostRelationshipName = nameof(BaseJsonApiController<,>.PostRelationshipAsync); + private const string PatchResourceName = nameof(BaseJsonApiController<,>.PatchAsync); + private const string PatchRelationshipName = nameof(BaseJsonApiController<,>.PatchRelationshipAsync); + private const string DeleteResourceName = nameof(BaseJsonApiController<,>.DeleteAsync); + private const string DeleteRelationshipName = nameof(BaseJsonApiController<,>.DeleteRelationshipAsync); private const string PostOperationsName = nameof(BaseJsonApiOperationsController.PostOperationsAsync); private const string TextCompareETag = diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/JsonApiDataContractResolver.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/JsonApiDataContractResolver.cs index dcc652c696..c4e6fbfd39 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/JsonApiDataContractResolver.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/JsonApiDataContractResolver.cs @@ -63,7 +63,7 @@ private List GetDataPropertiesThatExistInResourceClrType(Type reso foreach (DataProperty property in dataContract.ObjectProperties) { - if (property.MemberInfo.Name == nameof(Identifiable.Id)) + if (property.MemberInfo.Name == nameof(Identifiable<>.Id)) { // Schemas of JsonApiDotNetCore resources will obtain an Id property through inheritance of a resource identifier type. continue; diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs b/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs index 30b850e8b8..8d7a4a29e5 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiValidationFilter.cs @@ -61,7 +61,7 @@ private IServiceProvider GetScopedServiceProvider() private static bool IsId(string key) { - return key == nameof(Identifiable.Id) || key.EndsWith($".{nameof(Identifiable.Id)}", StringComparison.Ordinal); + return key == nameof(Identifiable<>.Id) || key.EndsWith($".{nameof(Identifiable<>.Id)}", StringComparison.Ordinal); } private static bool IsAtPrimaryEndpoint(IJsonApiRequest request) diff --git a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs index a10d6a904c..cabc8bcc06 100644 --- a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs +++ b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs @@ -299,7 +299,7 @@ private Dictionary.ValueCollection GetAttributes(Type res if (attribute == null) { - if (property.Name == nameof(Identifiable.Id)) + if (property.Name == nameof(Identifiable<>.Id)) { // Although strictly not correct, 'id' is added to the list of attributes for convenience. // For example, it enables to filter on ID, without the need to special-case existing logic. diff --git a/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs b/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs index fc85156e57..2c46313e34 100644 --- a/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs +++ b/src/JsonApiDotNetCore/Errors/InvalidModelStateException.cs @@ -134,7 +134,7 @@ private static List FromModelStateDictionary(IReadOnlyDictionary.Id) + string sourcePointer = attribute.Property.Name == nameof(Identifiable<>.Id) ? $"{segment.SourcePointer ?? "/data"}/{attribute.PublicName}" : $"{segment.SourcePointer ?? "/data"}/attributes/{attribute.PublicName}"; diff --git a/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs b/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs index 3babdae45e..34f88f1c77 100644 --- a/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs +++ b/src/JsonApiDotNetCore/Queries/Parsing/FilterParser.cs @@ -540,7 +540,7 @@ protected virtual ConstantValueConverter GetConstantValueConverterForType(Type d private ConstantValueConverter GetConstantValueConverterForAttribute(AttrAttribute attribute) { - if (attribute is { Property.Name: nameof(Identifiable.Id) }) + if (attribute is { Property.Name: nameof(Identifiable<>.Id) }) { return (stringValue, position) => { diff --git a/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs b/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs index 020040e928..c8fe4c5495 100644 --- a/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs +++ b/src/JsonApiDotNetCore/Queries/QueryLayerComposer.cs @@ -620,6 +620,6 @@ protected virtual PaginationExpression GetPagination(IReadOnlyCollection.Id)); + return resourceType.GetAttributeByPropertyName(nameof(Identifiable<>.Id)); } } diff --git a/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs b/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs index 0df2d5af75..f2c5593ab1 100644 --- a/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs +++ b/src/JsonApiDotNetCore/Queries/SparseFieldSetCache.cs @@ -94,7 +94,7 @@ public IImmutableSet GetIdAttributeSetForRelationshipQuery(Resour { ArgumentNullException.ThrowIfNull(resourceType); - AttrAttribute idAttribute = resourceType.GetAttributeByPropertyName(nameof(Identifiable.Id)); + AttrAttribute idAttribute = resourceType.GetAttributeByPropertyName(nameof(Identifiable<>.Id)); var inputExpression = new SparseFieldSetExpression(ImmutableHashSet.Create(idAttribute)); // Intentionally not cached, as we are fetching ID only (ignoring any sparse fieldset that came from query string). diff --git a/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs b/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs index 308fe44588..454fb34c49 100644 --- a/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/SparseFieldSetQueryStringParameterReader.cs @@ -85,7 +85,7 @@ private SparseFieldSetExpression GetSparseFieldSet(string parameterValue, Resour if (sparseFieldSet == null) { // We add ID to an incoming empty fieldset, so that callers can distinguish between no fieldset and an empty one. - AttrAttribute idAttribute = resourceType.GetAttributeByPropertyName(nameof(Identifiable.Id)); + AttrAttribute idAttribute = resourceType.GetAttributeByPropertyName(nameof(Identifiable<>.Id)); return new SparseFieldSetExpression(ImmutableHashSet.Create(idAttribute)); } diff --git a/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs b/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs index d4e3c156cb..678c308ed4 100644 --- a/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs +++ b/src/JsonApiDotNetCore/Resources/IdentifiableExtensions.cs @@ -4,7 +4,7 @@ namespace JsonApiDotNetCore.Resources; internal static class IdentifiableExtensions { - private const string IdPropertyName = nameof(Identifiable.Id); + private const string IdPropertyName = nameof(Identifiable<>.Id); public static object GetTypedId(this IIdentifiable identifiable) { diff --git a/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs b/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs index 529c76a1d2..e66550fbac 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonConverters/ResourceObjectConverter.cs @@ -204,7 +204,7 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver { object? attributeValue; - if (property.Name == nameof(Identifiable.Id)) + if (property.Name == nameof(Identifiable<>.Id)) { attributeValue = JsonInvalidAttributeInfo.Id; } diff --git a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs index df712d6eec..1fec12996f 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs @@ -22,11 +22,9 @@ public class LinkBuilder : ILinkBuilder private const string PageSizeParameterName = "page[size]"; private const string PageNumberParameterName = "page[number]"; - private static readonly string GetPrimaryControllerActionName = NoAsyncSuffix(nameof(BaseJsonApiController, int>.GetAsync)); - private static readonly string GetSecondaryControllerActionName = NoAsyncSuffix(nameof(BaseJsonApiController, int>.GetSecondaryAsync)); - - private static readonly string GetRelationshipControllerActionName = - NoAsyncSuffix(nameof(BaseJsonApiController, int>.GetRelationshipAsync)); + private static readonly string GetPrimaryControllerActionName = NoAsyncSuffix(nameof(BaseJsonApiController<,>.GetAsync)); + private static readonly string GetSecondaryControllerActionName = NoAsyncSuffix(nameof(BaseJsonApiController<,>.GetSecondaryAsync)); + private static readonly string GetRelationshipControllerActionName = NoAsyncSuffix(nameof(BaseJsonApiController<,>.GetRelationshipAsync)); private static readonly UriNormalizer UriNormalizer = new(); diff --git a/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs b/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs index 80f7809255..036373b8a5 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/ResponseModelAdapter.cs @@ -247,7 +247,7 @@ protected virtual ResourceObject ConvertResource(IIdentifiable resource, Resourc foreach (AttrAttribute attr in resourceType.Attributes) { - if (!fieldSet.Contains(attr) || attr.Property.Name == nameof(Identifiable.Id)) + if (!fieldSet.Contains(attr) || attr.Property.Name == nameof(Identifiable<>.Id)) { continue; } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs index e7802bcb09..1e4234c259 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarExpressionRewriter.cs @@ -75,7 +75,7 @@ public CarExpressionRewriter(IResourceGraph resourceGraph) private static bool IsCarId(PropertyInfo property) { - return property.Name == nameof(Identifiable.Id) && property.DeclaringType == typeof(Car); + return property.Name == nameof(Identifiable<>.Id) && property.DeclaringType == typeof(Car); } private QueryExpression RewriteFilterOnCarStringIds(ResourceFieldChainExpression existingCarIdChain, IEnumerable carStringIds) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs index 004fcb2121..cd420d0bd9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs @@ -112,7 +112,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => workItemInDatabase.DueAt.Should().Be(newWorkItem.DueAt); }); - PropertyInfo? property = typeof(WorkItem).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(WorkItem).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -160,7 +160,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => userAccountInDatabase.LastName.Should().Be(newUserAccount.LastName); }); - PropertyInfo? property = typeof(UserAccount).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(UserAccount).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -205,7 +205,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => groupInDatabase.Name.Should().Be(newGroup.Name); }); - PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs index 681dc034c2..160cd3864a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs @@ -78,7 +78,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => groupInDatabase.Name.Should().Be(groupName); }); - PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -132,7 +132,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => groupInDatabase.Name.Should().Be(groupName); }); - PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -183,7 +183,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase.DisplayName.Should().Be(newColor.DisplayName); }); - PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -234,7 +234,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase.DisplayName.Should().Be(newColor.DisplayName); }); - PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -290,7 +290,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase.DisplayName.Should().Be(defaultName); }); - PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -473,7 +473,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase.DisplayName.Should().Be(newColor.DisplayName); }); - PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs index 428c4a30d3..cf8ec690b7 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs @@ -325,7 +325,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => groupInDatabase.IsPublic.Should().Be(existingGroup.IsPublic); }); - PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(WorkItemGroup).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } @@ -373,7 +373,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => colorInDatabase.DisplayName.Should().Be(newDisplayName); }); - PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable.Id)); + PropertyInfo? property = typeof(RgbColor).GetProperty(nameof(Identifiable<>.Id)); property.Should().NotBeNull(); property.PropertyType.Should().Be(); } diff --git a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs index 6ed5b6c67a..597a5d9d89 100644 --- a/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs +++ b/test/JsonApiDotNetCoreTests/UnitTests/ResourceGraph/ResourceGraphBuilderTests.cs @@ -413,7 +413,7 @@ public void Can_override_capabilities_on_Id_property() IResourceGraph resourceGraph = builder.Build(); ResourceType resourceType = resourceGraph.GetResourceType(); - AttrAttribute idAttribute = resourceType.GetAttributeByPropertyName(nameof(Identifiable.Id)); + AttrAttribute idAttribute = resourceType.GetAttributeByPropertyName(nameof(Identifiable<>.Id)); idAttribute.Capabilities.Should().Be(AttrCapabilities.AllowFilter); } diff --git a/test/TestBuildingBlocks/Unknown.cs b/test/TestBuildingBlocks/Unknown.cs index a777435228..79227fddf3 100644 --- a/test/TestBuildingBlocks/Unknown.cs +++ b/test/TestBuildingBlocks/Unknown.cs @@ -79,7 +79,7 @@ private static string InnerFor(bool isAlt) } throw new NotSupportedException( - $"Unsupported '{nameof(Identifiable.Id)}' property of type '{type}' on resource type '{typeof(TResource).Name}'."); + $"Unsupported '{nameof(Identifiable<>.Id)}' property of type '{type}' on resource type '{typeof(TResource).Name}'."); } } } From 947d606ea61f7e80a200346da81507a2f84ef828 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:45:05 +0100 Subject: [PATCH 06/26] Add net10.0 to target frameworks --- benchmarks/Benchmarks.csproj | 2 +- src/Examples/DapperExample/DapperExample.csproj | 2 +- .../DatabasePerTenantExample/DatabasePerTenantExample.csproj | 2 +- src/Examples/GettingStarted/GettingStarted.csproj | 2 +- .../JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj | 2 +- src/Examples/MultiDbContextExample/MultiDbContextExample.csproj | 2 +- .../NoEntityFrameworkExample/NoEntityFrameworkExample.csproj | 2 +- .../OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj | 2 +- .../OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj | 2 +- src/Examples/ReportsExample/ReportsExample.csproj | 2 +- .../JsonApiDotNetCore.Annotations.csproj | 2 +- .../JsonApiDotNetCore.OpenApi.Client.Kiota.csproj | 2 +- .../JsonApiDotNetCore.OpenApi.Client.NSwag.csproj | 2 +- .../JsonApiDotNetCore.OpenApi.Swashbuckle.csproj | 2 +- src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 2 +- test/AnnotationTests/AnnotationTests.csproj | 2 +- test/DapperTests/DapperTests.csproj | 2 +- test/DiscoveryTests/DiscoveryTests.csproj | 2 +- test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj | 2 +- test/MultiDbContextTests/MultiDbContextTests.csproj | 2 +- test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj | 2 +- test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj | 2 +- test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj | 2 +- test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj | 2 +- test/OpenApiTests/OpenApiTests.csproj | 2 +- test/SourceGeneratorTests/SourceGeneratorTests.csproj | 2 +- test/TestBuildingBlocks/TestBuildingBlocks.csproj | 2 +- test/UnitTests/UnitTests.csproj | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj index 90d53461d2..6bd78a5cdd 100644 --- a/benchmarks/Benchmarks.csproj +++ b/benchmarks/Benchmarks.csproj @@ -1,7 +1,7 @@ Exe - net9.0 + net10.0 true diff --git a/src/Examples/DapperExample/DapperExample.csproj b/src/Examples/DapperExample/DapperExample.csproj index 0685dc0343..d06e92ef7f 100644 --- a/src/Examples/DapperExample/DapperExample.csproj +++ b/src/Examples/DapperExample/DapperExample.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj b/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj index 3edc993428..c7cee804b1 100644 --- a/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj +++ b/src/Examples/DatabasePerTenantExample/DatabasePerTenantExample.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/src/Examples/GettingStarted/GettingStarted.csproj b/src/Examples/GettingStarted/GettingStarted.csproj index 611aeb37a5..806fdf45a5 100644 --- a/src/Examples/GettingStarted/GettingStarted.csproj +++ b/src/Examples/GettingStarted/GettingStarted.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj index 768a2de827..58feac6a6d 100644 --- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj +++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 true GeneratedSwagger diff --git a/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj b/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj index 611aeb37a5..806fdf45a5 100644 --- a/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj +++ b/src/Examples/MultiDbContextExample/MultiDbContextExample.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj index 15a485c08f..e50874f733 100644 --- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj +++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/src/Examples/OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj b/src/Examples/OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj index 8f65b2b688..8dd3e2e4df 100644 --- a/src/Examples/OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj +++ b/src/Examples/OpenApiKiotaClientExample/OpenApiKiotaClientExample.csproj @@ -1,6 +1,6 @@ - net9.0 + net10.0 diff --git a/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj index c30833a39a..079e43121c 100644 --- a/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj +++ b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj index 6ade1386be..73a16ddf4f 100644 --- a/src/Examples/ReportsExample/ReportsExample.csproj +++ b/src/Examples/ReportsExample/ReportsExample.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj b/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj index d615476081..fd646bfd78 100644 --- a/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj +++ b/src/JsonApiDotNetCore.Annotations/JsonApiDotNetCore.Annotations.csproj @@ -1,6 +1,6 @@ - net8.0;netstandard1.0 + net10.0;net8.0;netstandard1.0 true true JsonApiDotNetCore diff --git a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj index 640b949477..fce1fb7c40 100644 --- a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj +++ b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj @@ -1,6 +1,6 @@  - net8.0 + net10.0;net8.0 true true false diff --git a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj index 20e2306730..550f284509 100644 --- a/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj +++ b/src/JsonApiDotNetCore.OpenApi.Client.NSwag/JsonApiDotNetCore.OpenApi.Client.NSwag.csproj @@ -1,6 +1,6 @@  - net8.0 + net10.0;net8.0 true true false diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj index 4a57ca1c85..a32d89a5ec 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0;net8.0 true true false diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj index d36600e878..009c7d8656 100644 --- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj +++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0;net8.0 true true diff --git a/test/AnnotationTests/AnnotationTests.csproj b/test/AnnotationTests/AnnotationTests.csproj index 885e9f769c..6d2bfff1e6 100644 --- a/test/AnnotationTests/AnnotationTests.csproj +++ b/test/AnnotationTests/AnnotationTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0;netstandard2.0 + net10.0;net9.0;net8.0;netstandard2.0 diff --git a/test/DapperTests/DapperTests.csproj b/test/DapperTests/DapperTests.csproj index 1d7fc6184d..d4b9a3e661 100644 --- a/test/DapperTests/DapperTests.csproj +++ b/test/DapperTests/DapperTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/test/DiscoveryTests/DiscoveryTests.csproj b/test/DiscoveryTests/DiscoveryTests.csproj index 11567b9113..d92d81790f 100644 --- a/test/DiscoveryTests/DiscoveryTests.csproj +++ b/test/DiscoveryTests/DiscoveryTests.csproj @@ -1,6 +1,6 @@  - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj b/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj index bdfea682d9..e74bbc8d3d 100644 --- a/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj +++ b/test/JsonApiDotNetCoreTests/JsonApiDotNetCoreTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/test/MultiDbContextTests/MultiDbContextTests.csproj b/test/MultiDbContextTests/MultiDbContextTests.csproj index e80f03c69e..524270f7e2 100644 --- a/test/MultiDbContextTests/MultiDbContextTests.csproj +++ b/test/MultiDbContextTests/MultiDbContextTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj index 4deb6b21cd..9ff82322ba 100644 --- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj +++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj b/test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj index 4e5e8dded9..b3c6215934 100644 --- a/test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj +++ b/test/OpenApiKiotaEndToEndTests/OpenApiKiotaEndToEndTests.csproj @@ -1,6 +1,6 @@ - net9.0 + net10.0 diff --git a/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj index b005d3786f..23d45e95ab 100644 --- a/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj +++ b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 diff --git a/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj index 0c716f4be5..021ad0342e 100644 --- a/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj +++ b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 diff --git a/test/OpenApiTests/OpenApiTests.csproj b/test/OpenApiTests/OpenApiTests.csproj index 8d9336f54a..5700b77798 100644 --- a/test/OpenApiTests/OpenApiTests.csproj +++ b/test/OpenApiTests/OpenApiTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 True false $(NoWarn);1591 diff --git a/test/SourceGeneratorTests/SourceGeneratorTests.csproj b/test/SourceGeneratorTests/SourceGeneratorTests.csproj index 4f487fa168..61946fbc1a 100644 --- a/test/SourceGeneratorTests/SourceGeneratorTests.csproj +++ b/test/SourceGeneratorTests/SourceGeneratorTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/test/TestBuildingBlocks/TestBuildingBlocks.csproj b/test/TestBuildingBlocks/TestBuildingBlocks.csproj index 4d66eac8a6..3174e64374 100644 --- a/test/TestBuildingBlocks/TestBuildingBlocks.csproj +++ b/test/TestBuildingBlocks/TestBuildingBlocks.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj index 68076a51e1..503547d0c5 100644 --- a/test/UnitTests/UnitTests.csproj +++ b/test/UnitTests/UnitTests.csproj @@ -1,6 +1,6 @@ - net9.0;net8.0 + net10.0;net9.0;net8.0 From 717768f78dc88e49857759310ca183ab9b6b3d09 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:57:23 +0100 Subject: [PATCH 07/26] Update versions, add workaround for missing stable/unstable packages for EF Core 10 --- Directory.Build.props | 11 +++++++++++ package-versions.props | 15 +++++++++++++++ src/Examples/DapperExample/DapperExample.csproj | 6 +++--- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index e5323c6c76..11975ee095 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,6 +15,17 @@ direct + + + + $(NoWarn);NU1608 + + + + 10.0.0 + + + 10.0.* + 10.0.*-* + + + 9.0.* + + + N/A @@ -42,6 +55,7 @@ 9.0.* 9.0.* + $(EntityFrameworkCoreVersion) @@ -51,5 +65,6 @@ 8.0.* 8.0.* + $(EntityFrameworkCoreVersion) diff --git a/src/Examples/DapperExample/DapperExample.csproj b/src/Examples/DapperExample/DapperExample.csproj index d06e92ef7f..f34631b4a8 100644 --- a/src/Examples/DapperExample/DapperExample.csproj +++ b/src/Examples/DapperExample/DapperExample.csproj @@ -1,4 +1,4 @@ - + net10.0;net9.0;net8.0 @@ -13,9 +13,9 @@ - + - + From 056dce40dea617189f84c14e93a5621f03d26b85 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:12:34 +0100 Subject: [PATCH 08/26] Fix warning CA1873: Evaluation of this argument may be expensive and unnecessary if logging is disabled --- .../JsonApiActionDescriptorCollectionProvider.cs | 11 ++--------- .../QueryStrings/QueryStringReader.cs | 9 +++++++-- test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs | 2 ++ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiActionDescriptorCollectionProvider.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiActionDescriptorCollectionProvider.cs index c11683b50d..77be1e7ce1 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiActionDescriptorCollectionProvider.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiActionDescriptorCollectionProvider.cs @@ -17,7 +17,6 @@ using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Logging; namespace JsonApiDotNetCore.OpenApi.Swashbuckle; @@ -27,7 +26,7 @@ namespace JsonApiDotNetCore.OpenApi.Swashbuckle; /// /article/{id}/{relationshipName} -> /article/{id}/author, /article/{id}/revisions, etc. /// ]]> /// -internal sealed partial class JsonApiActionDescriptorCollectionProvider : IActionDescriptorCollectionProvider +internal sealed class JsonApiActionDescriptorCollectionProvider : IActionDescriptorCollectionProvider { private const int FilterScope = 10; private static readonly Type ErrorDocumentType = typeof(ErrorResponseDocument); @@ -35,24 +34,21 @@ internal sealed partial class JsonApiActionDescriptorCollectionProvider : IActio private readonly IActionDescriptorCollectionProvider _defaultProvider; private readonly IControllerResourceMapping _controllerResourceMapping; private readonly JsonApiEndpointMetadataProvider _jsonApiEndpointMetadataProvider; - private readonly ILogger _logger; private readonly ConcurrentDictionary> _versionedActionDescriptorCache = new(); public ActionDescriptorCollection ActionDescriptors => _versionedActionDescriptorCache.GetOrAdd(_defaultProvider.ActionDescriptors.Version, LazyGetActionDescriptors).Value; public JsonApiActionDescriptorCollectionProvider(IActionDescriptorCollectionProvider defaultProvider, IControllerResourceMapping controllerResourceMapping, - JsonApiEndpointMetadataProvider jsonApiEndpointMetadataProvider, ILogger logger) + JsonApiEndpointMetadataProvider jsonApiEndpointMetadataProvider) { ArgumentNullException.ThrowIfNull(defaultProvider); ArgumentNullException.ThrowIfNull(controllerResourceMapping); ArgumentNullException.ThrowIfNull(jsonApiEndpointMetadataProvider); - ArgumentNullException.ThrowIfNull(logger); _defaultProvider = defaultProvider; _controllerResourceMapping = controllerResourceMapping; _jsonApiEndpointMetadataProvider = jsonApiEndpointMetadataProvider; - _logger = logger; } private Lazy LazyGetActionDescriptors(int version) @@ -478,7 +474,4 @@ private static void SetNonPrimaryResponseMetadata(ActionDescriptor descriptor, descriptorsByRelationship[relationship] = relationshipDescriptor; } - - [LoggerMessage(Level = LogLevel.Warning, Message = "Hiding unsupported custom JSON:API action method [{HttpMethods}] {ActionMethod} in OpenAPI.")] - private partial void LogSuppressedActionMethod(string httpMethods, string? actionMethod); } diff --git a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs index 89337708e7..8e58d1a1ff 100644 --- a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs @@ -47,7 +47,11 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) if (reader != null) { - LogParameterAccepted(parameterName, parameterValue, reader.GetType().Name); + if (_logger.IsEnabled(LogLevel.Debug)) + { + string readerType = reader.GetType().Name; + LogParameterAccepted(parameterName, parameterValue, readerType); + } if (!reader.AllowEmptyValue && string.IsNullOrEmpty(parameterValue)) { @@ -74,7 +78,8 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) } } - [LoggerMessage(Level = LogLevel.Debug, Message = "Query string parameter '{ParameterName}' with value '{ParameterValue}' was accepted by {ReaderType}.")] + [LoggerMessage(Level = LogLevel.Debug, SkipEnabledCheck = true, + Message = "Query string parameter '{ParameterName}' with value '{ParameterValue}' was accepted by {ReaderType}.")] private partial void LogParameterAccepted(string parameterName, StringValues parameterValue, string readerType); [LoggerMessage(Level = LogLevel.Debug, Message = "Query string parameter '{ParameterName}' was successfully read.")] diff --git a/test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs b/test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs index 4b981f81d2..514ba19c51 100644 --- a/test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs +++ b/test/TestBuildingBlocks/XUnitLogHttpMessageHandler.cs @@ -1,6 +1,8 @@ using Microsoft.Extensions.Logging; using Xunit.Abstractions; +#pragma warning disable CA1873 // Avoid potentially expensive logging + namespace TestBuildingBlocks; /// From 67ba27513fcf9084c701109f6f13e592d9da470c Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:25:44 +0100 Subject: [PATCH 09/26] Package updates --- .config/dotnet-tools.json | 4 ++-- package-versions.props | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 4cd65cb7fd..de5a0b2ff0 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -17,14 +17,14 @@ "rollForward": false }, "dotnet-reportgenerator-globaltool": { - "version": "5.4.17", + "version": "5.5.0", "commands": [ "reportgenerator" ], "rollForward": false }, "docfx": { - "version": "2.78.2", + "version": "2.78.4", "commands": [ "docfx" ], diff --git a/package-versions.props b/package-versions.props index 0eaf007436..07b54d40b5 100644 --- a/package-versions.props +++ b/package-versions.props @@ -13,23 +13,23 @@ 0.15.* 1.0.* 35.6.* - 4.14.* + 5.0.* 6.0.* 2.1.* 7.2.* 2.4.* 2.0.* 1.* - 9.0.* - 9.0.* + 10.0.* + 10.0.* 0.9.* 14.6.* 13.0.* - 8.9.* + 9.1.* 4.1.* - 2.9.* + 2.11.* 9.*-* - 9.0.* + 10.0.* 18.0.* 2.9.* 3.1.* From 4d114b64c0b0a42c74d45280a8becd8803c2f7e3 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:36:01 +0100 Subject: [PATCH 10/26] Remove reference to Microsoft.Extensions.ApiDescription.Client, because the contents of v8 (which ships with NSwag.ApiDescription.Client) is identical to v10, except for a new deprecation warning --- package-versions.props | 1 - .../OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj | 1 - test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj | 1 - test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj | 1 - 4 files changed, 4 deletions(-) diff --git a/package-versions.props b/package-versions.props index 07b54d40b5..1d40964d54 100644 --- a/package-versions.props +++ b/package-versions.props @@ -20,7 +20,6 @@ 2.4.* 2.0.* 1.* - 10.0.* 10.0.* 0.9.* 14.6.* diff --git a/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj index 079e43121c..5523c5eba3 100644 --- a/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj +++ b/src/Examples/OpenApiNSwagClientExample/OpenApiNSwagClientExample.csproj @@ -12,7 +12,6 @@ - diff --git a/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj index 23d45e95ab..552d4e74c1 100644 --- a/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj +++ b/test/OpenApiNSwagClientTests/OpenApiNSwagClientTests.csproj @@ -20,7 +20,6 @@ - diff --git a/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj index 021ad0342e..c05f841f49 100644 --- a/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj +++ b/test/OpenApiNSwagEndToEndTests/OpenApiNSwagEndToEndTests.csproj @@ -20,7 +20,6 @@ - From d542a123aa09bb59edd2a6dc927337de3b8ab96b Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:55:21 +0100 Subject: [PATCH 11/26] Review warning suppressions --- src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs | 2 +- .../Repositories/EntityFrameworkCoreRepository.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs b/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs index 72a30a060a..bc1425b02e 100644 --- a/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs @@ -1,7 +1,7 @@ using System.Linq.Expressions; using System.Reflection; -#pragma warning disable AV1008 +#pragma warning disable AV1008 // Class should not be static namespace JsonApiDotNetCore.Queries; diff --git a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs index f4c9af37c0..22bad02ef6 100644 --- a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs +++ b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs @@ -146,9 +146,9 @@ protected virtual IQueryable ApplyQueryLayer(QueryLayer queryLayer) source = queryableHandler.Apply(source); } -#pragma warning disable CS0618 +#pragma warning disable CS0618 // Type or member is obsolete IQueryableBuilder builder = _resourceDefinitionAccessor.QueryableBuilder; -#pragma warning restore CS0618 +#pragma warning restore CS0618 // Type or member is obsolete var context = QueryableBuilderContext.CreateRoot(source, typeof(Queryable), _dbContext.Model, null); Expression expression = builder.ApplyQuery(queryLayer, context); @@ -179,9 +179,9 @@ protected virtual IQueryable GetAll() { // EF Core rejects the way we project sparse fieldsets when owned entities are involved, unless the query is explicitly // marked as non-tracked (see https://github.com/dotnet/EntityFramework.Docs/issues/2205#issuecomment-1542914439). -#pragma warning disable CS0618 +#pragma warning disable CS0618 // Type or member is obsolete return _resourceDefinitionAccessor.IsReadOnlyRequest ? QueryTrackingBehavior.NoTrackingWithIdentityResolution : null; -#pragma warning restore CS0618 +#pragma warning restore CS0618 // Type or member is obsolete } /// From d3afb2c084c436c32720b187d33ab17ff07f9f5d Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 14 Nov 2025 02:09:36 +0100 Subject: [PATCH 12/26] Use type alias for lock primitive --- test/TestBuildingBlocks/CapturingLoggerProvider.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/TestBuildingBlocks/CapturingLoggerProvider.cs b/test/TestBuildingBlocks/CapturingLoggerProvider.cs index 07366f5db1..d0894696a1 100644 --- a/test/TestBuildingBlocks/CapturingLoggerProvider.cs +++ b/test/TestBuildingBlocks/CapturingLoggerProvider.cs @@ -1,5 +1,12 @@ using JetBrains.Annotations; using Microsoft.Extensions.Logging; +using LockPrimitive = +#if NET9_0_OR_GREATER + System.Threading.Lock +#else + object +#endif + ; namespace TestBuildingBlocks; @@ -9,11 +16,7 @@ public sealed class CapturingLoggerProvider : ILoggerProvider private static readonly Func DefaultFilter = (_, _) => true; private readonly Func _filter; -#if NET8_0 - private readonly object _lockObject = new(); -#else - private readonly Lock _lockObject = new(); -#endif + private readonly LockPrimitive _lockObject = new(); private readonly List _messages = []; public CapturingLoggerProvider() From 5fd2b8cffef45040dd94e2548c8eec48d0199077 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 15 Nov 2025 13:33:48 +0100 Subject: [PATCH 13/26] Update to Swashbuckle v10 and Microsoft.OpenAPI v2 (adds support for OpenAPI 3.1), fix culture-sensitive keys in sorted set/dictionary, write list of tags to OpenAPI file, sort response headers --- package-versions.props | 4 +- .../JsonApiDotNetCoreExample.json | 271 +++--- .../SetOpenApiServerAtBuildTimeFilter.cs | 4 +- .../OpenApiSchemaExtensions.cs | 66 +- .../AtomicOperationCodeSchemaGenerator.cs | 22 +- .../DataContainerSchemaGenerator.cs | 49 +- .../Components/DataSchemaGenerator.cs | 228 ++--- .../LinksVisibilitySchemaGenerator.cs | 57 +- .../Components/MetaSchemaGenerator.cs | 14 +- .../RelationshipIdentifierSchemaGenerator.cs | 48 +- .../RelationshipNameSchemaGenerator.cs | 22 +- .../Components/ResourceIdSchemaGenerator.cs | 8 +- .../Components/ResourceTypeSchemaGenerator.cs | 42 +- ...AtomicOperationsDocumentSchemaGenerator.cs | 121 +-- .../Documents/DocumentSchemaGenerator.cs | 21 +- .../ErrorResponseDocumentSchemaGenerator.cs | 21 +- ...ceOrRelationshipDocumentSchemaGenerator.cs | 15 +- .../GenerationCacheSchemaGenerator.cs | 31 +- .../JsonApiSchemaGenerator.cs | 10 +- .../SchemaRepositoryExtensions.cs | 22 +- .../SetSchemaTypeToObjectDocumentFilter.cs | 13 +- .../DocumentationOpenApiOperationFilter.cs | 78 +- .../EndpointOrderingFilter.cs | 31 +- .../ResourceFieldSchemaBuilder.cs | 91 +- .../SwaggerComponents/ServerDocumentFilter.cs | 17 +- .../StringEnumOrderingFilter.cs | 34 +- .../UnusedComponentSchemaCleaner.cs | 69 +- .../GeneratedSwagger/swagger.g.json | 7 +- .../AttributeTypes/AttributeTypesStartup.cs | 20 +- .../GeneratedSwagger/swagger.g.json | 35 +- .../GeneratedSwagger/swagger.g.json | 13 +- .../Documentation/DocumentationStartup.cs | 2 +- .../Headers/GeneratedSwagger/swagger.g.json | 63 +- .../GeneratedSwagger/swagger.g.json | 125 +-- .../GeneratedSwagger/swagger.g.json | 324 ++++---- .../LegacyOpenApi/expected-swagger.json | 324 ++++---- .../Enabled/GeneratedSwagger/swagger.g.json | 212 ++--- .../GeneratedSwagger/swagger.g.json | 30 +- .../GeneratedSwagger/swagger.g.json | 7 +- .../CamelCase/GeneratedSwagger/swagger.g.json | 153 ++-- .../KebabCase/GeneratedSwagger/swagger.g.json | 153 ++-- .../GeneratedSwagger/swagger.g.json | 153 ++-- .../GeneratedSwagger/swagger.g.json | 178 ++-- .../GeneratedSwagger/swagger.g.json | 147 ++-- .../GeneratedSwagger/swagger.g.json | 147 ++-- .../GeneratedSwagger/swagger.g.json | 203 ++--- .../GeneratedSwagger/swagger.g.json | 203 ++--- .../GeneratedSwagger/swagger.g.json | 777 ++++++++++-------- .../GeneratedSwagger/swagger.g.json | 205 +++-- .../GeneratedSwagger/swagger.g.json | 7 +- .../GeneratedSwagger/swagger.g.json | 58 +- .../GeneratedSwagger/swagger.g.json | 271 +++--- 52 files changed, 2809 insertions(+), 2417 deletions(-) diff --git a/package-versions.props b/package-versions.props index 1d40964d54..eb57740bd9 100644 --- a/package-versions.props +++ b/package-versions.props @@ -5,7 +5,7 @@ 0.4.1 2.14.1 13.0.4 - 9.0.6 + 10.0.1 4.3.1 @@ -27,7 +27,7 @@ 9.1.* 4.1.* 2.11.* - 9.*-* + 10.*-* 10.0.* 18.0.* 2.9.* diff --git a/src/Examples/JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json b/src/Examples/JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json index 8b23ba14e3..f32c5983c0 100644 --- a/src/Examples/JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json +++ b/src/Examples/JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json @@ -344,13 +344,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -358,6 +351,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -631,13 +631,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -645,6 +638,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -947,13 +947,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -961,6 +954,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1125,13 +1125,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1139,6 +1132,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1543,13 +1543,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1557,6 +1550,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1721,13 +1721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1735,6 +1728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2107,13 +2107,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2121,6 +2114,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2394,13 +2394,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2408,6 +2401,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2710,13 +2710,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2724,6 +2717,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2888,13 +2888,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2902,6 +2895,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3274,13 +3274,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3288,6 +3281,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3561,13 +3561,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3575,6 +3568,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3877,13 +3877,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3891,6 +3884,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4055,13 +4055,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4069,6 +4062,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4313,13 +4313,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4327,6 +4320,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4491,13 +4491,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4505,6 +4498,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4749,13 +4749,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4763,6 +4756,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4927,13 +4927,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4941,6 +4934,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -8716,5 +8716,22 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "nonJsonApi" + }, + { + "name": "operations" + }, + { + "name": "people" + }, + { + "name": "tags" + }, + { + "name": "todoItems" + } + ] } \ No newline at end of file diff --git a/src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs b/src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs index 894c0d0966..f1a162698f 100644 --- a/src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs +++ b/src/Examples/JsonApiDotNetCoreExample/SetOpenApiServerAtBuildTimeFilter.cs @@ -1,5 +1,5 @@ using JetBrains.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCoreExample; @@ -16,6 +16,8 @@ public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { if (_httpContextAccessor.HttpContext == null) { + swaggerDoc.Servers ??= new List(); + swaggerDoc.Servers.Add(new OpenApiServer { Url = "https://localhost:44340" diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs index 10095834b2..a954af0de9 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/OpenApiSchemaExtensions.cs @@ -1,30 +1,70 @@ -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; namespace JsonApiDotNetCore.OpenApi.Swashbuckle; internal static class OpenApiSchemaExtensions { - public static void ReorderProperties(this OpenApiSchema fullSchema, IEnumerable propertyNamesInOrder) + public static OpenApiSchema AsInlineSchema(this IOpenApiSchema schema) { - ArgumentNullException.ThrowIfNull(fullSchema); - ArgumentNullException.ThrowIfNull(propertyNamesInOrder); + ConsistencyGuard.ThrowIf(schema is not OpenApiSchema); + return (OpenApiSchema)schema; + } - var propertiesInOrder = new Dictionary(); + public static OpenApiSchemaReference AsReferenceSchema(this IOpenApiSchema schema) + { + ConsistencyGuard.ThrowIf(schema is not OpenApiSchemaReference); + return (OpenApiSchemaReference)schema; + } - foreach (string propertyName in propertyNamesInOrder) + public static string GetReferenceId(this OpenApiSchemaReference referenceSchema) + { + string? schemaId = referenceSchema.Reference.Id; + ConsistencyGuard.ThrowIf(schemaId is null); + return schemaId; + } + + public static void SetNullable(this OpenApiSchema inlineSchema, bool nullable) + { + ArgumentNullException.ThrowIfNull(inlineSchema); + + if (nullable) + { + inlineSchema.Type ??= JsonSchemaType.Null; + inlineSchema.Type |= JsonSchemaType.Null; + } + else { - if (fullSchema.Properties.TryGetValue(propertyName, out OpenApiSchema? schema)) + if (inlineSchema.Type != null) { - propertiesInOrder.Add(propertyName, schema); + inlineSchema.Type &= ~JsonSchemaType.Null; } } + } + + public static void ReorderProperties(this OpenApiSchema inlineSchema, IEnumerable propertyNamesInOrder) + { + ArgumentNullException.ThrowIfNull(inlineSchema); + ArgumentNullException.ThrowIfNull(propertyNamesInOrder); + + if (inlineSchema.Properties is { Count: > 1 }) + { + var propertiesInOrder = new Dictionary(); - ConsistencyGuard.ThrowIf(fullSchema.Properties.Count != propertiesInOrder.Count); + foreach (string propertyName in propertyNamesInOrder) + { + if (inlineSchema.Properties.TryGetValue(propertyName, out IOpenApiSchema? schema)) + { + propertiesInOrder.Add(propertyName, schema); + } + } - fullSchema.Properties = propertiesInOrder; + ConsistencyGuard.ThrowIf(inlineSchema.Properties.Count != propertiesInOrder.Count); + + inlineSchema.Properties = propertiesInOrder; + } } - public static OpenApiSchema WrapInExtendedSchema(this OpenApiSchema source) + public static OpenApiSchema WrapInExtendedSchema(this IOpenApiSchema source) { ArgumentNullException.ThrowIfNull(source); @@ -34,11 +74,11 @@ public static OpenApiSchema WrapInExtendedSchema(this OpenApiSchema source) }; } - public static OpenApiSchema UnwrapLastExtendedSchema(this OpenApiSchema source) + public static IOpenApiSchema UnwrapLastExtendedSchema(this IOpenApiSchema source) { ArgumentNullException.ThrowIfNull(source); - if (source.AllOf is { Count: > 0 }) + if (source is OpenApiSchema && source.AllOf is { Count: > 0 }) { return source.AllOf.Last(); } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs index 78a25da441..c7022c195a 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/AtomicOperationCodeSchemaGenerator.cs @@ -1,6 +1,5 @@ using JsonApiDotNetCore.Serialization.Objects; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -19,7 +18,7 @@ public AtomicOperationCodeSchemaGenerator(SchemaGenerationTracer schemaGeneratio _schemaIdSelector = schemaIdSelector; } - public OpenApiSchema GenerateSchema(AtomicOperationCode operationCode, SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(AtomicOperationCode operationCode, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaRepository); @@ -27,27 +26,20 @@ public OpenApiSchema GenerateSchema(AtomicOperationCode operationCode, SchemaRep if (schemaRepository.Schemas.ContainsKey(schemaId)) { - return new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = schemaId, - Type = ReferenceType.Schema - } - }; + return new OpenApiSchemaReference(schemaId); } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, operationCode); string enumValue = operationCode.ToString().ToLowerInvariant(); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "string", - Enum = [new OpenApiString(enumValue)] + Type = JsonSchemaType.String, + Enum = [enumValue] }; - OpenApiSchema referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + OpenApiSchemaReference referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); traceScope.TraceSucceeded(schemaId); return referenceSchema; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs index c4b41dd0f5..3501c1f32f 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataContainerSchemaGenerator.cs @@ -2,7 +2,7 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -27,49 +27,44 @@ public DataContainerSchemaGenerator(SchemaGenerationTracer schemaGenerationTrace _resourceGraph = resourceGraph; } - public OpenApiSchema GenerateSchemaForCommonResourceDataInResponse(SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchemaForCommonResourceDataInResponse(SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaRepository); return _dataSchemaGenerator.GenerateSchemaForCommonData(typeof(ResourceInResponse), schemaRepository); } - public OpenApiSchema GenerateSchema(Type dataContainerSchemaType, ResourceType resourceType, bool forRequestSchema, bool canIncludeRelated, + public void GenerateSchema(Type dataContainerSchemaType, ResourceType resourceType, bool forRequestSchema, bool canIncludeRelated, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(dataContainerSchemaType); ArgumentNullException.ThrowIfNull(resourceType); ArgumentNullException.ThrowIfNull(schemaRepository); - if (schemaRepository.TryLookupByType(dataContainerSchemaType, out OpenApiSchema referenceSchemaForData)) + if (!schemaRepository.TryLookupByTypeSafe(dataContainerSchemaType, out _)) { - return referenceSchemaForData; - } - - Type dataConstructedType = GetElementTypeOfDataProperty(dataContainerSchemaType, resourceType); - - if (schemaRepository.TryLookupByType(dataConstructedType, out _)) - { - return referenceSchemaForData; - } + Type dataConstructedType = GetElementTypeOfDataProperty(dataContainerSchemaType, resourceType); - using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, dataConstructedType); - - if (canIncludeRelated) - { - var resourceSchemaType = ResourceSchemaType.Create(dataConstructedType, _resourceGraph); - - if (resourceSchemaType.SchemaOpenType == typeof(DataInResponse<>)) + if (!schemaRepository.TryLookupByTypeSafe(dataConstructedType, out _)) { - // Ensure all reachable related resource types in response schemas are generated upfront. - // This is needed to make includes work when not all endpoints are exposed. - GenerateReachableRelatedTypesInResponse(dataConstructedType, schemaRepository); + using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, dataConstructedType); + + if (canIncludeRelated) + { + var resourceSchemaType = ResourceSchemaType.Create(dataConstructedType, _resourceGraph); + + if (resourceSchemaType.SchemaOpenType == typeof(DataInResponse<>)) + { + // Ensure all reachable related resource types in response schemas are generated upfront. + // This is needed to make includes work when not all endpoints are exposed. + GenerateReachableRelatedTypesInResponse(dataConstructedType, schemaRepository); + } + } + + OpenApiSchemaReference referenceSchemaForData = _dataSchemaGenerator.GenerateSchema(dataConstructedType, forRequestSchema, schemaRepository); + traceScope.TraceSucceeded(referenceSchemaForData.GetReferenceId()); } } - - referenceSchemaForData = _dataSchemaGenerator.GenerateSchema(dataConstructedType, forRequestSchema, schemaRepository); - traceScope.TraceSucceeded(referenceSchemaForData.Reference.Id); - return referenceSchemaForData; } private static Type GetElementTypeOfDataProperty(Type dataContainerConstructedType, ResourceType resourceType) diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs index 4d7783f780..6db68645fc 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/DataSchemaGenerator.cs @@ -1,12 +1,13 @@ using System.Collections.Concurrent; using System.Reflection; using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Text.Json.Nodes; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -79,7 +80,7 @@ public DataSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, Schema _resourceDocumentationReader = resourceDocumentationReader; } - public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema, SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(Type dataSchemaType, bool forRequestSchema, SchemaRepository schemaRepository) { // For a given resource (identifier) type, we always generate the full type hierarchy. Discriminator mappings // are managed manually, because there's no way to intercept in the Swashbuckle recursive component schema generation. @@ -87,7 +88,7 @@ public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema, ArgumentNullException.ThrowIfNull(dataSchemaType); ArgumentNullException.ThrowIfNull(schemaRepository); - if (schemaRepository.TryLookupByType(dataSchemaType, out OpenApiSchema referenceSchemaForData)) + if (schemaRepository.TryLookupByTypeSafe(dataSchemaType, out OpenApiSchemaReference? referenceSchemaForData)) { return referenceSchemaForData; } @@ -114,18 +115,18 @@ public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema, using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, dataSchemaType); - referenceSchemaForData = _defaultSchemaGenerator.GenerateSchema(dataSchemaType, schemaRepository); - OpenApiSchema fullSchemaForData = schemaRepository.Schemas[referenceSchemaForData.Reference.Id]; - fullSchemaForData.AdditionalPropertiesAllowed = false; + referenceSchemaForData = _defaultSchemaGenerator.GenerateSchema(dataSchemaType, schemaRepository).AsReferenceSchema(); + OpenApiSchema possiblyCompositeInlineSchemaForData = schemaRepository.Schemas[referenceSchemaForData.GetReferenceId()].AsInlineSchema(); + possiblyCompositeInlineSchemaForData.AdditionalPropertiesAllowed = false; - OpenApiSchema inlineSchemaForData = fullSchemaForData.UnwrapLastExtendedSchema(); + OpenApiSchema inlineSchemaForData = possiblyCompositeInlineSchemaForData.UnwrapLastExtendedSchema().AsInlineSchema(); SetAbstract(inlineSchemaForData, resourceSchemaType); SetResourceType(inlineSchemaForData, resourceType, schemaRepository); AdaptResourceIdentity(inlineSchemaForData, resourceSchemaType, forRequestSchema, schemaRepository); SetResourceId(inlineSchemaForData, resourceType, schemaRepository); SetResourceFields(inlineSchemaForData, resourceSchemaType, forRequestSchema, schemaRepository); - SetDocumentation(fullSchemaForData, resourceType); + SetDocumentation(possiblyCompositeInlineSchemaForData, resourceType); SetLinksVisibility(inlineSchemaForData, resourceSchemaType, schemaRepository); if (resourceType.IsPartOfTypeHierarchy()) @@ -142,10 +143,11 @@ public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema, if (RequiresRootObjectTypeInDataSchema(resourceSchemaType, forRequestSchema)) { - fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiBoolean(true); + possiblyCompositeInlineSchemaForData.Extensions ??= new SortedDictionary(StringComparer.Ordinal); + possiblyCompositeInlineSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new JsonNodeExtension(true); } - traceScope.TraceSucceeded(referenceSchemaForData.Reference.Id); + traceScope.TraceSucceeded(referenceSchemaForData.GetReferenceId()); return referenceSchemaForData; } @@ -202,45 +204,44 @@ public OpenApiSchema GenerateSchema(Type dataSchemaType, bool forRequestSchema, return boxedSchemaType.Value; } - public OpenApiSchema GenerateSchemaForCommonData(Type commonDataSchemaType, SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchemaForCommonData(Type commonDataSchemaType, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(commonDataSchemaType); ArgumentNullException.ThrowIfNull(schemaRepository); - if (schemaRepository.TryLookupByType(commonDataSchemaType, out OpenApiSchema? referenceSchema)) + if (schemaRepository.TryLookupByTypeSafe(commonDataSchemaType, out OpenApiSchemaReference? referenceSchema)) { return referenceSchema; } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, commonDataSchemaType); - OpenApiSchema referenceSchemaForResourceType = _resourceTypeSchemaGenerator.GenerateSchema(schemaRepository); - OpenApiSchema referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); + OpenApiSchemaReference referenceSchemaForResourceType = _resourceTypeSchemaGenerator.GenerateSchema(schemaRepository); + OpenApiSchemaReference referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "object", - Required = new SortedSet([JsonApiPropertyName.Type]), - Properties = new Dictionary + Type = JsonSchemaType.Object, + Required = new SortedSet([JsonApiPropertyName.Type], StringComparer.Ordinal), + Properties = new Dictionary { [JsonApiPropertyName.Type] = referenceSchemaForResourceType.WrapInExtendedSchema(), - [referenceSchemaForMeta.Reference.Id] = referenceSchemaForMeta.WrapInExtendedSchema() + [referenceSchemaForMeta.GetReferenceId()] = referenceSchemaForMeta.WrapInExtendedSchema() }, AdditionalPropertiesAllowed = false, Discriminator = new OpenApiDiscriminator { - PropertyName = JsonApiPropertyName.Type, - Mapping = new SortedDictionary(StringComparer.Ordinal) + PropertyName = JsonApiPropertyName.Type }, - Extensions = + Extensions = new SortedDictionary(StringComparer.Ordinal) { - ["x-abstract"] = new OpenApiBoolean(true) + ["x-abstract"] = new JsonNodeExtension(true) } }; string schemaId = _schemaIdSelector.GetSchemaId(commonDataSchemaType); - referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); schemaRepository.RegisterType(commonDataSchemaType, schemaId); traceScope.TraceSucceeded(schemaId); @@ -268,24 +269,25 @@ private static Type ChangeResourceTypeInSchemaType(Type schemaType, ResourceType return schemaOpenType.MakeGenericType(resourceType.ClrType); } - private static void SetAbstract(OpenApiSchema fullSchema, ResourceSchemaType resourceSchemaType) + private static void SetAbstract(OpenApiSchema inlineSchema, ResourceSchemaType resourceSchemaType) { if (resourceSchemaType.ResourceType.ClrType.IsAbstract && resourceSchemaType.SchemaOpenType != typeof(IdentifierInRequest<>)) { - fullSchema.Extensions["x-abstract"] = new OpenApiBoolean(true); + inlineSchema.Extensions ??= new SortedDictionary(StringComparer.Ordinal); + inlineSchema.Extensions["x-abstract"] = new JsonNodeExtension(true); } } - private void SetResourceType(OpenApiSchema fullSchema, ResourceType resourceType, SchemaRepository schemaRepository) + private void SetResourceType(OpenApiSchema inlineSchema, ResourceType resourceType, SchemaRepository schemaRepository) { - if (fullSchema.Properties.ContainsKey(JsonApiPropertyName.Type)) + if (inlineSchema.Properties != null && inlineSchema.Properties.ContainsKey(JsonApiPropertyName.Type)) { - OpenApiSchema referenceSchema = _resourceTypeSchemaGenerator.GenerateSchema(resourceType, schemaRepository); - fullSchema.Properties[JsonApiPropertyName.Type] = referenceSchema.WrapInExtendedSchema(); + OpenApiSchemaReference referenceSchema = _resourceTypeSchemaGenerator.GenerateSchema(resourceType, schemaRepository); + inlineSchema.Properties[JsonApiPropertyName.Type] = referenceSchema.WrapInExtendedSchema(); } } - private void AdaptResourceIdentity(OpenApiSchema fullSchema, ResourceSchemaType resourceSchemaType, bool forRequestSchema, + private void AdaptResourceIdentity(OpenApiSchema inlineSchema, ResourceSchemaType resourceSchemaType, bool forRequestSchema, SchemaRepository schemaRepository) { if (!forRequestSchema) @@ -297,7 +299,7 @@ private void AdaptResourceIdentity(OpenApiSchema fullSchema, ResourceSchemaType if (!hasAtomicOperationsEndpoint) { - fullSchema.Properties.Remove(JsonApiPropertyName.Lid); + inlineSchema.Properties?.Remove(JsonApiPropertyName.Lid); } if (resourceSchemaType.SchemaOpenType == typeof(DataInCreateRequest<>)) @@ -308,23 +310,25 @@ private void AdaptResourceIdentity(OpenApiSchema fullSchema, ResourceSchemaType { if (clientIdGeneration == ClientIdGenerationMode.Forbidden) { - fullSchema.Properties.Remove(JsonApiPropertyName.Id); + inlineSchema.Properties?.Remove(JsonApiPropertyName.Id); } else if (clientIdGeneration == ClientIdGenerationMode.Required) { - fullSchema.Properties.Remove(JsonApiPropertyName.Lid); - fullSchema.Required.Add(JsonApiPropertyName.Id); + inlineSchema.Properties?.Remove(JsonApiPropertyName.Lid); + inlineSchema.Required ??= new SortedSet(StringComparer.Ordinal); + inlineSchema.Required.Add(JsonApiPropertyName.Id); } } else { if (clientIdGeneration == ClientIdGenerationMode.Forbidden) { - fullSchema.Properties.Remove(JsonApiPropertyName.Id); + inlineSchema.Properties?.Remove(JsonApiPropertyName.Id); } else if (clientIdGeneration == ClientIdGenerationMode.Required) { - fullSchema.Required.Add(JsonApiPropertyName.Id); + inlineSchema.Required ??= new SortedSet(StringComparer.Ordinal); + inlineSchema.Required.Add(JsonApiPropertyName.Id); } } } @@ -332,60 +336,59 @@ private void AdaptResourceIdentity(OpenApiSchema fullSchema, ResourceSchemaType { if (!hasAtomicOperationsEndpoint) { - fullSchema.Required.Add(JsonApiPropertyName.Id); + inlineSchema.Required ??= new SortedSet(StringComparer.Ordinal); + inlineSchema.Required.Add(JsonApiPropertyName.Id); } } } - private void SetResourceId(OpenApiSchema fullSchema, ResourceType resourceType, SchemaRepository schemaRepository) + private void SetResourceId(OpenApiSchema inlineSchema, ResourceType resourceType, SchemaRepository schemaRepository) { - if (fullSchema.Properties.ContainsKey(JsonApiPropertyName.Id)) + if (inlineSchema.Properties != null && inlineSchema.Properties.ContainsKey(JsonApiPropertyName.Id)) { OpenApiSchema idSchema = _resourceIdSchemaGenerator.GenerateSchema(resourceType, schemaRepository); - fullSchema.Properties[JsonApiPropertyName.Id] = idSchema; + inlineSchema.Properties[JsonApiPropertyName.Id] = idSchema; } } - private void SetResourceFields(OpenApiSchema fullSchemaForData, ResourceSchemaType resourceSchemaType, bool forRequestSchema, - SchemaRepository schemaRepository) + private void SetResourceFields(OpenApiSchema inlineSchema, ResourceSchemaType resourceSchemaType, bool forRequestSchema, SchemaRepository schemaRepository) { - bool schemaHasFields = fullSchemaForData.Properties.ContainsKey(JsonApiPropertyName.Attributes) && - fullSchemaForData.Properties.ContainsKey(JsonApiPropertyName.Relationships); - - if (schemaHasFields) + if (inlineSchema.Properties != null && inlineSchema.Properties.ContainsKey(JsonApiPropertyName.Attributes) && + inlineSchema.Properties.ContainsKey(JsonApiPropertyName.Relationships)) { var fieldSchemaBuilder = new ResourceFieldSchemaBuilder(_schemaGenerationTracer, _defaultSchemaGenerator, this, _linksVisibilitySchemaGenerator, _resourceFieldValidationMetadataProvider, _relationshipTypeFactory, resourceSchemaType); - SetFieldSchemaMembers(fullSchemaForData, resourceSchemaType, forRequestSchema, true, fieldSchemaBuilder, schemaRepository); - SetFieldSchemaMembers(fullSchemaForData, resourceSchemaType, forRequestSchema, false, fieldSchemaBuilder, schemaRepository); + SetFieldSchemaMembers(inlineSchema.Properties, resourceSchemaType, forRequestSchema, true, fieldSchemaBuilder, schemaRepository); + SetFieldSchemaMembers(inlineSchema.Properties, resourceSchemaType, forRequestSchema, false, fieldSchemaBuilder, schemaRepository); } } - private void SetFieldSchemaMembers(OpenApiSchema fullSchemaForData, ResourceSchemaType resourceSchemaTypeForData, bool forRequestSchema, bool forAttributes, - ResourceFieldSchemaBuilder fieldSchemaBuilder, SchemaRepository schemaRepository) + private void SetFieldSchemaMembers(IDictionary inlineSchemaForDataProperties, ResourceSchemaType resourceSchemaTypeForData, + bool forRequestSchema, bool forAttributes, ResourceFieldSchemaBuilder fieldSchemaBuilder, SchemaRepository schemaRepository) { string propertyNameInSchema = forAttributes ? JsonApiPropertyName.Attributes : JsonApiPropertyName.Relationships; - OpenApiSchema referenceSchemaForFields = fullSchemaForData.Properties[propertyNameInSchema].UnwrapLastExtendedSchema(); - OpenApiSchema fullSchemaForFields = schemaRepository.Schemas[referenceSchemaForFields.Reference.Id]; - fullSchemaForFields.AdditionalPropertiesAllowed = false; + OpenApiSchemaReference referenceSchemaForFields = inlineSchemaForDataProperties[propertyNameInSchema].UnwrapLastExtendedSchema().AsReferenceSchema(); + OpenApiSchema inlineSchemaForFields = schemaRepository.Schemas[referenceSchemaForFields.GetReferenceId()].AsInlineSchema(); + inlineSchemaForFields.AdditionalPropertiesAllowed = false; - SetAbstract(fullSchemaForFields, resourceSchemaTypeForData); + SetAbstract(inlineSchemaForFields, resourceSchemaTypeForData); if (forAttributes) { - fieldSchemaBuilder.SetMembersOfAttributes(fullSchemaForFields, forRequestSchema, schemaRepository); + fieldSchemaBuilder.SetMembersOfAttributes(inlineSchemaForFields, forRequestSchema, schemaRepository); } else { - fieldSchemaBuilder.SetMembersOfRelationships(fullSchemaForFields, forRequestSchema, schemaRepository); + fieldSchemaBuilder.SetMembersOfRelationships(inlineSchemaForFields, forRequestSchema, schemaRepository); } - if (fullSchemaForFields.Properties.Count == 0 && !resourceSchemaTypeForData.ResourceType.IsPartOfTypeHierarchy()) + if ((inlineSchemaForFields.Properties == null || inlineSchemaForFields.Properties.Count == 0) && + !resourceSchemaTypeForData.ResourceType.IsPartOfTypeHierarchy()) { - fullSchemaForData.Properties.Remove(propertyNameInSchema); - schemaRepository.Schemas.Remove(referenceSchemaForFields.Reference.Id); + inlineSchemaForDataProperties.Remove(propertyNameInSchema); + schemaRepository.Schemas.Remove(referenceSchemaForFields.GetReferenceId()); } else { @@ -414,14 +417,14 @@ private void SetFieldSchemaMembers(OpenApiSchema fullSchemaForData, ResourceSche baseSchemaType = commonFieldsSchemaType; } - OpenApiSchema referenceSchemaForBase = schemaRepository.LookupByType(baseSchemaType); + OpenApiSchemaReference referenceSchemaForBase = schemaRepository.LookupByType(baseSchemaType); - schemaRepository.Schemas[referenceSchemaForFields.Reference.Id] = new OpenApiSchema + schemaRepository.Schemas[referenceSchemaForFields.GetReferenceId()] = new OpenApiSchema { AllOf = [ referenceSchemaForBase, - fullSchemaForFields + inlineSchemaForFields ], AdditionalPropertiesAllowed = false }; @@ -437,40 +440,39 @@ private ResourceSchemaType GetResourceSchemaTypeForFieldsProperty(ResourceSchema return ResourceSchemaType.Create(fieldsConstructedType, _resourceGraph); } - private OpenApiSchema GenerateSchemaForCommonFields(Type commonFieldsSchemaType, SchemaRepository schemaRepository) + private OpenApiSchemaReference GenerateSchemaForCommonFields(Type commonFieldsSchemaType, SchemaRepository schemaRepository) { - if (schemaRepository.TryLookupByType(commonFieldsSchemaType, out OpenApiSchema? referenceSchema)) + if (schemaRepository.TryLookupByTypeSafe(commonFieldsSchemaType, out OpenApiSchemaReference? referenceSchema)) { return referenceSchema; } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, commonFieldsSchemaType); - OpenApiSchema referenceSchemaForResourceType = _resourceTypeSchemaGenerator.GenerateSchema(schemaRepository); + OpenApiSchemaReference referenceSchemaForResourceType = _resourceTypeSchemaGenerator.GenerateSchema(schemaRepository); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "object", - Required = new SortedSet([OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName]), - Properties = new Dictionary + Type = JsonSchemaType.Object, + Required = new SortedSet([OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName], StringComparer.Ordinal), + Properties = new Dictionary { [OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName] = referenceSchemaForResourceType.WrapInExtendedSchema() }, AdditionalPropertiesAllowed = false, Discriminator = new OpenApiDiscriminator { - PropertyName = OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName, - Mapping = new SortedDictionary(StringComparer.Ordinal) + PropertyName = OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName }, - Extensions = + Extensions = new SortedDictionary(StringComparer.Ordinal) { - ["x-abstract"] = new OpenApiBoolean(true) + ["x-abstract"] = new JsonNodeExtension(true) } }; string schemaId = _schemaIdSelector.GetSchemaId(commonFieldsSchemaType); - referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); schemaRepository.RegisterType(commonFieldsSchemaType, schemaId); traceScope.TraceSucceeded(schemaId); @@ -480,7 +482,7 @@ private OpenApiSchema GenerateSchemaForCommonFields(Type commonFieldsSchemaType, private void MapInDiscriminator(ResourceSchemaType resourceSchemaType, bool forRequestSchema, string discriminatorPropertyName, SchemaRepository schemaRepository) { - OpenApiSchema referenceSchemaForDerived = schemaRepository.LookupByType(resourceSchemaType.SchemaConstructedType); + OpenApiSchemaReference referenceSchemaForDerived = schemaRepository.LookupByType(resourceSchemaType.SchemaConstructedType); foreach (ResourceType? baseResourceType in GetBaseTypesToMapInto(resourceSchemaType, forRequestSchema)) { @@ -488,23 +490,23 @@ private void MapInDiscriminator(ResourceSchemaType resourceSchemaType, bool forR ? GetCommonSchemaType(resourceSchemaType.SchemaOpenType)! : resourceSchemaType.ChangeResourceType(baseResourceType).SchemaConstructedType; - OpenApiSchema referenceSchemaForBase = schemaRepository.LookupByType(baseSchemaType); - OpenApiSchema inlineSchemaForBase = schemaRepository.Schemas[referenceSchemaForBase.Reference.Id].UnwrapLastExtendedSchema(); + OpenApiSchemaReference referenceSchemaForBase = schemaRepository.LookupByType(baseSchemaType); + OpenApiSchema inlineSchemaForBase = schemaRepository.Schemas[referenceSchemaForBase.GetReferenceId()].UnwrapLastExtendedSchema().AsInlineSchema(); inlineSchemaForBase.Discriminator ??= new OpenApiDiscriminator { - PropertyName = discriminatorPropertyName, - Mapping = new SortedDictionary(StringComparer.Ordinal) + PropertyName = discriminatorPropertyName }; if (RepeatDiscriminatorInResponseDerivedTypes && !forRequestSchema) { + inlineSchemaForBase.Required ??= new SortedSet(StringComparer.Ordinal); inlineSchemaForBase.Required.Add(discriminatorPropertyName); } string publicName = resourceSchemaType.ResourceType.PublicName; - if (inlineSchemaForBase.Discriminator.Mapping.TryAdd(publicName, referenceSchemaForDerived.Reference.ReferenceV3) && baseResourceType == null) + if (TryAddToDiscriminatorMapping(inlineSchemaForBase, publicName, referenceSchemaForDerived) && baseResourceType == null) { MapResourceTypeInEnum(publicName, schemaRepository); } @@ -540,30 +542,40 @@ private void MapInDiscriminator(ResourceSchemaType resourceSchemaType, bool forR } } + private static bool TryAddToDiscriminatorMapping(OpenApiSchema inlineSchema, string schemaId, OpenApiSchemaReference mappingValueReferenceSchema) + { + ConsistencyGuard.ThrowIf(inlineSchema.Discriminator is null); + + inlineSchema.Discriminator.Mapping ??= new SortedDictionary(StringComparer.Ordinal); + return inlineSchema.Discriminator.Mapping.TryAdd(schemaId, mappingValueReferenceSchema); + } + private void MapResourceTypeInEnum(string publicName, SchemaRepository schemaRepository) { string schemaId = _schemaIdSelector.GetResourceTypeSchemaId(null); - OpenApiSchema fullSchema = schemaRepository.Schemas[schemaId]; + OpenApiSchema inlineSchema = schemaRepository.Schemas[schemaId].AsInlineSchema(); + inlineSchema.Enum ??= new List(); - if (!fullSchema.Enum.Any(openApiAny => openApiAny is OpenApiString openApiString && openApiString.Value == publicName)) + if (!inlineSchema.Enum.Any(jsonNode => jsonNode is JsonValue jsonValue && jsonValue.GetValueKind() == JsonValueKind.String && + jsonValue.GetValue() == publicName)) { - fullSchema.Enum.Add(new OpenApiString(publicName)); + inlineSchema.Enum.Add(publicName); } } - private void SetDocumentation(OpenApiSchema fullSchema, ResourceType resourceType) + private void SetDocumentation(OpenApiSchema inlineSchema, ResourceType resourceType) { - fullSchema.Description = _resourceDocumentationReader.GetDocumentationForType(resourceType); + inlineSchema.Description = _resourceDocumentationReader.GetDocumentationForType(resourceType); } - private void SetLinksVisibility(OpenApiSchema fullSchema, ResourceSchemaType resourceSchemaType, SchemaRepository schemaRepository) + private void SetLinksVisibility(OpenApiSchema inlineSchema, ResourceSchemaType resourceSchemaType, SchemaRepository schemaRepository) { - _linksVisibilitySchemaGenerator.UpdateSchemaForResource(resourceSchemaType, fullSchema, schemaRepository); + _linksVisibilitySchemaGenerator.UpdateSchemaForResource(resourceSchemaType, inlineSchema, schemaRepository); } private void GenerateDataSchemasForDirectlyDerivedTypes(ResourceSchemaType resourceSchemaType, bool forRequestSchema, SchemaRepository schemaRepository) { - OpenApiSchema referenceSchemaForBase = schemaRepository.LookupByType(resourceSchemaType.SchemaConstructedType); + OpenApiSchemaReference referenceSchemaForBase = schemaRepository.LookupByType(resourceSchemaType.SchemaConstructedType); foreach (ResourceType derivedType in resourceSchemaType.ResourceType.DirectlyDerivedTypes) { @@ -572,54 +584,58 @@ private void GenerateDataSchemasForDirectlyDerivedTypes(ResourceSchemaType resou using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, resourceSchemaTypeForDerived.SchemaConstructedType); - OpenApiSchema referenceSchemaForDerived = _defaultSchemaGenerator.GenerateSchema(derivedSchemaType, schemaRepository); - OpenApiSchema fullSchemaForDerived = schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id]; - fullSchemaForDerived.AdditionalPropertiesAllowed = false; + OpenApiSchemaReference referenceSchemaForDerived = _defaultSchemaGenerator.GenerateSchema(derivedSchemaType, schemaRepository).AsReferenceSchema(); + OpenApiSchema possiblyCompositeInlineSchemaForDerived = schemaRepository.Schemas[referenceSchemaForDerived.GetReferenceId()].AsInlineSchema(); + possiblyCompositeInlineSchemaForDerived.AdditionalPropertiesAllowed = false; - OpenApiSchema inlineSchemaForDerived = fullSchemaForDerived.UnwrapLastExtendedSchema(); + OpenApiSchema inlineSchemaForDerived = possiblyCompositeInlineSchemaForDerived.UnwrapLastExtendedSchema().AsInlineSchema(); SetResourceFields(inlineSchemaForDerived, resourceSchemaTypeForDerived, forRequestSchema, schemaRepository); SetAbstract(inlineSchemaForDerived, resourceSchemaTypeForDerived); RemoveProperties(inlineSchemaForDerived); MapInDiscriminator(resourceSchemaTypeForDerived, forRequestSchema, JsonApiPropertyName.Type, schemaRepository); - if (fullSchemaForDerived.AllOf.Count == 0) + if (possiblyCompositeInlineSchemaForDerived.AllOf == null || possiblyCompositeInlineSchemaForDerived.AllOf.Count == 0) { - var compositeSchemaForDerived = new OpenApiSchema + var compositeInlineSchemaForDerived = new OpenApiSchema { AllOf = [ referenceSchemaForBase, - fullSchemaForDerived + possiblyCompositeInlineSchemaForDerived ], AdditionalPropertiesAllowed = false }; - schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id] = compositeSchemaForDerived; + schemaRepository.Schemas[referenceSchemaForDerived.GetReferenceId()] = compositeInlineSchemaForDerived; } else { - fullSchemaForDerived.AllOf[0] = referenceSchemaForBase; + possiblyCompositeInlineSchemaForDerived.AllOf[0] = referenceSchemaForBase; } if (RequiresRootObjectTypeInDataSchema(resourceSchemaTypeForDerived, forRequestSchema)) { - OpenApiSchema fullSchemaForData = schemaRepository.Schemas[referenceSchemaForDerived.Reference.Id]; - fullSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new OpenApiBoolean(true); + OpenApiSchema inlineSchemaForData = schemaRepository.Schemas[referenceSchemaForDerived.GetReferenceId()].AsInlineSchema(); + inlineSchemaForData.Extensions ??= new SortedDictionary(StringComparer.Ordinal); + inlineSchemaForData.Extensions[SetSchemaTypeToObjectDocumentFilter.RequiresRootObjectTypeKey] = new JsonNodeExtension(true); } GenerateDataSchemasForDirectlyDerivedTypes(resourceSchemaTypeForDerived, forRequestSchema, schemaRepository); - traceScope.TraceSucceeded(referenceSchemaForDerived.Reference.Id); + traceScope.TraceSucceeded(referenceSchemaForDerived.GetReferenceId()); } } - private static void RemoveProperties(OpenApiSchema fullSchema) + private static void RemoveProperties(OpenApiSchema inlineSchema) { - foreach (string propertyName in fullSchema.Properties.Keys) + if (inlineSchema.Properties != null) { - fullSchema.Properties.Remove(propertyName); - fullSchema.Required.Remove(propertyName); + foreach (string propertyName in inlineSchema.Properties.Keys) + { + inlineSchema.Properties.Remove(propertyName); + inlineSchema.Required?.Remove(propertyName); + } } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/LinksVisibilitySchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/LinksVisibilitySchemaGenerator.cs index 5c099a3fc1..80229d6025 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/LinksVisibilitySchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/LinksVisibilitySchemaGenerator.cs @@ -4,7 +4,7 @@ using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; using JsonApiDotNetCore.Resources.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -70,72 +70,77 @@ public LinksVisibilitySchemaGenerator(IJsonApiOptions options, IResourceGraph re _lazyLinksVisibility = new Lazy(() => new LinksVisibility(options, resourceGraph), LazyThreadSafetyMode.ExecutionAndPublication); } - public void UpdateSchemaForTopLevel(Type schemaType, OpenApiSchema fullSchemaForLinksContainer, SchemaRepository schemaRepository) + public void UpdateSchemaForTopLevel(Type schemaType, OpenApiSchema inlineSchemaForLinksContainer, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaType); - ArgumentNullException.ThrowIfNull(fullSchemaForLinksContainer); + ArgumentNullException.ThrowIfNull(inlineSchemaForLinksContainer); Type lookupType = schemaType.ConstructedToOpenType(); if (LinksInJsonApiSchemaTypes.TryGetValue(lookupType, out LinkTypes possibleLinkTypes)) { - UpdateLinksProperty(fullSchemaForLinksContainer, _lazyLinksVisibility.Value.TopLevelLinks, possibleLinkTypes, schemaRepository); + UpdateLinksProperty(inlineSchemaForLinksContainer, _lazyLinksVisibility.Value.TopLevelLinks, possibleLinkTypes, schemaRepository); } } - public void UpdateSchemaForResource(ResourceSchemaType resourceSchemaType, OpenApiSchema fullSchemaForResourceData, SchemaRepository schemaRepository) + public void UpdateSchemaForResource(ResourceSchemaType resourceSchemaType, OpenApiSchema inlineSchemaForResourceData, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(resourceSchemaType); - ArgumentNullException.ThrowIfNull(fullSchemaForResourceData); + ArgumentNullException.ThrowIfNull(inlineSchemaForResourceData); if (LinksInJsonApiSchemaTypes.TryGetValue(resourceSchemaType.SchemaOpenType, out LinkTypes possibleLinkTypes)) { - UpdateLinksProperty(fullSchemaForResourceData, _lazyLinksVisibility.Value.ResourceLinks, possibleLinkTypes, schemaRepository); + UpdateLinksProperty(inlineSchemaForResourceData, _lazyLinksVisibility.Value.ResourceLinks, possibleLinkTypes, schemaRepository); } } - public void UpdateSchemaForRelationship(Type schemaType, OpenApiSchema fullSchemaForRelationship, SchemaRepository schemaRepository) + public void UpdateSchemaForRelationship(Type schemaType, OpenApiSchema inlineSchemaForRelationship, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaType); - ArgumentNullException.ThrowIfNull(fullSchemaForRelationship); + ArgumentNullException.ThrowIfNull(inlineSchemaForRelationship); Type lookupType = schemaType.ConstructedToOpenType(); if (LinksInJsonApiSchemaTypes.TryGetValue(lookupType, out LinkTypes possibleLinkTypes)) { - UpdateLinksProperty(fullSchemaForRelationship, _lazyLinksVisibility.Value.RelationshipLinks, possibleLinkTypes, schemaRepository); + UpdateLinksProperty(inlineSchemaForRelationship, _lazyLinksVisibility.Value.RelationshipLinks, possibleLinkTypes, schemaRepository); } } - private void UpdateLinksProperty(OpenApiSchema fullSchemaForLinksContainer, LinkTypes visibleLinkTypes, LinkTypes possibleLinkTypes, + private void UpdateLinksProperty(OpenApiSchema inlineSchemaForLinksContainer, LinkTypes visibleLinkTypes, LinkTypes possibleLinkTypes, SchemaRepository schemaRepository) { - OpenApiSchema referenceSchemaForLinks = fullSchemaForLinksContainer.Properties[JsonApiPropertyName.Links].UnwrapLastExtendedSchema(); - - if ((visibleLinkTypes & possibleLinkTypes) == 0) + if (inlineSchemaForLinksContainer.Properties != null) { - fullSchemaForLinksContainer.Required.Remove(JsonApiPropertyName.Links); - fullSchemaForLinksContainer.Properties.Remove(JsonApiPropertyName.Links); + OpenApiSchemaReference referenceSchemaForLinks = + inlineSchemaForLinksContainer.Properties[JsonApiPropertyName.Links].UnwrapLastExtendedSchema().AsReferenceSchema(); - schemaRepository.Schemas.Remove(referenceSchemaForLinks.Reference.Id); - } - else if (visibleLinkTypes != possibleLinkTypes) - { - string linksSchemaId = referenceSchemaForLinks.Reference.Id; + if ((visibleLinkTypes & possibleLinkTypes) == 0) + { + inlineSchemaForLinksContainer.Required?.Remove(JsonApiPropertyName.Links); + inlineSchemaForLinksContainer.Properties.Remove(JsonApiPropertyName.Links); - if (schemaRepository.Schemas.TryGetValue(linksSchemaId, out OpenApiSchema? fullSchemaForLinks)) + schemaRepository.Schemas.Remove(referenceSchemaForLinks.GetReferenceId()); + } + else if (visibleLinkTypes != possibleLinkTypes) { - UpdateLinkProperties(fullSchemaForLinks, visibleLinkTypes); + string linksSchemaId = referenceSchemaForLinks.GetReferenceId(); + + if (schemaRepository.Schemas.TryGetValue(linksSchemaId, out IOpenApiSchema? schemaForLinks)) + { + OpenApiSchema inlineSchemaForLinks = schemaForLinks.AsInlineSchema(); + UpdateLinkProperties(inlineSchemaForLinks, visibleLinkTypes); + } } } } - private void UpdateLinkProperties(OpenApiSchema fullSchemaForLinks, LinkTypes availableLinkTypes) + private void UpdateLinkProperties(OpenApiSchema inlineSchemaForLinks, LinkTypes availableLinkTypes) { foreach (string propertyName in LinkTypeToPropertyNamesMap.Where(pair => !availableLinkTypes.HasFlag(pair.Key)).SelectMany(pair => pair.Value)) { - fullSchemaForLinks.Required.Remove(propertyName); - fullSchemaForLinks.Properties.Remove(propertyName); + inlineSchemaForLinks.Required?.Remove(propertyName); + inlineSchemaForLinks.Properties?.Remove(propertyName); } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/MetaSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/MetaSchemaGenerator.cs index 1e1bd07852..83c4a0836f 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/MetaSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/MetaSchemaGenerator.cs @@ -1,5 +1,5 @@ using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -19,29 +19,29 @@ public MetaSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, JsonAp _schemaIdSelector = schemaIdSelector; } - public OpenApiSchema GenerateSchema(SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaRepository); - if (schemaRepository.TryLookupByType(SchemaType, out OpenApiSchema? referenceSchema)) + if (schemaRepository.TryLookupByTypeSafe(SchemaType, out OpenApiSchemaReference? referenceSchema)) { return referenceSchema; } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, SchemaType); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalProperties = new OpenApiSchema { - Nullable = true + Type = JsonSchemaType.Null } }; string schemaId = _schemaIdSelector.GetMetaSchemaId(); - referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); schemaRepository.RegisterType(SchemaType, schemaId); traceScope.TraceSucceeded(schemaId); diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipIdentifierSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipIdentifierSchemaGenerator.cs index 98f176e8df..fb50e61900 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipIdentifierSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipIdentifierSchemaGenerator.cs @@ -1,7 +1,7 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; using JsonApiDotNetCore.Resources.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -34,7 +34,7 @@ public RelationshipIdentifierSchemaGenerator(SchemaGenerationTracer schemaGenera _schemaIdSelector = schemaIdSelector; } - public OpenApiSchema GenerateSchema(RelationshipAttribute relationship, SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(RelationshipAttribute relationship, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(relationship); ArgumentNullException.ThrowIfNull(schemaRepository); @@ -43,52 +43,48 @@ public OpenApiSchema GenerateSchema(RelationshipAttribute relationship, SchemaRe if (schemaRepository.Schemas.ContainsKey(schemaId)) { - return new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = schemaId, - Type = ReferenceType.Schema - } - }; + return new OpenApiSchemaReference(schemaId); } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, relationship); Type relationshipIdentifierConstructedType = typeof(RelationshipIdentifier<>).MakeGenericType(relationship.LeftType.ClrType); - ConsistencyGuard.ThrowIf(schemaRepository.TryLookupByType(relationshipIdentifierConstructedType, out _)); + ConsistencyGuard.ThrowIf(schemaRepository.TryLookupByTypeSafe(relationshipIdentifierConstructedType, out _)); - OpenApiSchema referenceSchemaForIdentifier = _defaultSchemaGenerator.GenerateSchema(relationshipIdentifierConstructedType, schemaRepository); - OpenApiSchema fullSchemaForIdentifier = schemaRepository.Schemas[referenceSchemaForIdentifier.Reference.Id]; + OpenApiSchemaReference referenceSchemaForIdentifier = + _defaultSchemaGenerator.GenerateSchema(relationshipIdentifierConstructedType, schemaRepository).AsReferenceSchema(); - fullSchemaForIdentifier.Properties.Remove(JsonApiPropertyName.Meta); + OpenApiSchema inlineSchemaForIdentifier = schemaRepository.Schemas[referenceSchemaForIdentifier.GetReferenceId()].AsInlineSchema(); - SetResourceType(fullSchemaForIdentifier, relationship.LeftType, schemaRepository); - SetResourceId(fullSchemaForIdentifier, relationship.LeftType, schemaRepository); - SetRelationship(fullSchemaForIdentifier, relationship, schemaRepository); + inlineSchemaForIdentifier.Properties ??= new Dictionary(); + inlineSchemaForIdentifier.Properties.Remove(JsonApiPropertyName.Meta); + + SetResourceType(inlineSchemaForIdentifier.Properties, relationship.LeftType, schemaRepository); + SetResourceId(inlineSchemaForIdentifier.Properties, relationship.LeftType, schemaRepository); + SetRelationship(inlineSchemaForIdentifier.Properties, relationship, schemaRepository); schemaRepository.ReplaceSchemaId(relationshipIdentifierConstructedType, schemaId); - referenceSchemaForIdentifier.Reference.Id = schemaId; + referenceSchemaForIdentifier = new OpenApiSchemaReference(schemaId); traceScope.TraceSucceeded(schemaId); return referenceSchemaForIdentifier; } - private void SetResourceType(OpenApiSchema fullSchemaForIdentifier, ResourceType resourceType, SchemaRepository schemaRepository) + private void SetResourceType(IDictionary schemaProperties, ResourceType resourceType, SchemaRepository schemaRepository) { - OpenApiSchema referenceSchema = _resourceTypeSchemaGenerator.GenerateSchema(resourceType, schemaRepository); - fullSchemaForIdentifier.Properties[JsonApiPropertyName.Type] = referenceSchema.WrapInExtendedSchema(); + OpenApiSchemaReference referenceSchema = _resourceTypeSchemaGenerator.GenerateSchema(resourceType, schemaRepository); + schemaProperties[JsonApiPropertyName.Type] = referenceSchema.WrapInExtendedSchema(); } - private void SetResourceId(OpenApiSchema fullSchemaForResourceData, ResourceType resourceType, SchemaRepository schemaRepository) + private void SetResourceId(IDictionary schemaProperties, ResourceType resourceType, SchemaRepository schemaRepository) { OpenApiSchema idSchema = _resourceIdSchemaGenerator.GenerateSchema(resourceType, schemaRepository); - fullSchemaForResourceData.Properties[JsonApiPropertyName.Id] = idSchema; + schemaProperties[JsonApiPropertyName.Id] = idSchema; } - private void SetRelationship(OpenApiSchema fullSchemaForIdentifier, RelationshipAttribute relationship, SchemaRepository schemaRepository) + private void SetRelationship(IDictionary schemaProperties, RelationshipAttribute relationship, SchemaRepository schemaRepository) { - OpenApiSchema referenceSchema = _relationshipNameSchemaGenerator.GenerateSchema(relationship, schemaRepository); - fullSchemaForIdentifier.Properties[JsonApiPropertyName.Relationship] = referenceSchema.WrapInExtendedSchema(); + OpenApiSchemaReference referenceSchema = _relationshipNameSchemaGenerator.GenerateSchema(relationship, schemaRepository); + schemaProperties[JsonApiPropertyName.Relationship] = referenceSchema.WrapInExtendedSchema(); } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipNameSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipNameSchemaGenerator.cs index 7f5c0c5d3a..38d47c81f6 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipNameSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/RelationshipNameSchemaGenerator.cs @@ -1,6 +1,5 @@ using JsonApiDotNetCore.Resources.Annotations; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -19,7 +18,7 @@ public RelationshipNameSchemaGenerator(SchemaGenerationTracer schemaGenerationTr _schemaIdSelector = schemaIdSelector; } - public OpenApiSchema GenerateSchema(RelationshipAttribute relationship, SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(RelationshipAttribute relationship, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(relationship); ArgumentNullException.ThrowIfNull(schemaRepository); @@ -28,25 +27,18 @@ public OpenApiSchema GenerateSchema(RelationshipAttribute relationship, SchemaRe if (schemaRepository.Schemas.ContainsKey(schemaId)) { - return new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = schemaId, - Type = ReferenceType.Schema - } - }; + return new OpenApiSchemaReference(schemaId); } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, relationship); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "string", - Enum = [new OpenApiString(relationship.PublicName)] + Type = JsonSchemaType.String, + Enum = [relationship.PublicName] }; - OpenApiSchema referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + OpenApiSchemaReference referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); traceScope.TraceSucceeded(schemaId); return referenceSchema; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs index f361db8183..09e38f6545 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceIdSchemaGenerator.cs @@ -2,7 +2,7 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using JsonApiDotNetCore.OpenApi.Swashbuckle.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -40,10 +40,8 @@ public OpenApiSchema GenerateSchema(ResourceType resourceType, SchemaRepository ArgumentNullException.ThrowIfNull(resourceType); ArgumentNullException.ThrowIfNull(schemaRepository); - OpenApiSchema idSchema = _defaultSchemaGenerator.GenerateSchema(resourceType.IdentityClrType, schemaRepository); - ConsistencyGuard.ThrowIf(idSchema.Reference != null); - - idSchema.Type = "string"; + OpenApiSchema idSchema = _defaultSchemaGenerator.GenerateSchema(resourceType.IdentityClrType, schemaRepository).AsInlineSchema(); + idSchema.Type = JsonSchemaType.String; var hideIdTypeAttribute = resourceType.ClrType.GetCustomAttribute(); diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceTypeSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceTypeSchemaGenerator.cs index eb933bedbe..8eb4771cb7 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceTypeSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Components/ResourceTypeSchemaGenerator.cs @@ -1,7 +1,6 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; @@ -20,70 +19,63 @@ public ResourceTypeSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer _schemaIdSelector = schemaIdSelector; } - public OpenApiSchema GenerateSchema(ResourceType resourceType, SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(ResourceType resourceType, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(resourceType); ArgumentNullException.ThrowIfNull(schemaRepository); - if (schemaRepository.TryLookupByType(resourceType.ClrType, out OpenApiSchema? referenceSchema)) + if (schemaRepository.TryLookupByTypeSafe(resourceType.ClrType, out OpenApiSchemaReference? referenceSchema)) { return referenceSchema; } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, resourceType.ClrType); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "string", - Enum = resourceType.ClrType.IsAbstract ? [] : [new OpenApiString(resourceType.PublicName)], - Extensions = + Type = JsonSchemaType.String, + Enum = resourceType.ClrType.IsAbstract ? [] : [resourceType.PublicName], + Extensions = new SortedDictionary(StringComparer.Ordinal) { - [StringEnumOrderingFilter.RequiresSortKey] = new OpenApiBoolean(true) + [StringEnumOrderingFilter.RequiresSortKey] = new JsonNodeExtension(true) } }; foreach (ResourceType derivedType in resourceType.GetAllConcreteDerivedTypes()) { - fullSchema.Enum.Add(new OpenApiString(derivedType.PublicName)); + inlineSchema.Enum.Add(derivedType.PublicName); } string schemaId = _schemaIdSelector.GetResourceTypeSchemaId(resourceType); - referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); schemaRepository.RegisterType(resourceType.ClrType, schemaId); traceScope.TraceSucceeded(schemaId); return referenceSchema; } - public OpenApiSchema GenerateSchema(SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(SchemaRepository schemaRepository) { string schemaId = _schemaIdSelector.GetResourceTypeSchemaId(null); if (schemaRepository.Schemas.ContainsKey(schemaId)) { - return new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = schemaId, - Type = ReferenceType.Schema - } - }; + return new OpenApiSchemaReference(schemaId); } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "string", - Extensions = + Type = JsonSchemaType.String, + Extensions = new SortedDictionary(StringComparer.Ordinal) { - [StringEnumOrderingFilter.RequiresSortKey] = new OpenApiBoolean(true) + [StringEnumOrderingFilter.RequiresSortKey] = new JsonNodeExtension(true) } }; - OpenApiSchema referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + OpenApiSchemaReference referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); traceScope.TraceSucceeded(schemaId); return referenceSchema; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/AtomicOperationsDocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/AtomicOperationsDocumentSchemaGenerator.cs index 648831fcbb..54a5b25179 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/AtomicOperationsDocumentSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/AtomicOperationsDocumentSchemaGenerator.cs @@ -7,8 +7,7 @@ using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; using JsonApiDotNetCore.Resources.Annotations; using JsonApiDotNetCore.Serialization.Objects; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; @@ -68,7 +67,7 @@ public override bool CanGenerate(Type schemaType) return schemaType == typeof(OperationsRequestDocument) || schemaType == typeof(OperationsResponseDocument); } - protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) + protected override OpenApiSchemaReference GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaType); ArgumentNullException.ThrowIfNull(schemaRepository); @@ -84,7 +83,7 @@ protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaR GenerateSchemasForResponseDocument(schemaRepository); } - return _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository); + return _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository).AsReferenceSchema(); } private void GenerateSchemasForRequestDocument(SchemaRepository schemaRepository) @@ -97,44 +96,43 @@ private void GenerateSchemasForRequestDocument(SchemaRepository schemaRepository } } - private OpenApiSchema GenerateSchemaForAbstractOperation(SchemaRepository schemaRepository) + private OpenApiSchemaReference GenerateSchemaForAbstractOperation(SchemaRepository schemaRepository) { - if (schemaRepository.TryLookupByType(AtomicOperationAbstractType, out OpenApiSchema? referenceSchema)) + if (schemaRepository.TryLookupByTypeSafe(AtomicOperationAbstractType, out OpenApiSchemaReference? referenceSchema)) { return referenceSchema; } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, AtomicOperationAbstractType); - OpenApiSchema referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); + OpenApiSchemaReference referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); - var fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "object", - Required = new SortedSet([OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName]), - Properties = new Dictionary + Type = JsonSchemaType.Object, + Required = new SortedSet([OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName], StringComparer.Ordinal), + Properties = new Dictionary { - [OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName] = new() + [OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName] = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, - [referenceSchemaForMeta.Reference.Id] = referenceSchemaForMeta.WrapInExtendedSchema() + [referenceSchemaForMeta.GetReferenceId()] = referenceSchemaForMeta.WrapInExtendedSchema() }, AdditionalPropertiesAllowed = false, Discriminator = new OpenApiDiscriminator { - PropertyName = OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName, - Mapping = new SortedDictionary(StringComparer.Ordinal) + PropertyName = OpenApiMediaTypeExtension.FullyQualifiedOpenApiDiscriminatorPropertyName }, - Extensions = + Extensions = new SortedDictionary(StringComparer.Ordinal) { - ["x-abstract"] = new OpenApiBoolean(true) + ["x-abstract"] = new JsonNodeExtension(true) } }; string schemaId = _schemaIdSelector.GetSchemaId(AtomicOperationAbstractType); - referenceSchema = schemaRepository.AddDefinition(schemaId, fullSchema); + referenceSchema = schemaRepository.AddDefinition(schemaId, inlineSchema); schemaRepository.RegisterType(AtomicOperationAbstractType, schemaId); traceScope.TraceSucceeded(schemaId); @@ -184,22 +182,25 @@ private void GenerateSchemaForResourceOperation(Type operationOpenType, Resource if (hasDataProperty) { - _ = _dataContainerSchemaGenerator.GenerateSchema(operationConstructedType, resourceType, true, false, schemaRepository); + _dataContainerSchemaGenerator.GenerateSchema(operationConstructedType, resourceType, true, false, schemaRepository); } } - OpenApiSchema referenceSchemaForOperation = _defaultSchemaGenerator.GenerateSchema(operationConstructedType, schemaRepository); - OpenApiSchema fullSchemaForOperation = schemaRepository.Schemas[referenceSchemaForOperation.Reference.Id]; - fullSchemaForOperation.AdditionalPropertiesAllowed = false; - OpenApiSchema inlineSchemaForOperation = fullSchemaForOperation.UnwrapLastExtendedSchema(); + OpenApiSchemaReference referenceSchemaForOperation = + _defaultSchemaGenerator.GenerateSchema(operationConstructedType, schemaRepository).AsReferenceSchema(); + + OpenApiSchema compositeInlineSchemaForOperation = schemaRepository.Schemas[referenceSchemaForOperation.GetReferenceId()].AsInlineSchema(); + compositeInlineSchemaForOperation.AdditionalPropertiesAllowed = false; + OpenApiSchema inlineSchemaForOperation = compositeInlineSchemaForOperation.UnwrapLastExtendedSchema().AsInlineSchema(); if (needsEmptyDerivedSchema) { Type baseOperationSchemaType = ChangeResourceTypeInSchemaType(operationOpenType, resourceType.BaseType!); - OpenApiSchema referenceSchemaForBaseOperation = schemaRepository.LookupByType(baseOperationSchemaType); + OpenApiSchemaReference referenceSchemaForBaseOperation = schemaRepository.LookupByType(baseOperationSchemaType); RemoveProperties(inlineSchemaForOperation); - fullSchemaForOperation.AllOf[0] = referenceSchemaForBaseOperation; + compositeInlineSchemaForOperation.AllOf ??= new List(); + compositeInlineSchemaForOperation.AllOf[0] = referenceSchemaForBaseOperation; } else { @@ -208,7 +209,7 @@ private void GenerateSchemaForResourceOperation(Type operationOpenType, Resource MapInDiscriminator(referenceSchemaForOperation, schemaRepository); - traceScope.TraceSucceeded(referenceSchemaForOperation.Reference.Id); + traceScope.TraceSucceeded(referenceSchemaForOperation.GetReferenceId()); } foreach (ResourceType derivedType in resourceType.DirectlyDerivedTypes) @@ -248,26 +249,38 @@ private static Type ChangeResourceTypeInSchemaType(Type schemaOpenType, Resource return schemaOpenType.MakeGenericType(resourceType.ClrType); } - private static void RemoveProperties(OpenApiSchema fullSchema) + private static void RemoveProperties(OpenApiSchema inlineSchema) { - foreach (string propertyName in fullSchema.Properties.Keys) + if (inlineSchema.Properties != null) { - fullSchema.Properties.Remove(propertyName); - fullSchema.Required.Remove(propertyName); + foreach (string propertyName in inlineSchema.Properties.Keys) + { + inlineSchema.Properties.Remove(propertyName); + inlineSchema.Required?.Remove(propertyName); + } } } - private void SetOperationCode(OpenApiSchema fullSchema, AtomicOperationCode operationCode, SchemaRepository schemaRepository) + private void SetOperationCode(OpenApiSchema inlineSchema, AtomicOperationCode operationCode, SchemaRepository schemaRepository) { - OpenApiSchema referenceSchema = _atomicOperationCodeSchemaGenerator.GenerateSchema(operationCode, schemaRepository); - fullSchema.Properties[JsonApiPropertyName.Op] = referenceSchema.WrapInExtendedSchema(); + OpenApiSchemaReference referenceSchema = _atomicOperationCodeSchemaGenerator.GenerateSchema(operationCode, schemaRepository); + inlineSchema.Properties ??= new Dictionary(); + inlineSchema.Properties[JsonApiPropertyName.Op] = referenceSchema.WrapInExtendedSchema(); } - private static void MapInDiscriminator(OpenApiSchema referenceSchemaForOperation, SchemaRepository schemaRepository) + private static void MapInDiscriminator(OpenApiSchemaReference referenceSchemaForOperation, SchemaRepository schemaRepository) { - OpenApiSchema referenceSchemaForAbstractOperation = schemaRepository.LookupByType(AtomicOperationAbstractType); - OpenApiSchema fullSchemaForAbstractOperation = schemaRepository.Schemas[referenceSchemaForAbstractOperation.Reference.Id]; - fullSchemaForAbstractOperation.Discriminator.Mapping.Add(referenceSchemaForOperation.Reference.Id, referenceSchemaForOperation.Reference.ReferenceV3); + OpenApiSchemaReference referenceSchemaForAbstractOperation = schemaRepository.LookupByType(AtomicOperationAbstractType); + OpenApiSchema inlineSchemaForAbstractOperation = schemaRepository.Schemas[referenceSchemaForAbstractOperation.GetReferenceId()].AsInlineSchema(); + AddToDiscriminatorMapping(inlineSchemaForAbstractOperation, referenceSchemaForOperation.GetReferenceId(), referenceSchemaForOperation); + } + + private static void AddToDiscriminatorMapping(OpenApiSchema inlineSchema, string schemaId, OpenApiSchemaReference mappingValueReferenceSchema) + { + ConsistencyGuard.ThrowIf(inlineSchema.Discriminator is null); + + inlineSchema.Discriminator.Mapping ??= new SortedDictionary(StringComparer.Ordinal); + inlineSchema.Discriminator.Mapping.Add(schemaId, mappingValueReferenceSchema); } private static HashSet GetRelationshipsInTypeHierarchy(ResourceType baseType) @@ -314,7 +327,7 @@ private void GenerateSchemaForRelationshipOperation(Type operationOpenType, Rela RelationshipAttribute? relationshipInAnyBaseResourceType = GetRelationshipEnabledInAnyBase(relationship, writeOperation); - OpenApiSchema? referenceSchemaForRelationshipIdentifier; + OpenApiSchemaReference? referenceSchemaForRelationshipIdentifier; if (relationshipInAnyBaseResourceType == null) { @@ -329,29 +342,33 @@ private void GenerateSchemaForRelationshipOperation(Type operationOpenType, Rela } Type operationConstructedType = ChangeResourceTypeInSchemaType(operationOpenType, relationship.RightType); - _ = _dataContainerSchemaGenerator.GenerateSchema(operationConstructedType, relationship.RightType, true, false, schemaRepository); + _dataContainerSchemaGenerator.GenerateSchema(operationConstructedType, relationship.RightType, true, false, schemaRepository); // This complicated implementation that generates a temporary schema stems from the fact that GetSchemaId takes a Type. // We could feed it a constructed type with TLeftResource and TRightResource, but there's no way to include // the relationship name because there's no runtime Type available for it. string schemaId = _schemaIdSelector.GetRelationshipAtomicOperationSchemaId(relationship, operationCode); - OpenApiSchema referenceSchemaForOperation = _defaultSchemaGenerator.GenerateSchema(operationConstructedType, schemaRepository); - OpenApiSchema fullSchemaForOperation = schemaRepository.Schemas[referenceSchemaForOperation.Reference.Id]; - fullSchemaForOperation.AdditionalPropertiesAllowed = false; + OpenApiSchemaReference referenceSchemaForOperation = + _defaultSchemaGenerator.GenerateSchema(operationConstructedType, schemaRepository).AsReferenceSchema(); + + OpenApiSchema compositeInlineSchemaForOperation = schemaRepository.Schemas[referenceSchemaForOperation.GetReferenceId()].AsInlineSchema(); + compositeInlineSchemaForOperation.AdditionalPropertiesAllowed = false; - OpenApiSchema inlineSchemaForOperation = fullSchemaForOperation.UnwrapLastExtendedSchema(); + OpenApiSchema inlineSchemaForOperation = compositeInlineSchemaForOperation.UnwrapLastExtendedSchema().AsInlineSchema(); SetOperationCode(inlineSchemaForOperation, operationCode, schemaRepository); + inlineSchemaForOperation.Properties ??= new Dictionary(); if (referenceSchemaForRelationshipIdentifier != null) { inlineSchemaForOperation.Properties[JsonApiPropertyName.Ref] = referenceSchemaForRelationshipIdentifier.WrapInExtendedSchema(); } - inlineSchemaForOperation.Properties[JsonApiPropertyName.Data].Nullable = _resourceFieldValidationMetadataProvider.IsNullable(relationship); + bool isNullable = _resourceFieldValidationMetadataProvider.IsNullable(relationship); + ((OpenApiSchema)inlineSchemaForOperation.Properties[JsonApiPropertyName.Data]).SetNullable(isNullable); schemaRepository.ReplaceSchemaId(operationConstructedType, schemaId); - referenceSchemaForOperation.Reference.Id = schemaId; + referenceSchemaForOperation = new OpenApiSchemaReference(schemaId); if (relationshipInAnyBaseResourceType != null) { @@ -360,14 +377,8 @@ private void GenerateSchemaForRelationshipOperation(Type operationOpenType, Rela string baseRelationshipSchemaId = _schemaIdSelector.GetRelationshipAtomicOperationSchemaId(relationshipInAnyBaseResourceType, operationCode); ConsistencyGuard.ThrowIf(!schemaRepository.Schemas.ContainsKey(baseRelationshipSchemaId)); - fullSchemaForOperation.AllOf[0] = new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = baseRelationshipSchemaId, - Type = ReferenceType.Schema - } - }; + compositeInlineSchemaForOperation.AllOf ??= new List(); + compositeInlineSchemaForOperation.AllOf[0] = new OpenApiSchemaReference(baseRelationshipSchemaId); } MapInDiscriminator(referenceSchemaForOperation, schemaRepository); @@ -476,7 +487,7 @@ private void GenerateSchemasForResponseDocument(SchemaRepository schemaRepositor if (IsResourceTypeEnabled(resourceType, WriteOperationKind.CreateResource) || IsResourceTypeEnabled(resourceType, WriteOperationKind.UpdateResource)) { - _ = _dataContainerSchemaGenerator.GenerateSchema(typeof(AtomicResult), resourceType, false, false, schemaRepository); + _dataContainerSchemaGenerator.GenerateSchema(typeof(AtomicResult), resourceType, false, false, schemaRepository); } } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/DocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/DocumentSchemaGenerator.cs index 740b2fca43..6ab806485f 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/DocumentSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/DocumentSchemaGenerator.cs @@ -1,6 +1,6 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; @@ -31,12 +31,12 @@ protected DocumentSchemaGenerator(SchemaGenerationTracer schemaGenerationTracer, public abstract bool CanGenerate(Type schemaType); - public OpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepository) + public OpenApiSchemaReference GenerateSchema(Type schemaType, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaType); ArgumentNullException.ThrowIfNull(schemaRepository); - if (schemaRepository.TryLookupByType(schemaType, out OpenApiSchema? referenceSchema)) + if (schemaRepository.TryLookupByTypeSafe(schemaType, out OpenApiSchemaReference? referenceSchema)) { return referenceSchema; } @@ -46,23 +46,22 @@ public OpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepo _metaSchemaGenerator.GenerateSchema(schemaRepository); referenceSchema = GenerateDocumentSchema(schemaType, schemaRepository); - OpenApiSchema fullSchema = schemaRepository.Schemas[referenceSchema.Reference.Id]; + OpenApiSchema inlineSchema = schemaRepository.Schemas[referenceSchema.GetReferenceId()].AsInlineSchema(); - _linksVisibilitySchemaGenerator.UpdateSchemaForTopLevel(schemaType, fullSchema, schemaRepository); + _linksVisibilitySchemaGenerator.UpdateSchemaForTopLevel(schemaType, inlineSchema, schemaRepository); - SetJsonApiVersion(fullSchema, schemaRepository); + SetJsonApiVersion(inlineSchema, schemaRepository); - traceScope.TraceSucceeded(referenceSchema.Reference.Id); + traceScope.TraceSucceeded(referenceSchema.GetReferenceId()); return referenceSchema; } - protected abstract OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository); + protected abstract OpenApiSchemaReference GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository); - private void SetJsonApiVersion(OpenApiSchema fullSchema, SchemaRepository schemaRepository) + private void SetJsonApiVersion(OpenApiSchema inlineSchema, SchemaRepository schemaRepository) { - if (fullSchema.Properties.ContainsKey(JsonApiPropertyName.Jsonapi) && !_options.IncludeJsonApiVersion) + if (!_options.IncludeJsonApiVersion && inlineSchema.Properties != null && inlineSchema.Properties.Remove(JsonApiPropertyName.Jsonapi)) { - fullSchema.Properties.Remove(JsonApiPropertyName.Jsonapi); schemaRepository.Schemas.Remove(JsonApiPropertyName.Jsonapi); } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ErrorResponseDocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ErrorResponseDocumentSchemaGenerator.cs index 3d305e889b..57a4d2ff26 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ErrorResponseDocumentSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ErrorResponseDocumentSchemaGenerator.cs @@ -2,7 +2,7 @@ using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.Documents; using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; using JsonApiDotNetCore.Serialization.Objects; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; @@ -34,27 +34,28 @@ public override bool CanGenerate(Type schemaType) return schemaType == typeof(ErrorResponseDocument); } - protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) + protected override OpenApiSchemaReference GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaType); ArgumentNullException.ThrowIfNull(schemaRepository); - OpenApiSchema referenceSchemaForErrorObject = GenerateSchemaForErrorObject(schemaRepository); - OpenApiSchema fullSchemaForErrorObject = schemaRepository.Schemas[referenceSchemaForErrorObject.Reference.Id]; + OpenApiSchemaReference referenceSchemaForErrorObject = GenerateSchemaForErrorObject(schemaRepository); + OpenApiSchema inlineSchemaForErrorObject = schemaRepository.Schemas[referenceSchemaForErrorObject.GetReferenceId()].AsInlineSchema(); - OpenApiSchema referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); - fullSchemaForErrorObject.Properties[JsonApiPropertyName.Meta] = referenceSchemaForMeta.WrapInExtendedSchema(); + OpenApiSchemaReference referenceSchemaForMeta = _metaSchemaGenerator.GenerateSchema(schemaRepository); + inlineSchemaForErrorObject.Properties ??= new Dictionary(); + inlineSchemaForErrorObject.Properties[JsonApiPropertyName.Meta] = referenceSchemaForMeta.WrapInExtendedSchema(); - return _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository); + return _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository).AsReferenceSchema(); } - private OpenApiSchema GenerateSchemaForErrorObject(SchemaRepository schemaRepository) + private OpenApiSchemaReference GenerateSchemaForErrorObject(SchemaRepository schemaRepository) { using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, ErrorObjectType); - OpenApiSchema referenceSchema = _defaultSchemaGenerator.GenerateSchema(ErrorObjectType, schemaRepository); + OpenApiSchemaReference referenceSchema = _defaultSchemaGenerator.GenerateSchema(ErrorObjectType, schemaRepository).AsReferenceSchema(); - traceScope.TraceSucceeded(referenceSchema.Reference.Id); + traceScope.TraceSucceeded(referenceSchema.GetReferenceId()); return referenceSchema; } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ResourceOrRelationshipDocumentSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ResourceOrRelationshipDocumentSchemaGenerator.cs index 0762e5b8c1..eff27e5eb8 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ResourceOrRelationshipDocumentSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/Documents/ResourceOrRelationshipDocumentSchemaGenerator.cs @@ -1,7 +1,7 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; using JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; @@ -34,7 +34,7 @@ public override bool CanGenerate(Type schemaType) return JsonApiSchemaFacts.IsRequestDocumentSchemaType(schemaType) || JsonApiSchemaFacts.IsResponseDocumentSchemaType(schemaType); } - protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) + protected override OpenApiSchemaReference GenerateDocumentSchema(Type schemaType, SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaType); ArgumentNullException.ThrowIfNull(schemaRepository); @@ -42,14 +42,17 @@ protected override OpenApiSchema GenerateDocumentSchema(Type schemaType, SchemaR var resourceSchemaType = ResourceSchemaType.Create(schemaType, _resourceGraph); bool isRequestSchema = JsonApiSchemaFacts.IsRequestDocumentSchemaType(resourceSchemaType.SchemaOpenType); - _ = _dataContainerSchemaGenerator.GenerateSchema(schemaType, resourceSchemaType.ResourceType, isRequestSchema, !isRequestSchema, schemaRepository); + _dataContainerSchemaGenerator.GenerateSchema(schemaType, resourceSchemaType.ResourceType, isRequestSchema, !isRequestSchema, schemaRepository); - OpenApiSchema? referenceSchemaForDocument = _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository); - OpenApiSchema inlineSchemaForDocument = schemaRepository.Schemas[referenceSchemaForDocument.Reference.Id].UnwrapLastExtendedSchema(); + OpenApiSchemaReference referenceSchemaForDocument = _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository).AsReferenceSchema(); + + OpenApiSchema inlineSchemaForDocument = + schemaRepository.Schemas[referenceSchemaForDocument.GetReferenceId()].UnwrapLastExtendedSchema().AsInlineSchema(); if (JsonApiSchemaFacts.HasNullableDataProperty(resourceSchemaType.SchemaOpenType)) { - inlineSchemaForDocument.Properties[JsonApiPropertyName.Data].Nullable = true; + inlineSchemaForDocument.Properties ??= new Dictionary(); + inlineSchemaForDocument.Properties[JsonApiPropertyName.Data].AsInlineSchema().SetNullable(true); } return referenceSchemaForDocument; diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/GenerationCacheSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/GenerationCacheSchemaGenerator.cs index d67203979a..5750899a52 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/GenerationCacheSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/GenerationCacheSchemaGenerator.cs @@ -1,8 +1,7 @@ using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata.ActionMethods; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators; @@ -31,40 +30,40 @@ public bool HasAtomicOperationsEndpoint(SchemaRepository schemaRepository) { ArgumentNullException.ThrowIfNull(schemaRepository); - OpenApiSchema fullSchema = GenerateFullSchema(schemaRepository); + OpenApiSchema inlineSchema = GenerateInlineSchema(schemaRepository); - var hasAtomicOperationsEndpoint = (OpenApiBoolean)fullSchema.Properties[HasAtomicOperationsEndpointPropertyName].Default; - return hasAtomicOperationsEndpoint.Value; + return inlineSchema.Properties != null && + inlineSchema.Properties.TryGetValue(HasAtomicOperationsEndpointPropertyName, out IOpenApiSchema? propertyValue) && (bool)propertyValue.Default!; } - private OpenApiSchema GenerateFullSchema(SchemaRepository schemaRepository) + private OpenApiSchema GenerateInlineSchema(SchemaRepository schemaRepository) { - if (schemaRepository.Schemas.TryGetValue(SchemaId, out OpenApiSchema? fullSchema)) + if (schemaRepository.Schemas.TryGetValue(SchemaId, out IOpenApiSchema? existingSchema)) { - return fullSchema; + return existingSchema.AsInlineSchema(); } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this); bool hasAtomicOperationsEndpoint = EvaluateHasAtomicOperationsEndpoint(); - fullSchema = new OpenApiSchema + var inlineSchema = new OpenApiSchema { - Type = "object", - Properties = new Dictionary + Type = JsonSchemaType.Object, + Properties = new Dictionary { - [HasAtomicOperationsEndpointPropertyName] = new() + [HasAtomicOperationsEndpointPropertyName] = new OpenApiSchema { - Type = "boolean", - Default = new OpenApiBoolean(hasAtomicOperationsEndpoint) + Type = JsonSchemaType.Boolean, + Default = hasAtomicOperationsEndpoint } } }; - schemaRepository.AddDefinition(SchemaId, fullSchema); + schemaRepository.AddDefinition(SchemaId, inlineSchema); traceScope.TraceSucceeded(SchemaId); - return fullSchema; + return inlineSchema; } private bool EvaluateHasAtomicOperationsEndpoint() diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs index b8e1d9f053..a8516daa0b 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaGenerators/JsonApiSchemaGenerator.cs @@ -3,7 +3,7 @@ using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Documents; using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators; @@ -26,7 +26,7 @@ public JsonApiSchemaGenerator(SchemaGenerator defaultSchemaGenerator, ResourceId _documentSchemaGenerators = documentSchemaGenerators as DocumentSchemaGenerator[] ?? documentSchemaGenerators.ToArray(); } - public OpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepository, MemberInfo? memberInfo = null, ParameterInfo? parameterInfo = null, + public IOpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepository, MemberInfo? memberInfo = null, ParameterInfo? parameterInfo = null, ApiParameterRouteInfo? routeInfo = null) { ArgumentNullException.ThrowIfNull(schemaType); @@ -41,16 +41,16 @@ public OpenApiSchema GenerateSchema(Type schemaType, SchemaRepository schemaRepo if (schemaGenerator != null) { - OpenApiSchema referenceSchema = schemaGenerator.GenerateSchema(schemaType, schemaRepository); + IOpenApiSchema documentSchema = schemaGenerator.GenerateSchema(schemaType, schemaRepository); if (memberInfo != null || parameterInfo != null) { // For unknown reasons, Swashbuckle chooses to wrap request bodies in allOf, but not response bodies. // We just replicate that behavior here. See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/861#issuecomment-1373631712. - referenceSchema = referenceSchema.WrapInExtendedSchema(); + documentSchema = documentSchema.WrapInExtendedSchema(); } - return referenceSchema; + return documentSchema; } return _defaultSchemaGenerator.GenerateSchema(schemaType, schemaRepository, memberInfo, parameterInfo, routeInfo); diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaRepositoryExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaRepositoryExtensions.cs index 669c50b4e0..f6f05fded3 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaRepositoryExtensions.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SchemaRepositoryExtensions.cs @@ -1,5 +1,6 @@ +using System.Diagnostics.CodeAnalysis; using System.Reflection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle; @@ -28,12 +29,12 @@ private static FieldInfo GetReservedIdsField() return field; } - public static OpenApiSchema LookupByType(this SchemaRepository schemaRepository, Type schemaType) + public static OpenApiSchemaReference LookupByType(this SchemaRepository schemaRepository, Type schemaType) { ArgumentNullException.ThrowIfNull(schemaRepository); ArgumentNullException.ThrowIfNull(schemaType); - if (!schemaRepository.TryLookupByType(schemaType, out OpenApiSchema? referenceSchema)) + if (!schemaRepository.TryLookupByTypeSafe(schemaType, out OpenApiSchemaReference? referenceSchema)) { throw new InvalidOperationException($"Reference schema for '{schemaType.Name}' does not exist."); } @@ -41,20 +42,27 @@ public static OpenApiSchema LookupByType(this SchemaRepository schemaRepository, return referenceSchema; } + public static bool TryLookupByTypeSafe(this SchemaRepository schemaRepository, Type type, [NotNullWhen(true)] out OpenApiSchemaReference? referenceSchema) + { + bool result = schemaRepository.TryLookupByType(type, out OpenApiSchemaReference? obliviousReferenceSchema); + referenceSchema = result ? obliviousReferenceSchema : null; + return result; + } + public static void ReplaceSchemaId(this SchemaRepository schemaRepository, Type oldSchemaType, string newSchemaId) { ArgumentNullException.ThrowIfNull(schemaRepository); ArgumentNullException.ThrowIfNull(oldSchemaType); ArgumentException.ThrowIfNullOrEmpty(newSchemaId); - if (schemaRepository.TryLookupByType(oldSchemaType, out OpenApiSchema? referenceSchema)) + if (schemaRepository.TryLookupByTypeSafe(oldSchemaType, out OpenApiSchemaReference? referenceSchema)) { - string oldSchemaId = referenceSchema.Reference.Id; + string oldSchemaId = referenceSchema.GetReferenceId(); - OpenApiSchema fullSchema = schemaRepository.Schemas[oldSchemaId]; + IOpenApiSchema targetSchema = schemaRepository.Schemas[oldSchemaId]; schemaRepository.Schemas.Remove(oldSchemaId); - schemaRepository.Schemas.Add(newSchemaId, fullSchema); + schemaRepository.Schemas.Add(newSchemaId, targetSchema); var reservedIds = (Dictionary)ReservedIdsField.GetValue(schemaRepository)!; reservedIds.Remove(oldSchemaType); diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SetSchemaTypeToObjectDocumentFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SetSchemaTypeToObjectDocumentFilter.cs index 2764f868e6..da6672ed6a 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SetSchemaTypeToObjectDocumentFilter.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SetSchemaTypeToObjectDocumentFilter.cs @@ -1,5 +1,5 @@ using JetBrains.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle; @@ -11,12 +11,15 @@ internal sealed class SetSchemaTypeToObjectDocumentFilter : IDocumentFilter public void Apply(OpenApiDocument document, DocumentFilterContext context) { - foreach (OpenApiSchema schema in document.Components.Schemas.Values) + if (document.Components?.Schemas != null) { - if (schema.Extensions.ContainsKey(RequiresRootObjectTypeKey)) + foreach (OpenApiSchema inlineSchema in document.Components.Schemas.Values.OfType()) { - schema.Type = "object"; - schema.Extensions.Remove(RequiresRootObjectTypeKey); + if (inlineSchema.Extensions != null && inlineSchema.Extensions.ContainsKey(RequiresRootObjectTypeKey)) + { + inlineSchema.Type = JsonSchemaType.Object; + inlineSchema.Extensions.Remove(RequiresRootObjectTypeKey); + } } } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs index b34b580f66..e5ccf92379 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/DocumentationOpenApiOperationFilter.cs @@ -8,8 +8,7 @@ using JsonApiDotNetCore.Resources.Annotations; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.Net.Http.Headers; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; @@ -75,11 +74,11 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context) bool hasHeadVerb = context.ApiDescription.HttpMethod == "HEAD"; - if (hasHeadVerb) + if (hasHeadVerb && operation.Responses != null) { - foreach (OpenApiResponse response in operation.Responses.Values) + foreach (IOpenApiResponse response in operation.Responses.Values) { - response.Content.Clear(); + response.Content?.Clear(); } } @@ -170,7 +169,7 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context) private static void ApplyGetPrimary(OpenApiOperation operation, ResourceType resourceType, bool hasHeadVerb) { - if (operation.Parameters.Count == 0) + if (operation.Parameters == null || operation.Parameters.Count == 0) { if (hasHeadVerb) { @@ -221,7 +220,7 @@ private static void ApplyGetPrimary(OpenApiOperation operation, ResourceType res SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); } - SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to retrieve."); + SetParameterDescription(operation.Parameters, 0, $"The identifier of the {singularName} to retrieve."); AddQueryStringParameters(operation, false); AddRequestHeaderIfNoneMatch(operation); SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad); @@ -264,7 +263,7 @@ private void ApplyPatchResource(OpenApiOperation operation, ResourceType resourc string singularName = resourceType.PublicName.Singularize(); SetOperationSummary(operation, $"Updates an existing {singularName}."); - SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to update."); + SetParameterDescription(operation.Parameters, 0, $"The identifier of the {singularName} to update."); AddQueryStringParameters(operation, false); SetRequestBodyDescription(operation.RequestBody, @@ -287,7 +286,7 @@ private void ApplyDeleteResource(OpenApiOperation operation, ResourceType resour string singularName = resourceType.PublicName.Singularize(); SetOperationSummary(operation, $"Deletes an existing {singularName} by its identifier."); - SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularName} to delete."); + SetParameterDescription(operation.Parameters, 0, $"The identifier of the {singularName} to delete."); SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, $"The {singularName} was successfully deleted."); SetResponseDescription(operation.Responses, HttpStatusCode.NotFound, $"The {singularName} does not exist."); } @@ -325,7 +324,7 @@ relationship is HasOneAttribute SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); } - SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} whose related {rightName} to retrieve."); + SetParameterDescription(operation.Parameters, 0, $"The identifier of the {singularLeftName} whose related {rightName} to retrieve."); AddQueryStringParameters(operation, false); AddRequestHeaderIfNoneMatch(operation); SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad); @@ -367,7 +366,7 @@ relationship is HasOneAttribute SetResponseHeaderETag(operation.Responses, HttpStatusCode.NotModified); } - SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} whose related {singularRightName} {ident} to retrieve."); + SetParameterDescription(operation.Parameters, 0, $"The identifier of the {singularLeftName} whose related {singularRightName} {ident} to retrieve."); AddQueryStringParameters(operation, true); AddRequestHeaderIfNoneMatch(operation); SetResponseDescription(operation.Responses, HttpStatusCode.BadRequest, TextQueryStringBad); @@ -380,7 +379,7 @@ private void ApplyPostRelationship(OpenApiOperation operation, RelationshipAttri string rightName = relationship.RightType.PublicName; SetOperationSummary(operation, $"Adds existing {rightName} to the {relationship} relationship of an individual {singularLeftName}."); - SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} to add {rightName} to."); + SetParameterDescription(operation.Parameters, 0, $"The identifier of the {singularLeftName} to add {rightName} to."); SetRequestBodyDescription(operation.RequestBody, $"The identities of the {rightName} to add to the {relationship} relationship."); SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, @@ -405,7 +404,7 @@ relationship is HasOneAttribute : $"Assigns an existing {rightName} to the {relationship} relationship of an individual {singularLeftName}." : $"Assigns existing {rightName} to the {relationship} relationship of an individual {singularLeftName}."); - SetParameterDescription(operation.Parameters[0], + SetParameterDescription(operation.Parameters, 0, isOptional ? $"The identifier of the {singularLeftName} whose {relationship} relationship to assign or clear." : $"The identifier of the {singularLeftName} whose {relationship} relationship to assign."); @@ -432,7 +431,7 @@ private void ApplyDeleteRelationship(OpenApiOperation operation, RelationshipAtt string rightName = relationship.RightType.PublicName; SetOperationSummary(operation, $"Removes existing {rightName} from the {relationship} relationship of an individual {singularLeftName}."); - SetParameterDescription(operation.Parameters[0], $"The identifier of the {singularLeftName} to remove {rightName} from."); + SetParameterDescription(operation.Parameters, 0, $"The identifier of the {singularLeftName} to remove {rightName} from."); SetRequestBodyDescription(operation.RequestBody, $"The identities of the {rightName} to remove from the {relationship} relationship."); SetResponseDescription(operation.Responses, HttpStatusCode.NoContent, @@ -462,25 +461,35 @@ private static void SetOperationRemarks(OpenApiOperation operation, string descr operation.Description = XmlCommentsTextHelper.Humanize(description); } - private static void SetParameterDescription(OpenApiParameter parameter, string description) + private static void SetParameterDescription(IList? parameters, int index, string description) { + ConsistencyGuard.ThrowIf(parameters is null); + + IOpenApiParameter parameter = parameters[index]; parameter.Description = XmlCommentsTextHelper.Humanize(description); } - private static void SetRequestBodyDescription(OpenApiRequestBody requestBody, string description) + private static void SetRequestBodyDescription(IOpenApiRequestBody? requestBody, string description) { + ConsistencyGuard.ThrowIf(requestBody is null); + requestBody.Description = XmlCommentsTextHelper.Humanize(description); } - private static void SetResponseDescription(OpenApiResponses responses, HttpStatusCode statusCode, string description) + private static void SetResponseDescription(OpenApiResponses? responses, HttpStatusCode statusCode, string description) { + ConsistencyGuard.ThrowIf(responses is null); + OpenApiResponse response = GetOrAddResponse(responses, statusCode); response.Description = XmlCommentsTextHelper.Humanize(description); } - private static void SetResponseHeaderETag(OpenApiResponses responses, HttpStatusCode statusCode) + private static void SetResponseHeaderETag(OpenApiResponses? responses, HttpStatusCode statusCode) { + ConsistencyGuard.ThrowIf(responses is null); + OpenApiResponse response = GetOrAddResponse(responses, statusCode); + response.Headers ??= new SortedDictionary(StringComparer.Ordinal); response.Headers[HeaderNames.ETag] = new OpenApiHeader { @@ -488,14 +497,17 @@ private static void SetResponseHeaderETag(OpenApiResponses responses, HttpStatus Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }; } - private static void SetResponseHeaderContentLength(OpenApiResponses responses, HttpStatusCode statusCode) + private static void SetResponseHeaderContentLength(OpenApiResponses? responses, HttpStatusCode statusCode) { + ConsistencyGuard.ThrowIf(responses is null); + OpenApiResponse response = GetOrAddResponse(responses, statusCode); + response.Headers ??= new SortedDictionary(StringComparer.Ordinal); response.Headers[HeaderNames.ContentLength] = new OpenApiHeader { @@ -503,15 +515,18 @@ private static void SetResponseHeaderContentLength(OpenApiResponses responses, H Required = true, Schema = new OpenApiSchema { - Type = "integer", + Type = JsonSchemaType.Integer, Format = "int64" } }; } - private static void SetResponseHeaderLocation(OpenApiResponses responses, HttpStatusCode statusCode, string resourceName) + private static void SetResponseHeaderLocation(OpenApiResponses? responses, HttpStatusCode statusCode, string resourceName) { + ConsistencyGuard.ThrowIf(responses is null); + OpenApiResponse response = GetOrAddResponse(responses, statusCode); + response.Headers ??= new SortedDictionary(StringComparer.Ordinal); response.Headers[HeaderNames.Location] = new OpenApiHeader { @@ -519,7 +534,7 @@ private static void SetResponseHeaderLocation(OpenApiResponses responses, HttpSt Required = true, Schema = new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, Format = "uri" } }; @@ -529,13 +544,13 @@ private static OpenApiResponse GetOrAddResponse(OpenApiResponses responses, Http { string responseCode = ((int)statusCode).ToString(); - if (!responses.TryGetValue(responseCode, out OpenApiResponse? response)) + if (!responses.TryGetValue(responseCode, out IOpenApiResponse? response) || response is not OpenApiResponse) { response = new OpenApiResponse(); responses.Add(responseCode, response); } - return response; + return (OpenApiResponse)response; } private static void AddQueryStringParameters(OpenApiOperation operation, bool isRelationshipEndpoint) @@ -550,20 +565,21 @@ private static void AddQueryStringParameters(OpenApiOperation operation, bool is // - This makes NSwag produce a C# client with method signature: GetAsync(IDictionary? query) // when combined with true in the project file. + operation.Parameters ??= new List(); + operation.Parameters.Add(new OpenApiParameter { In = ParameterLocation.Query, Name = "query", Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalProperties = new OpenApiSchema { - Type = "string", - Nullable = true + Type = JsonSchemaType.String | JsonSchemaType.Null }, // Prevent SwaggerUI from producing sample, which fails when used because unknown query string parameters are blocked by default. - Example = new OpenApiString(string.Empty) + Example = string.Empty }, Description = isRelationshipEndpoint ? RelationshipQueryStringParameters : ResourceQueryStringParameters }); @@ -571,6 +587,8 @@ private static void AddQueryStringParameters(OpenApiOperation operation, bool is private static void AddRequestHeaderIfNoneMatch(OpenApiOperation operation) { + operation.Parameters ??= new List(); + operation.Parameters.Add(new OpenApiParameter { In = ParameterLocation.Header, @@ -578,7 +596,7 @@ private static void AddRequestHeaderIfNoneMatch(OpenApiOperation operation) Description = "A list of ETags, resulting in HTTP status 304 without a body, if one of them matches the current fingerprint.", Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }); } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/EndpointOrderingFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/EndpointOrderingFilter.cs index 047ba4355a..c1fcb5f582 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/EndpointOrderingFilter.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/EndpointOrderingFilter.cs @@ -1,6 +1,6 @@ using System.Text.RegularExpressions; using JetBrains.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; @@ -13,28 +13,43 @@ public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) ArgumentNullException.ThrowIfNull(swaggerDoc); ArgumentNullException.ThrowIfNull(context); - KeyValuePair[] endpointsInOrder = swaggerDoc.Paths.OrderBy(GetPrimaryResourcePublicName) + KeyValuePair[] endpointsInOrder = swaggerDoc.Paths.OrderBy(GetPrimaryResourcePublicName) .ThenBy(GetRelationshipName).ThenBy(IsSecondaryEndpoint).ToArray(); - swaggerDoc.Paths.Clear(); + swaggerDoc.Paths = new OpenApiPaths(); - foreach ((string url, OpenApiPathItem path) in endpointsInOrder) + foreach ((string url, IOpenApiPathItem path) in endpointsInOrder) { swaggerDoc.Paths.Add(url, path); } } - private static string GetPrimaryResourcePublicName(KeyValuePair entry) + private static string GetPrimaryResourcePublicName(KeyValuePair entry) { - return entry.Value.Operations.First().Value.Tags.First().Name; + if (entry.Value.Operations is { Count: > 0 }) + { + ISet? tagReferences = entry.Value.Operations.First().Value.Tags; + + if (tagReferences is { Count: > 0 }) + { + OpenApiTagReference openApiTagReference = tagReferences.First(); + + if (openApiTagReference.Name != null) + { + return openApiTagReference.Name; + } + } + } + + throw new InvalidOperationException($"Failed to find tag value for endpoint '{entry.Key}'."); } - private static bool IsSecondaryEndpoint(KeyValuePair entry) + private static bool IsSecondaryEndpoint(KeyValuePair entry) { return entry.Key.Contains("/relationships"); } - private static string GetRelationshipName(KeyValuePair entry) + private static string GetRelationshipName(KeyValuePair entry) { Match match = RelationshipNameInUrlRegex().Match(entry.Key); diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs index 31bf7be625..5b0350dba9 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ResourceFieldSchemaBuilder.cs @@ -3,7 +3,7 @@ using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiObjects.ResourceObjects; using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators.Components; using JsonApiDotNetCore.Resources.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; @@ -20,7 +20,7 @@ internal sealed class ResourceFieldSchemaBuilder private readonly SchemaRepository _resourceSchemaRepository = new(); private readonly ResourceDocumentationReader _resourceDocumentationReader = new(); - private readonly IDictionary _schemasForResourceFields; + private readonly IDictionary _schemasForResourceFields; public ResourceFieldSchemaBuilder(SchemaGenerationTracer schemaGenerationTracer, SchemaGenerator defaultSchemaGenerator, DataSchemaGenerator dataSchemaGenerator, LinksVisibilitySchemaGenerator linksVisibilitySchemaGenerator, @@ -46,26 +46,29 @@ public ResourceFieldSchemaBuilder(SchemaGenerationTracer schemaGenerationTracer, _schemasForResourceFields = GetFieldSchemas(); } - private IDictionary GetFieldSchemas() + private IDictionary GetFieldSchemas() { - if (!_resourceSchemaRepository.TryLookupByType(_resourceSchemaType.ResourceType.ClrType, out OpenApiSchema referenceSchemaForResource)) + if (!_resourceSchemaRepository.TryLookupByTypeSafe(_resourceSchemaType.ResourceType.ClrType, out OpenApiSchemaReference? referenceSchemaForResource)) { - referenceSchemaForResource = _defaultSchemaGenerator.GenerateSchema(_resourceSchemaType.ResourceType.ClrType, _resourceSchemaRepository); + referenceSchemaForResource = _defaultSchemaGenerator.GenerateSchema(_resourceSchemaType.ResourceType.ClrType, _resourceSchemaRepository) + .AsReferenceSchema(); } - OpenApiSchema inlineSchemaForResource = _resourceSchemaRepository.Schemas[referenceSchemaForResource.Reference.Id].UnwrapLastExtendedSchema(); - return inlineSchemaForResource.Properties; + OpenApiSchema inlineSchemaForResource = + _resourceSchemaRepository.Schemas[referenceSchemaForResource.GetReferenceId()].UnwrapLastExtendedSchema().AsInlineSchema(); + + return inlineSchemaForResource.Properties ?? new Dictionary(); } - public void SetMembersOfAttributes(OpenApiSchema fullSchemaForAttributes, bool forRequestSchema, SchemaRepository schemaRepository) + public void SetMembersOfAttributes(OpenApiSchema inlineSchemaForAttributes, bool forRequestSchema, SchemaRepository schemaRepository) { - ArgumentNullException.ThrowIfNull(fullSchemaForAttributes); + ArgumentNullException.ThrowIfNull(inlineSchemaForAttributes); ArgumentNullException.ThrowIfNull(schemaRepository); - AssertHasNoProperties(fullSchemaForAttributes); + AssertHasNoProperties(inlineSchemaForAttributes); AttrCapabilities requiredCapability = GetRequiredCapabilityForAttributes(_resourceSchemaType.SchemaOpenType); - foreach ((string publicName, OpenApiSchema schemaForResourceField) in _schemasForResourceFields) + foreach ((string publicName, IOpenApiSchema schemaForResourceField) in _schemasForResourceFields) { AttrAttribute? matchingAttribute = _resourceSchemaType.ResourceType.FindAttributeByPublicName(publicName); @@ -86,22 +89,28 @@ public void SetMembersOfAttributes(OpenApiSchema fullSchemaForAttributes, bool f } } - bool isInlineSchemaType = schemaForResourceField.AllOf.Count == 0; + bool isInlineSchemaType = schemaForResourceField.AllOf == null || schemaForResourceField.AllOf.Count == 0; // Schemas for types like enum and complex attributes are handled as reference schemas. if (!isInlineSchemaType) { - OpenApiSchema referenceSchemaForAttribute = schemaForResourceField.UnwrapLastExtendedSchema(); + OpenApiSchemaReference referenceSchemaForAttribute = schemaForResourceField.UnwrapLastExtendedSchema().AsReferenceSchema(); EnsureAttributeSchemaIsExposed(referenceSchemaForAttribute, matchingAttribute, schemaRepository); } - fullSchemaForAttributes.Properties.Add(matchingAttribute.PublicName, schemaForResourceField); + inlineSchemaForAttributes.Properties ??= new Dictionary(); + inlineSchemaForAttributes.Properties.Add(matchingAttribute.PublicName, schemaForResourceField); - schemaForResourceField.Nullable = _resourceFieldValidationMetadataProvider.IsNullable(matchingAttribute); + if (schemaForResourceField is OpenApiSchema inlineSchemaForResourceField) + { + bool isNullable = _resourceFieldValidationMetadataProvider.IsNullable(matchingAttribute); + inlineSchemaForResourceField.SetNullable(isNullable); + } if (IsFieldRequired(matchingAttribute)) { - fullSchemaForAttributes.Required.Add(matchingAttribute.PublicName); + inlineSchemaForAttributes.Required ??= new SortedSet(StringComparer.Ordinal); + inlineSchemaForAttributes.Required.Add(matchingAttribute.PublicName); } schemaForResourceField.Description = _resourceDocumentationReader.GetDocumentationForAttribute(matchingAttribute); @@ -130,21 +139,21 @@ private static AttrCapabilities GetRequiredCapabilityForAttributes(Type resource return capabilities.Value; } - private void EnsureAttributeSchemaIsExposed(OpenApiSchema referenceSchemaForAttribute, AttrAttribute attribute, SchemaRepository schemaRepository) + private void EnsureAttributeSchemaIsExposed(OpenApiSchemaReference referenceSchemaForAttribute, AttrAttribute attribute, SchemaRepository schemaRepository) { Type nonNullableTypeInPropertyType = GetRepresentedTypeForAttributeSchema(attribute); - if (schemaRepository.TryLookupByType(nonNullableTypeInPropertyType, out _)) + if (schemaRepository.TryLookupByTypeSafe(nonNullableTypeInPropertyType, out _)) { return; } using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, nonNullableTypeInPropertyType); - string schemaId = referenceSchemaForAttribute.Reference.Id; - OpenApiSchema fullSchema = _resourceSchemaRepository.Schemas[schemaId]; + string schemaId = referenceSchemaForAttribute.GetReferenceId(); + OpenApiSchema inlineSchema = _resourceSchemaRepository.Schemas[schemaId].AsInlineSchema(); - schemaRepository.AddDefinition(schemaId, fullSchema); + schemaRepository.AddDefinition(schemaId, inlineSchema); schemaRepository.RegisterType(nonNullableTypeInPropertyType, schemaId); traceScope.TraceSucceeded(schemaId); @@ -170,11 +179,11 @@ private bool IsFieldRequired(ResourceFieldAttribute field) return isCreateResourceSchemaType && _resourceFieldValidationMetadataProvider.IsRequired(field); } - public void SetMembersOfRelationships(OpenApiSchema fullSchemaForRelationships, bool forRequestSchema, SchemaRepository schemaRepository) + public void SetMembersOfRelationships(OpenApiSchema inlineSchemaForRelationships, bool forRequestSchema, SchemaRepository schemaRepository) { - ArgumentNullException.ThrowIfNull(fullSchemaForRelationships); + ArgumentNullException.ThrowIfNull(inlineSchemaForRelationships); ArgumentNullException.ThrowIfNull(schemaRepository); - AssertHasNoProperties(fullSchemaForRelationships); + AssertHasNoProperties(inlineSchemaForRelationships); foreach (string publicName in _schemasForResourceFields.Keys) { @@ -186,27 +195,29 @@ public void SetMembersOfRelationships(OpenApiSchema fullSchemaForRelationships, Type identifierSchemaConstructedType = identifierSchemaOpenType.MakeGenericType(matchingRelationship.RightType.ClrType); _ = _dataSchemaGenerator.GenerateSchema(identifierSchemaConstructedType, forRequestSchema, schemaRepository); - AddRelationshipSchemaToResourceData(matchingRelationship, fullSchemaForRelationships, schemaRepository); + AddRelationshipSchemaToResourceData(matchingRelationship, inlineSchemaForRelationships, schemaRepository); } } } - private void AddRelationshipSchemaToResourceData(RelationshipAttribute relationship, OpenApiSchema fullSchemaForRelationships, + private void AddRelationshipSchemaToResourceData(RelationshipAttribute relationship, OpenApiSchema inlineSchemaForRelationships, SchemaRepository schemaRepository) { Type relationshipSchemaType = GetRelationshipSchemaType(relationship, _resourceSchemaType.SchemaOpenType); - OpenApiSchema referenceSchemaForRelationship = GetReferenceSchemaForRelationship(relationshipSchemaType, schemaRepository) ?? + OpenApiSchemaReference referenceSchemaForRelationship = GetReferenceSchemaForRelationship(relationshipSchemaType, schemaRepository) ?? CreateReferenceSchemaForRelationship(relationshipSchemaType, schemaRepository); OpenApiSchema extendedReferenceSchemaForRelationship = referenceSchemaForRelationship.WrapInExtendedSchema(); extendedReferenceSchemaForRelationship.Description = _resourceDocumentationReader.GetDocumentationForRelationship(relationship); - fullSchemaForRelationships.Properties.Add(relationship.PublicName, extendedReferenceSchemaForRelationship); + inlineSchemaForRelationships.Properties ??= new Dictionary(); + inlineSchemaForRelationships.Properties.Add(relationship.PublicName, extendedReferenceSchemaForRelationship); if (IsFieldRequired(relationship)) { - fullSchemaForRelationships.Required.Add(relationship.PublicName); + inlineSchemaForRelationships.Required ??= new SortedSet(StringComparer.Ordinal); + inlineSchemaForRelationships.Required.Add(relationship.PublicName); } } @@ -216,35 +227,35 @@ private Type GetRelationshipSchemaType(RelationshipAttribute relationship, Type return isResponseSchemaType ? _relationshipTypeFactory.GetForResponse(relationship) : _relationshipTypeFactory.GetForRequest(relationship); } - private OpenApiSchema? GetReferenceSchemaForRelationship(Type relationshipSchemaType, SchemaRepository schemaRepository) + private OpenApiSchemaReference? GetReferenceSchemaForRelationship(Type relationshipSchemaType, SchemaRepository schemaRepository) { - return schemaRepository.TryLookupByType(relationshipSchemaType, out OpenApiSchema? referenceSchema) ? referenceSchema : null; + return schemaRepository.TryLookupByTypeSafe(relationshipSchemaType, out OpenApiSchemaReference? referenceSchema) ? referenceSchema : null; } - private OpenApiSchema CreateReferenceSchemaForRelationship(Type relationshipSchemaType, SchemaRepository schemaRepository) + private OpenApiSchemaReference CreateReferenceSchemaForRelationship(Type relationshipSchemaType, SchemaRepository schemaRepository) { using ISchemaGenerationTraceScope traceScope = _schemaGenerationTracer.TraceStart(this, relationshipSchemaType); - OpenApiSchema referenceSchema = _defaultSchemaGenerator.GenerateSchema(relationshipSchemaType, schemaRepository); - - OpenApiSchema fullSchema = schemaRepository.Schemas[referenceSchema.Reference.Id]; + OpenApiSchemaReference referenceSchema = _defaultSchemaGenerator.GenerateSchema(relationshipSchemaType, schemaRepository).AsReferenceSchema(); + OpenApiSchema inlineSchema = schemaRepository.Schemas[referenceSchema.GetReferenceId()].AsInlineSchema(); if (JsonApiSchemaFacts.HasNullableDataProperty(relationshipSchemaType)) { - fullSchema.Properties[JsonApiPropertyName.Data].Nullable = true; + inlineSchema.Properties ??= new Dictionary(); + inlineSchema.Properties[JsonApiPropertyName.Data].AsInlineSchema().SetNullable(true); } if (JsonApiSchemaFacts.IsRelationshipInResponseType(relationshipSchemaType)) { - _linksVisibilitySchemaGenerator.UpdateSchemaForRelationship(relationshipSchemaType, fullSchema, schemaRepository); + _linksVisibilitySchemaGenerator.UpdateSchemaForRelationship(relationshipSchemaType, inlineSchema, schemaRepository); } - traceScope.TraceSucceeded(referenceSchema.Reference.Id); + traceScope.TraceSucceeded(referenceSchema.GetReferenceId()); return referenceSchema; } - private static void AssertHasNoProperties(OpenApiSchema fullSchema) + private static void AssertHasNoProperties(OpenApiSchema inlineSchema) { - ConsistencyGuard.ThrowIf(fullSchema.Properties.Count > 0); + ConsistencyGuard.ThrowIf(inlineSchema.Properties is { Count: > 0 }); } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ServerDocumentFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ServerDocumentFilter.cs index 723499d39c..2e2fab43a1 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ServerDocumentFilter.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/ServerDocumentFilter.cs @@ -1,6 +1,6 @@ using JetBrains.Annotations; using Microsoft.AspNetCore.Http; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; @@ -19,14 +19,19 @@ public ServerDocumentFilter(IHttpContextAccessor httpContextAccessor) public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { - if (swaggerDoc.Servers.Count == 0 && _httpContextAccessor.HttpContext != null) + if (_httpContextAccessor.HttpContext != null) { - HttpRequest httpRequest = _httpContextAccessor.HttpContext.Request; + swaggerDoc.Servers ??= new List(); - swaggerDoc.Servers.Add(new OpenApiServer + if (swaggerDoc.Servers.Count == 0) { - Url = $"{httpRequest.Scheme}://{httpRequest.Host.Value}" - }); + HttpRequest httpRequest = _httpContextAccessor.HttpContext.Request; + + swaggerDoc.Servers.Add(new OpenApiServer + { + Url = $"{httpRequest.Scheme}://{httpRequest.Host.Value}" + }); + } } } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/StringEnumOrderingFilter.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/StringEnumOrderingFilter.cs index dec10db97b..3dfa5902f3 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/StringEnumOrderingFilter.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/SwaggerComponents/StringEnumOrderingFilter.cs @@ -1,8 +1,7 @@ +using System.Text.Json; +using System.Text.Json.Nodes; using JetBrains.Annotations; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Services; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle.SwaggerComponents; @@ -24,31 +23,32 @@ public void Apply(OpenApiDocument document, DocumentFilterContext context) private sealed class OpenApiEnumVisitor : OpenApiVisitorBase { - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { - if (HasSortAnnotation(schema)) + if (schema is OpenApiSchema { Extensions: not null } inlineSchema && HasSortAnnotation(inlineSchema.Extensions)) { - if (schema.Enum.Count > 1) - { - OrderEnumMembers(schema); - } + OrderEnumMembers(inlineSchema); } - schema.Extensions.Remove(RequiresSortKey); + schema.Extensions?.Remove(RequiresSortKey); } - private static bool HasSortAnnotation(OpenApiSchema schema) + private static bool HasSortAnnotation(IDictionary schemaExtensions) { // Order our own enums, but don't touch enums from user-defined resource attributes. - return schema.Extensions.TryGetValue(RequiresSortKey, out IOpenApiExtension? extension) && extension is OpenApiBoolean { Value: true }; + return schemaExtensions.TryGetValue(RequiresSortKey, out IOpenApiExtension? extension) && + extension is JsonNodeExtension { Node: JsonValue value } && value.GetValueKind() == JsonValueKind.True; } - private static void OrderEnumMembers(OpenApiSchema schema) + private static void OrderEnumMembers(OpenApiSchema inlineSchema) { - List ordered = schema.Enum.OfType().OrderBy(openApiString => openApiString.Value).Cast().ToList(); - ConsistencyGuard.ThrowIf(ordered.Count != schema.Enum.Count); + if (inlineSchema.Enum is { Count: > 1 }) + { + List ordered = inlineSchema.Enum.OrderBy(node => node.ToString()).ToList(); + ConsistencyGuard.ThrowIf(ordered.Count != inlineSchema.Enum.Count); - schema.Enum = ordered; + inlineSchema.Enum = ordered; + } } } } diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/UnusedComponentSchemaCleaner.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/UnusedComponentSchemaCleaner.cs index 4e2addabb3..e59829ef94 100644 --- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/UnusedComponentSchemaCleaner.cs +++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/UnusedComponentSchemaCleaner.cs @@ -1,9 +1,7 @@ using System.Diagnostics; using JetBrains.Annotations; using JsonApiDotNetCore.OpenApi.Swashbuckle.SchemaGenerators; -using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Services; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace JsonApiDotNetCore.OpenApi.Swashbuckle; @@ -21,19 +19,22 @@ public void Apply(OpenApiDocument document, DocumentFilterContext context) ArgumentNullException.ThrowIfNull(document); ArgumentNullException.ThrowIfNull(context); - document.Components.Schemas.Remove(GenerationCacheSchemaGenerator.SchemaId); + if (document.Components?.Schemas != null) + { + document.Components.Schemas.Remove(GenerationCacheSchemaGenerator.SchemaId); - HashSet unusedSchemaIds = GetUnusedSchemaIds(document); - AssertNoUnknownSchemasFound(unusedSchemaIds); + HashSet unusedSchemaIds = GetUnusedSchemaIds(document, document.Components.Schemas); + AssertNoUnknownSchemasFound(unusedSchemaIds); - RemoveUnusedComponentSchemas(document, unusedSchemaIds); + RemoveUnusedComponentSchemas(document.Components.Schemas, unusedSchemaIds); + } } - private static HashSet GetUnusedSchemaIds(OpenApiDocument document) + private static HashSet GetUnusedSchemaIds(OpenApiDocument document, IDictionary componentSchemas) { HashSet reachableSchemaIds = ReachableRootsCollector.Instance.CollectReachableSchemaIds(document); - ComponentSchemaUsageCollector collector = new(document); + ComponentSchemaUsageCollector collector = new(componentSchemas); return collector.CollectUnusedSchemaIds(reachableSchemaIds); } @@ -46,11 +47,11 @@ private static void AssertNoUnknownSchemasFound(HashSet unusedSchemaIds) } } - private static void RemoveUnusedComponentSchemas(OpenApiDocument document, HashSet unusedSchemaIds) + private static void RemoveUnusedComponentSchemas(IDictionary componentSchemas, HashSet unusedSchemaIds) { foreach (string schemaId in unusedSchemaIds) { - document.Components.Schemas.Remove(schemaId); + componentSchemas.Remove(schemaId); } } @@ -78,13 +79,13 @@ private sealed class ComponentSchemaReferenceVisitor : OpenApiVisitorBase { public HashSet ReachableSchemaIds { get; } = []; - public override void Visit(IOpenApiReferenceable referenceable) + public override void Visit(IOpenApiReferenceHolder referenceHolder) { if (!PathString.StartsWith(ComponentSchemaPrefix, StringComparison.Ordinal)) { - if (referenceable is OpenApiSchema schema) + if (referenceHolder is OpenApiSchemaReference { Reference.Id: not null } referenceSchema) { - ReachableSchemaIds.Add(schema.Reference.Id); + ReachableSchemaIds.Add(referenceSchema.Reference.Id); } } } @@ -93,14 +94,14 @@ public override void Visit(IOpenApiReferenceable referenceable) private sealed class ComponentSchemaUsageCollector { - private readonly IDictionary _componentSchemas; + private readonly IDictionary _componentSchemas; private readonly HashSet _schemaIdsInUse = []; - public ComponentSchemaUsageCollector(OpenApiDocument document) + public ComponentSchemaUsageCollector(IDictionary componentSchemas) { - ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(componentSchemas); - _componentSchemas = document.Components.Schemas; + _componentSchemas = componentSchemas; } public HashSet CollectUnusedSchemaIds(ICollection reachableSchemaIds) @@ -117,18 +118,18 @@ public HashSet CollectUnusedSchemaIds(ICollection reachableSchem return unusedSchemaIds; } - private void WalkSchemaId(string schemaId) + private void WalkSchemaId(string? schemaId) { - if (_schemaIdsInUse.Add(schemaId)) + if (schemaId != null && _schemaIdsInUse.Add(schemaId)) { - if (_componentSchemas.TryGetValue(schemaId, out OpenApiSchema? schema)) + if (_componentSchemas.TryGetValue(schemaId, out IOpenApiSchema? schema)) { WalkSchema(schema); } } } - private void WalkSchema(OpenApiSchema? schema) + private void WalkSchema(IOpenApiSchema? schema) { if (schema != null) { @@ -137,22 +138,22 @@ private void WalkSchema(OpenApiSchema? schema) WalkSchema(schema.Items); WalkSchema(schema.Not); - foreach (OpenApiSchema? subSchema in schema.AllOf) + foreach (IOpenApiSchema subSchema in schema.AllOf ?? Array.Empty()) { WalkSchema(subSchema); } - foreach (OpenApiSchema? subSchema in schema.AnyOf) + foreach (IOpenApiSchema subSchema in schema.AnyOf ?? Array.Empty()) { WalkSchema(subSchema); } - foreach (OpenApiSchema? subSchema in schema.OneOf) + foreach (IOpenApiSchema subSchema in schema.OneOf ?? Array.Empty()) { WalkSchema(subSchema); } - foreach (OpenApiSchema? subSchema in schema.Properties.Values) + foreach (IOpenApiSchema subSchema in schema.Properties?.Values ?? Array.Empty()) { WalkSchema(subSchema); } @@ -162,22 +163,18 @@ private void WalkSchema(OpenApiSchema? schema) } } - private void VisitSchema(OpenApiSchema schema) + private void VisitSchema(IOpenApiSchema schema) { - if (schema.Reference is { Type: ReferenceType.Schema, IsExternal: false }) + if (schema is OpenApiSchemaReference { Reference: { Type: ReferenceType.Schema, IsExternal: false } } referenceSchema) { - WalkSchemaId(schema.Reference.Id); + WalkSchemaId(referenceSchema.Reference.Id); } - if (schema.Discriminator != null) + if (schema.Discriminator is { Mapping: not null }) { - foreach (string mappingValue in schema.Discriminator.Mapping.Values) + foreach (OpenApiSchemaReference mappingValueReferenceSchema in schema.Discriminator.Mapping.Values) { - if (mappingValue.StartsWith(ComponentSchemaPrefix, StringComparison.Ordinal)) - { - string schemaId = mappingValue[ComponentSchemaPrefix.Length..]; - WalkSchemaId(schemaId); - } + WalkSchemaId(mappingValueReferenceSchema.Reference.Id); } } } diff --git a/test/OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json index 613c50890c..b98e7ec750 100644 --- a/test/OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json @@ -3678,5 +3678,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "operations" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/AttributeTypes/AttributeTypesStartup.cs b/test/OpenApiTests/AttributeTypes/AttributeTypesStartup.cs index c71515104e..dcb6fda17c 100644 --- a/test/OpenApiTests/AttributeTypes/AttributeTypesStartup.cs +++ b/test/OpenApiTests/AttributeTypes/AttributeTypesStartup.cs @@ -6,7 +6,7 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Queries.Parsing; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace OpenApiTests.AttributeTypes; @@ -41,52 +41,52 @@ protected override void ConfigureSwaggerGenOptions(SwaggerGenOptions options) options.MapType(() => new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }); options.MapType(() => new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }); options.MapType(() => new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }); options.MapType(() => new OpenApiSchema { - Type = "number", + Type = JsonSchemaType.Number, Format = "float" }); options.MapType(() => new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }); options.MapType(() => new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, MaxLength = 4 }); options.MapType(() => new OpenApiSchema { // Beware that "duration" does not round-trip universally. NSwag and Kiota are incompatible. - Type = "string", + Type = JsonSchemaType.String, Format = "duration" }); options.MapType(() => new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, Format = "ipv4" }); options.MapType(() => new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }); } diff --git a/test/OpenApiTests/AttributeTypes/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/AttributeTypes/GeneratedSwagger/swagger.g.json index 370668bcd6..09240ea079 100644 --- a/test/OpenApiTests/AttributeTypes/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/AttributeTypes/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1991,5 +1991,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "typeContainers" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json index 0a32442e86..b230d33a26 100644 --- a/test/OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json @@ -1629,5 +1629,16 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "games" + }, + { + "name": "playerGroups" + }, + { + "name": "players" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/Documentation/DocumentationStartup.cs b/test/OpenApiTests/Documentation/DocumentationStartup.cs index 2e6aaa78cd..f38796f936 100644 --- a/test/OpenApiTests/Documentation/DocumentationStartup.cs +++ b/test/OpenApiTests/Documentation/DocumentationStartup.cs @@ -1,7 +1,7 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; using TestBuildingBlocks; diff --git a/test/OpenApiTests/Headers/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/Headers/GeneratedSwagger/swagger.g.json index 735ed22d80..c7eef9d8cf 100644 --- a/test/OpenApiTests/Headers/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/Headers/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -721,13 +721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -735,6 +728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -899,13 +899,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -913,6 +906,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2245,5 +2245,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "countries" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/IdObfuscation/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/IdObfuscation/GeneratedSwagger/swagger.g.json index d582e1d8f8..f4b3cc82c6 100644 --- a/test/OpenApiTests/IdObfuscation/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/IdObfuscation/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -401,13 +401,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -415,6 +408,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -709,13 +709,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -723,6 +716,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -883,13 +883,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -897,6 +890,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1263,13 +1263,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1277,6 +1270,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1546,13 +1546,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1560,6 +1553,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1854,13 +1854,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1868,6 +1861,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2028,13 +2028,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2042,6 +2035,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4316,5 +4316,16 @@ "type": "string" } } - } + }, + "tags": [ + { + "name": "bankAccounts" + }, + { + "name": "debitCards" + }, + { + "name": "operations" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/LegacyOpenApi/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/LegacyOpenApi/GeneratedSwagger/swagger.g.json index f72814347b..1891fd84de 100644 --- a/test/OpenApiTests/LegacyOpenApi/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/LegacyOpenApi/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -401,13 +401,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -415,6 +408,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -709,13 +709,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -723,6 +716,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -883,13 +883,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -897,6 +890,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1263,13 +1263,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1277,6 +1270,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1546,13 +1546,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1560,6 +1553,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1854,13 +1854,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1868,6 +1861,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2028,13 +2028,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2042,6 +2035,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2436,13 +2436,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2450,6 +2443,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2610,13 +2610,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2624,6 +2617,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2990,13 +2990,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3004,6 +2997,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3273,13 +3273,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3287,6 +3280,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3581,13 +3581,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3595,6 +3588,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3755,13 +3755,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3769,6 +3762,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4007,13 +4007,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4021,6 +4014,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4181,13 +4181,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4195,6 +4188,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4589,13 +4589,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4603,6 +4596,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4763,13 +4763,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4777,6 +4770,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5171,13 +5171,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5185,6 +5178,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5345,13 +5345,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5359,6 +5352,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5569,13 +5569,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5583,6 +5576,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5852,13 +5852,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5866,6 +5859,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -8854,5 +8854,19 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "airplanes" + }, + { + "name": "flight-attendants" + }, + { + "name": "flights" + }, + { + "name": "passengers" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/LegacyOpenApi/expected-swagger.json b/test/OpenApiTests/LegacyOpenApi/expected-swagger.json index f72814347b..1891fd84de 100644 --- a/test/OpenApiTests/LegacyOpenApi/expected-swagger.json +++ b/test/OpenApiTests/LegacyOpenApi/expected-swagger.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -401,13 +401,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -415,6 +408,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -709,13 +709,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -723,6 +716,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -883,13 +883,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -897,6 +890,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1263,13 +1263,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1277,6 +1270,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1546,13 +1546,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1560,6 +1553,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1854,13 +1854,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1868,6 +1861,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2028,13 +2028,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2042,6 +2035,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2436,13 +2436,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2450,6 +2443,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2610,13 +2610,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2624,6 +2617,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2990,13 +2990,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3004,6 +2997,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3273,13 +3273,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3287,6 +3280,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3581,13 +3581,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3595,6 +3588,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3755,13 +3755,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3769,6 +3762,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4007,13 +4007,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4021,6 +4014,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4181,13 +4181,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4195,6 +4188,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4589,13 +4589,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4603,6 +4596,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4763,13 +4763,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4777,6 +4770,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5171,13 +5171,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5185,6 +5178,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5345,13 +5345,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5359,6 +5352,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5569,13 +5569,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5583,6 +5576,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5852,13 +5852,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5866,6 +5859,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -8854,5 +8854,19 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "airplanes" + }, + { + "name": "flight-attendants" + }, + { + "name": "flights" + }, + { + "name": "passengers" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json index b72c15aecb..2814116d8a 100644 --- a/test/OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -689,13 +689,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -703,6 +696,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -976,13 +976,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -990,6 +983,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1260,13 +1260,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1274,6 +1267,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1547,13 +1547,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1561,6 +1554,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1831,13 +1831,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1845,6 +1838,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2118,13 +2118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2132,6 +2125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2434,13 +2434,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2448,6 +2441,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2612,13 +2612,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2626,6 +2619,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2870,13 +2870,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2884,6 +2877,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3048,13 +3048,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3062,6 +3055,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3466,13 +3466,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3480,6 +3473,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3644,13 +3644,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3658,6 +3651,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -6009,5 +6009,19 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "accommodations" + }, + { + "name": "excursions" + }, + { + "name": "transports" + }, + { + "name": "vacations" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/MixedControllers/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/MixedControllers/GeneratedSwagger/swagger.g.json index a7a9229cd5..e5bf0b32a7 100644 --- a/test/OpenApiTests/MixedControllers/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/MixedControllers/GeneratedSwagger/swagger.g.json @@ -352,13 +352,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -366,6 +359,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1358,5 +1358,19 @@ "type": "string" } } - } + }, + "tags": [ + { + "name": "coffeeSummaries" + }, + { + "name": "cupOfCoffees" + }, + { + "name": "emails" + }, + { + "name": "fileTransfers" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json index 05a83c87ee..b5b955524a 100644 --- a/test/OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json @@ -1060,5 +1060,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "socialMediaAccounts" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/NamingConventions/CamelCase/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/NamingConventions/CamelCase/GeneratedSwagger/swagger.g.json index 8454946d0c..396c94ccee 100644 --- a/test/OpenApiTests/NamingConventions/CamelCase/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/NamingConventions/CamelCase/GeneratedSwagger/swagger.g.json @@ -207,13 +207,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -221,6 +214,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -494,13 +494,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -508,6 +501,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -778,13 +778,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -792,6 +785,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1065,13 +1065,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1079,6 +1072,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1381,13 +1381,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1395,6 +1388,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1559,13 +1559,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1573,6 +1566,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1817,13 +1817,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1831,6 +1824,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1995,13 +1995,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2009,6 +2002,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2413,13 +2413,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2427,6 +2420,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2591,13 +2591,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2605,6 +2598,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5075,5 +5075,16 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "operations" + }, + { + "name": "staffMembers" + }, + { + "name": "supermarkets" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/NamingConventions/KebabCase/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/NamingConventions/KebabCase/GeneratedSwagger/swagger.g.json index c48444fbea..865e3ba235 100644 --- a/test/OpenApiTests/NamingConventions/KebabCase/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/NamingConventions/KebabCase/GeneratedSwagger/swagger.g.json @@ -207,13 +207,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -221,6 +214,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -494,13 +494,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -508,6 +501,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -778,13 +778,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -792,6 +785,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1065,13 +1065,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1079,6 +1072,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1381,13 +1381,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1395,6 +1388,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1559,13 +1559,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1573,6 +1566,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1817,13 +1817,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1831,6 +1824,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1995,13 +1995,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2009,6 +2002,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2413,13 +2413,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2427,6 +2420,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2591,13 +2591,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2605,6 +2598,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5075,5 +5075,16 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "operations" + }, + { + "name": "staff-members" + }, + { + "name": "supermarkets" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/NamingConventions/PascalCase/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/NamingConventions/PascalCase/GeneratedSwagger/swagger.g.json index bb924ef157..8fd99be448 100644 --- a/test/OpenApiTests/NamingConventions/PascalCase/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/NamingConventions/PascalCase/GeneratedSwagger/swagger.g.json @@ -207,13 +207,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -221,6 +214,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -494,13 +494,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -508,6 +501,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -778,13 +778,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -792,6 +785,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1065,13 +1065,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1079,6 +1072,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1381,13 +1381,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1395,6 +1388,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1559,13 +1559,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1573,6 +1566,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1817,13 +1817,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1831,6 +1824,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1995,13 +1995,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2009,6 +2002,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2413,13 +2413,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2427,6 +2420,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2591,13 +2591,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2605,6 +2598,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5075,5 +5075,16 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "operations" + }, + { + "name": "StaffMembers" + }, + { + "name": "Supermarkets" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json index 4b5473246c..8c619392b3 100644 --- a/test/OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -721,13 +721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -735,6 +728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -899,13 +899,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -913,6 +906,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1125,13 +1125,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1139,6 +1132,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1412,13 +1412,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1426,6 +1419,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1728,13 +1728,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1742,6 +1735,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1906,13 +1906,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1920,6 +1913,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2324,13 +2324,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2338,6 +2331,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2502,13 +2502,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2516,6 +2509,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2760,13 +2760,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2774,6 +2767,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2938,13 +2938,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2952,6 +2945,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4993,5 +4993,13 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "nameValuePairs" + }, + { + "name": "nodes" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedSwagger/swagger.g.json index 541a5901ba..f3bba9df82 100644 --- a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOff/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -721,13 +721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -735,6 +728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -899,13 +899,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -913,6 +906,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1317,13 +1317,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1331,6 +1324,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1495,13 +1495,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1509,6 +1502,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1753,13 +1753,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1767,6 +1760,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1931,13 +1931,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1945,6 +1938,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2349,13 +2349,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2363,6 +2356,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2527,13 +2527,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2541,6 +2534,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3951,5 +3951,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "resources" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedSwagger/swagger.g.json index cb83b19b17..30b371eb06 100644 --- a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOff/ModelStateValidationOn/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -721,13 +721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -735,6 +728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -899,13 +899,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -913,6 +906,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1317,13 +1317,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1331,6 +1324,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1495,13 +1495,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1509,6 +1502,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1753,13 +1753,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1767,6 +1760,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1931,13 +1931,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1945,6 +1938,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2349,13 +2349,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2363,6 +2356,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2527,13 +2527,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2541,6 +2534,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4061,5 +4061,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "resources" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedSwagger/swagger.g.json index 1b962dc499..37db4b7d2f 100644 --- a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOff/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -721,13 +721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -735,6 +728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -899,13 +899,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -913,6 +906,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1157,13 +1157,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1171,6 +1164,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1335,13 +1335,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1349,6 +1342,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1593,13 +1593,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1607,6 +1600,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1771,13 +1771,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1785,6 +1778,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2029,13 +2029,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2043,6 +2036,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2207,13 +2207,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2221,6 +2214,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2465,13 +2465,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2479,6 +2472,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2643,13 +2643,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2657,6 +2650,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3061,13 +3061,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3075,6 +3068,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3239,13 +3239,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3253,6 +3246,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5006,5 +5006,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "resources" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedSwagger/swagger.g.json index 0717249aa5..1a88111b71 100644 --- a/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceFieldValidation/NullableReferenceTypesOn/ModelStateValidationOn/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -721,13 +721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -735,6 +728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -899,13 +899,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -913,6 +906,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1157,13 +1157,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1171,6 +1164,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1335,13 +1335,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1349,6 +1342,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1593,13 +1593,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1607,6 +1600,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1771,13 +1771,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1785,6 +1778,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2029,13 +2029,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2043,6 +2036,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2207,13 +2207,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2221,6 +2214,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2465,13 +2465,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2479,6 +2472,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2643,13 +2643,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2657,6 +2650,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3061,13 +3061,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3075,6 +3068,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3239,13 +3239,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3253,6 +3246,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5000,5 +5000,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "resources" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json index 9dad8a07cb..18fa97e43b 100644 --- a/test/OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -405,13 +405,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -419,6 +412,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -721,13 +721,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -735,6 +728,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -899,13 +899,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -913,6 +906,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1125,13 +1125,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1139,6 +1132,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1412,13 +1412,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1426,6 +1419,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1728,13 +1728,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1742,6 +1735,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1906,13 +1906,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1920,6 +1913,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2132,13 +2132,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2146,6 +2139,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2419,13 +2419,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2433,6 +2426,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2703,13 +2703,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2717,6 +2710,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2990,13 +2990,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3004,6 +2997,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3274,13 +3274,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3288,6 +3281,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3561,13 +3561,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3575,6 +3568,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3877,13 +3877,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3891,6 +3884,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4055,13 +4055,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4069,6 +4062,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4473,13 +4473,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4487,6 +4480,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4651,13 +4651,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4665,6 +4658,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5037,13 +5037,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5051,6 +5044,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5324,13 +5324,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5338,6 +5331,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5640,13 +5640,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5654,6 +5647,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5818,13 +5818,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -5832,6 +5825,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -6204,13 +6204,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -6218,6 +6211,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -6491,13 +6491,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -6505,6 +6498,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -6807,13 +6807,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -6821,6 +6814,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -6985,13 +6985,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -6999,6 +6992,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -7211,13 +7211,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -7225,6 +7218,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -7498,13 +7498,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -7512,6 +7505,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -7814,13 +7814,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -7828,6 +7821,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -7992,13 +7992,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -8006,6 +7999,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -8218,13 +8218,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -8232,6 +8225,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -8505,13 +8505,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -8519,6 +8512,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -8821,13 +8821,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -8835,6 +8828,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -8999,13 +8999,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -9013,6 +9006,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -9417,13 +9417,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -9431,6 +9424,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -9595,13 +9595,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -9609,6 +9602,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -10070,13 +10070,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -10084,6 +10077,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -10357,13 +10357,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -10371,6 +10364,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -10673,13 +10673,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -10687,6 +10680,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -10851,13 +10851,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -10865,6 +10858,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -11237,13 +11237,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -11251,6 +11244,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -11524,13 +11524,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -11538,6 +11531,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -11808,13 +11808,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -11822,6 +11815,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -12095,13 +12095,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -12109,6 +12102,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -12411,13 +12411,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -12425,6 +12418,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -12589,13 +12589,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -12603,6 +12596,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -12815,13 +12815,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -12829,6 +12822,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -13102,13 +13102,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -13116,6 +13109,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -13386,13 +13386,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -13400,6 +13393,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -13673,13 +13673,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -13687,6 +13680,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -13989,13 +13989,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -14003,6 +13996,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -14167,13 +14167,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -14181,6 +14174,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -20009,5 +20009,52 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "bathrooms" + }, + { + "name": "bedrooms" + }, + { + "name": "buildings" + }, + { + "name": "cyclePaths" + }, + { + "name": "districts" + }, + { + "name": "familyHomes" + }, + { + "name": "kitchens" + }, + { + "name": "livingRooms" + }, + { + "name": "mansions" + }, + { + "name": "operations" + }, + { + "name": "residences" + }, + { + "name": "roads" + }, + { + "name": "rooms" + }, + { + "name": "staffMembers" + }, + { + "name": "toilets" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json index 4f80315108..508e052ce8 100644 --- a/test/OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json @@ -150,13 +150,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -164,6 +157,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -408,13 +408,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -422,6 +415,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -666,13 +666,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -680,6 +673,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1084,13 +1084,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1098,6 +1091,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1502,13 +1502,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1516,6 +1509,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1920,13 +1920,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1934,6 +1927,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2178,13 +2178,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2192,6 +2185,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2436,13 +2436,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2450,6 +2443,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2854,13 +2854,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2868,6 +2861,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3361,13 +3361,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3375,6 +3368,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3779,13 +3779,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3793,6 +3786,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -4037,13 +4037,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -4051,6 +4044,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -6190,5 +6190,40 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "bathrooms" + }, + { + "name": "bedrooms" + }, + { + "name": "districts" + }, + { + "name": "familyHomes" + }, + { + "name": "kitchens" + }, + { + "name": "livingRooms" + }, + { + "name": "mansions" + }, + { + "name": "operations" + }, + { + "name": "residences" + }, + { + "name": "rooms" + }, + { + "name": "toilets" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json index 48e39eb3ac..e1b1b75353 100644 --- a/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json @@ -3254,5 +3254,10 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "operations" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json index 42301a5d4d..ed0c8faa55 100644 --- a/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json @@ -369,13 +369,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -383,6 +376,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -515,13 +515,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -529,6 +522,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -690,13 +690,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -704,6 +697,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3365,5 +3365,19 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "buildings" + }, + { + "name": "cyclePaths" + }, + { + "name": "districts" + }, + { + "name": "familyHomes" + } + ] } \ No newline at end of file diff --git a/test/OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json b/test/OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json index 51cc607974..70f5bf303e 100644 --- a/test/OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json +++ b/test/OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json @@ -118,13 +118,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -132,6 +125,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -293,13 +293,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -307,6 +300,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -439,13 +439,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -453,6 +446,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -614,13 +614,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -628,6 +621,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -792,13 +792,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -806,6 +799,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -970,13 +970,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -984,6 +977,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1148,13 +1148,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1162,6 +1155,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1326,13 +1326,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1340,6 +1333,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1504,13 +1504,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1518,6 +1511,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1682,13 +1682,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1696,6 +1689,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -1828,13 +1828,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -1842,6 +1835,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2003,13 +2003,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2017,6 +2010,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2181,13 +2181,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2195,6 +2188,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2359,13 +2359,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2373,6 +2366,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2537,13 +2537,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2551,6 +2544,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -2715,13 +2715,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -2729,6 +2722,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3133,13 +3133,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3147,6 +3140,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -3391,13 +3391,6 @@ "200": { "description": "The operation completed successfully.", "headers": { - "ETag": { - "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", - "required": true, - "schema": { - "type": "string" - } - }, "Content-Length": { "description": "Size of the HTTP response body, in bytes.", "required": true, @@ -3405,6 +3398,13 @@ "type": "integer", "format": "int64" } + }, + "ETag": { + "description": "A fingerprint of the HTTP response, which can be used in an If-None-Match header to only fetch changes.", + "required": true, + "schema": { + "type": "string" + } } } }, @@ -5910,5 +5910,22 @@ "additionalProperties": false } } - } + }, + "tags": [ + { + "name": "dataStreams" + }, + { + "name": "readOnlyChannels" + }, + { + "name": "readOnlyResourceChannels" + }, + { + "name": "relationshipChannels" + }, + { + "name": "writeOnlyChannels" + } + ] } \ No newline at end of file From f2dddb1a02b290e0ac63b1826521eb6c66d3269e Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 19 Nov 2025 01:12:42 +0100 Subject: [PATCH 14/26] Switch NuGetAuditMode to all, which is the new default in the .NET 10 SDK --- Directory.Build.props | 1 - src/JsonApiDotNetCore/JsonApiDotNetCore.csproj | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 11975ee095..46088e01b0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,7 +12,6 @@ 5.9.2 pre 7 - direct diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj index 009c7d8656..bcc77754b2 100644 --- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj +++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj @@ -40,6 +40,12 @@ + + + From a4851faf048fedf1555c6618c2e9783238695550 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 19 Nov 2025 03:10:35 +0100 Subject: [PATCH 15/26] Adapt to breaking change in dotnet run --- docs/generate-examples.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generate-examples.ps1 b/docs/generate-examples.ps1 index ea6b2bd8f2..2555928dc7 100644 --- a/docs/generate-examples.ps1 +++ b/docs/generate-examples.ps1 @@ -34,7 +34,7 @@ function Start-WebServer { Write-Output "Starting web server" $startTimeUtc = Get-Date -AsUTC $job = Start-Job -ScriptBlock { - dotnet run --project ..\src\Examples\GettingStarted\GettingStarted.csproj --framework net8.0 --configuration Debug --property:TreatWarningsAsErrors=True --urls=http://0.0.0.0:14141 + dotnet run --project ../src/Examples/GettingStarted/GettingStarted.csproj --framework net8.0 --configuration Debug --property:TreatWarningsAsErrors=True --urls=http://0.0.0.0:14141 } $webProcessId = $null From dd57c66cca40d67464014f0effd69a0729efd7ff Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 21 Nov 2025 03:25:14 +0100 Subject: [PATCH 16/26] Update and simplify version table --- README.md | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index d9719db341..b15b2dc5cc 100644 --- a/README.md +++ b/README.md @@ -219,23 +219,17 @@ The following links explain what this project provides, why it exists, and how y The following chart should help you pick the best version, based on your environment. See also our [versioning policy](./VERSIONING_POLICY.md). -| JsonApiDotNetCore | Status | .NET | Entity Framework Core | -| ----------------- | ------------ | -------- | --------------------- | -| master | Preview | 9 | 9 | -| | | 8 | 8, 9 | -| 5.7.0+ | Stable | 9 | 9 | -| | | 8 | 8, 9 | -| 5.5.0-5.6.0 | Stable | 9 | 9 | -| | | 8 | 8, 9 | -| | | 7 | 7 | -| | | 6 | 6, 7 | -| 5.0.3-5.4.0 | Stable | 7 | 7 | -| | | 6 | 6, 7 | -| 5.0.0-5.0.2 | Stable | 6 | 6 | -| 4.x | Stable | 6 | 5 | -| | | 5 | 5 | -| | | Core 3.1 | 3.1, 5 | -| 3.x | Stable | Core 2.x | 2.x | +| .NET | Entity Framework Core | JsonApiDotNetCore | Status | +| -------- | --------------------- | ----------------- | -------------- | +| 10 | 10 | master | Preview | +| 9 | 9 | 5.5.0+ | Stable | +| 8 | 8, 9 | 5.5.0+ | Stable | +| 7 | 7 | 5.0.3 - 5.6.0 | Out of support | +| 6 | 7 | 5.0.3 - 5.6.0 | Out of support | +| 6 | 6 | 5.0.0 - 5.6.0 | Out of support | +| 5 | 5 | 4.x | Out of support | +| Core 3.1 | 3.1, 5 | 4.x | Out of support | +| Core 2.x | 2.x | 3.x | Out of support | ## Trying out the latest build From d9008c77d976bee41d4bb7fd629bf8e7c0a988ab Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 19 Nov 2025 02:41:55 +0100 Subject: [PATCH 17/26] Perf: turn off the ASP.NET OpenAPI source generator globally --- Directory.Build.targets | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Directory.Build.targets diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000000..302a82133d --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,7 @@ + + + + + + + From e1c1362f527c6362e3296a33d1c44279d47fe0d1 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 21 Nov 2025 03:54:52 +0100 Subject: [PATCH 18/26] Add workaround for extremely slow builds on .NET 10 --- Directory.Build.targets | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 302a82133d..61e668c6b9 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,18 @@ - + + + + + + + + + + + + From 90b5784eee206753260bd5e16418473df949e0d2 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 21 Nov 2025 04:36:42 +0100 Subject: [PATCH 19/26] Generate examples in docs against .NET 10 --- docs/generate-examples.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generate-examples.ps1 b/docs/generate-examples.ps1 index 2555928dc7..dced9ce131 100644 --- a/docs/generate-examples.ps1 +++ b/docs/generate-examples.ps1 @@ -34,7 +34,7 @@ function Start-WebServer { Write-Output "Starting web server" $startTimeUtc = Get-Date -AsUTC $job = Start-Job -ScriptBlock { - dotnet run --project ../src/Examples/GettingStarted/GettingStarted.csproj --framework net8.0 --configuration Debug --property:TreatWarningsAsErrors=True --urls=http://0.0.0.0:14141 + dotnet run --project ../src/Examples/GettingStarted/GettingStarted.csproj --framework net10.0 --configuration Debug --property:TreatWarningsAsErrors=True --urls=http://0.0.0.0:14141 } $webProcessId = $null From 1f810b8f0f243618a906b07bec2e05a986eaabbf Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 21 Nov 2025 04:53:23 +0100 Subject: [PATCH 20/26] Convert to slnx --- .github/workflows/build.yml | 7 +- JsonApiDotNetCore.sln | 479 ------------------ JsonApiDotNetCore.slnx | 54 ++ ...ings => JsonApiDotNetCore.slnx.DotSettings | 2 +- cleanupcode.ps1 | 8 +- inspectcode.ps1 | 20 +- 6 files changed, 75 insertions(+), 495 deletions(-) delete mode 100644 JsonApiDotNetCore.sln create mode 100644 JsonApiDotNetCore.slnx rename JsonApiDotNetCore.sln.DotSettings => JsonApiDotNetCore.slnx.DotSettings (99%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3e9f8edd9c..906a775636 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,7 @@ concurrency: env: DOTNET_NOLOGO: true DOTNET_CLI_TELEMETRY_OPTOUT: true + SOLUTION_FILE: JsonApiDotNetCore.slnx jobs: build-and-test: @@ -171,7 +172,7 @@ jobs: $inspectCodeOutputPath = Join-Path $env:RUNNER_TEMP 'jetbrains-inspectcode-results.xml' Write-Output "INSPECT_CODE_OUTPUT_PATH=$inspectCodeOutputPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append dotnet jb inspectcode --version - dotnet jb inspectcode JsonApiDotNetCore.sln --build --dotnetcoresdk=$(dotnet --version) --output="$inspectCodeOutputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal + dotnet jb inspectcode $env:SOLUTION_FILE --build --dotnetcoresdk=$(dotnet --version) --output="$inspectCodeOutputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal - name: Upload output to artifacts uses: actions/upload-artifact@v4 with: @@ -241,14 +242,14 @@ jobs: Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request." dotnet jb cleanupcode --version - dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff + dotnet regitlint -s $env:SOLUTION_FILE --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff - name: CleanupCode (on branch) if: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'workflow_dispatch' }} shell: pwsh run: | Write-Output 'Running code cleanup on all files.' dotnet jb cleanupcode --version - dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff + dotnet regitlint -s $env:SOLUTION_FILE --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff publish: timeout-minutes: 60 diff --git a/JsonApiDotNetCore.sln b/JsonApiDotNetCore.sln deleted file mode 100644 index 793c01950d..0000000000 --- a/JsonApiDotNetCore.sln +++ /dev/null @@ -1,479 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31919.166 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5B4D998-CECB-454D-9F32-085A897577BE}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .gitignore = .gitignore - .github\workflows\build.yml = .github\workflows\build.yml - CodingGuidelines.ruleset = CodingGuidelines.ruleset - CSharpGuidelinesAnalyzer.config = CSharpGuidelinesAnalyzer.config - Directory.Build.props = Directory.Build.props - package-versions.props = package-versions.props - tests.runsettings = tests.runsettings - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{026FBC6C-AF76-4568-9B87-EC73457899FD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{076E1AE4-FD25-4684-B826-CAAE37FEA0AA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GettingStarted", "src\Examples\GettingStarted\GettingStarted.csproj", "{067FFD7A-C66B-473D-8471-37F5C95DF61C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCoreTests", "test\JsonApiDotNetCoreTests\JsonApiDotNetCoreTests.csproj", "{CAF331F8-9255-4D72-A1A8-A54141E99F1E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NoEntityFrameworkTests", "test\NoEntityFrameworkTests\NoEntityFrameworkTests.csproj", "{4F15A8F8-5BC6-45A1-BC51-03F921B726A4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "test\UnitTests\UnitTests.csproj", "{8788FF65-C2B6-40B2-A3A0-1E3D91C02664}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscoveryTests", "test\DiscoveryTests\DiscoveryTests.csproj", "{03032A2F-664D-4DD8-A82F-AD8A482EDD85}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "benchmarks\Benchmarks.csproj", "{DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCoreExample", "src\Examples\JsonApiDotNetCoreExample\JsonApiDotNetCoreExample.csproj", "{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NoEntityFrameworkExample", "src\Examples\NoEntityFrameworkExample\NoEntityFrameworkExample.csproj", "{789085E1-048F-4996-B600-791B9CA3A663}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReportsExample", "src\Examples\ReportsExample\ReportsExample.csproj", "{8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\JsonApiDotNetCore\JsonApiDotNetCore.csproj", "{21D27239-138D-4604-8E49-DCBE41BCE4C8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiDbContextExample", "src\Examples\MultiDbContextExample\MultiDbContextExample.csproj", "{6CAFDDBE-00AB-4784-801B-AB419C3C3A26}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiDbContextTests", "test\MultiDbContextTests\MultiDbContextTests.csproj", "{EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestBuildingBlocks", "test\TestBuildingBlocks\TestBuildingBlocks.csproj", "{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.SourceGenerators", "src\JsonApiDotNetCore.SourceGenerators\JsonApiDotNetCore.SourceGenerators.csproj", "{952C0FDE-AFC8-455C-986F-6CC882ED8953}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGeneratorTests", "test\SourceGeneratorTests\SourceGeneratorTests.csproj", "{0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.Annotations", "src\JsonApiDotNetCore.Annotations\JsonApiDotNetCore.Annotations.csproj", "{83FF097C-C8C6-477B-9FAB-DF99B84978B5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabasePerTenantExample", "src\Examples\DatabasePerTenantExample\DatabasePerTenantExample.csproj", "{60334658-BE51-43B3-9C4D-F2BBF56C89CE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnnotationTests", "test\AnnotationTests\AnnotationTests.csproj", "{24B0C12F-38CD-4245-8785-87BEFAD55B00}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DapperExample", "src\Examples\DapperExample\DapperExample.csproj", "{C1774117-5073-4DF8-B5BE-BF7B538BD1C2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DapperTests", "test\DapperTests\DapperTests.csproj", "{80E322F5-5F5D-4670-A30F-02D33C2C7900}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Swashbuckle", "src\JsonApiDotNetCore.OpenApi.Swashbuckle\JsonApiDotNetCore.OpenApi.Swashbuckle.csproj", "{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiTests", "test\OpenApiTests\OpenApiTests.csproj", "{B693DE14-BB28-496F-AB39-B4E674ABCA80}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Client.NSwag", "src\JsonApiDotNetCore.OpenApi.Client.NSwag\JsonApiDotNetCore.OpenApi.Client.NSwag.csproj", "{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagClientExample", "src\Examples\OpenApiNSwagClientExample\OpenApiNSwagClientExample.csproj", "{7FC5DFA3-6F66-4FD8-820D-81E93856F252}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagClientTests", "test\OpenApiNSwagClientTests\OpenApiNSwagClientTests.csproj", "{77F98215-3085-422E-B99D-4C404C2114CF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagEndToEndTests", "test\OpenApiNSwagEndToEndTests\OpenApiNSwagEndToEndTests.csproj", "{3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Client.Kiota", "src\JsonApiDotNetCore.OpenApi.Client.Kiota\JsonApiDotNetCore.OpenApi.Client.Kiota.csproj", "{617FCA5D-A2DE-4083-B373-ADCA9901059F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiKiotaClientExample", "src\Examples\OpenApiKiotaClientExample\OpenApiKiotaClientExample.csproj", "{39DEAFE8-AE29-48E5-A67D-73776D70FC82}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiKiotaEndToEndTests", "test\OpenApiKiotaEndToEndTests\OpenApiKiotaEndToEndTests.csproj", "{FD86C676-3D80-4971-8D8C-B0729B2251F6}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x64.ActiveCfg = Debug|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x64.Build.0 = Debug|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x86.ActiveCfg = Debug|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x86.Build.0 = Debug|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|Any CPU.Build.0 = Release|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x64.ActiveCfg = Release|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x64.Build.0 = Release|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x86.ActiveCfg = Release|Any CPU - {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x86.Build.0 = Release|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x64.ActiveCfg = Debug|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x64.Build.0 = Debug|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x86.ActiveCfg = Debug|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x86.Build.0 = Debug|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|Any CPU.Build.0 = Release|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x64.ActiveCfg = Release|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x64.Build.0 = Release|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x86.ActiveCfg = Release|Any CPU - {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x86.Build.0 = Release|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x64.ActiveCfg = Debug|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x64.Build.0 = Debug|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x86.ActiveCfg = Debug|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x86.Build.0 = Debug|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|Any CPU.Build.0 = Release|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x64.ActiveCfg = Release|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x64.Build.0 = Release|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x86.ActiveCfg = Release|Any CPU - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x86.Build.0 = Release|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x64.ActiveCfg = Debug|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x64.Build.0 = Debug|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x86.ActiveCfg = Debug|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x86.Build.0 = Debug|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|Any CPU.Build.0 = Release|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x64.ActiveCfg = Release|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x64.Build.0 = Release|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x86.ActiveCfg = Release|Any CPU - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x86.Build.0 = Release|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x64.ActiveCfg = Debug|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x64.Build.0 = Debug|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x86.ActiveCfg = Debug|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x86.Build.0 = Debug|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|Any CPU.Build.0 = Release|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x64.ActiveCfg = Release|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x64.Build.0 = Release|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x86.ActiveCfg = Release|Any CPU - {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x86.Build.0 = Release|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x64.ActiveCfg = Debug|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x64.Build.0 = Debug|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x86.ActiveCfg = Debug|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x86.Build.0 = Debug|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|Any CPU.Build.0 = Release|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x64.ActiveCfg = Release|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x64.Build.0 = Release|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x86.ActiveCfg = Release|Any CPU - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x86.Build.0 = Release|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x64.ActiveCfg = Debug|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x64.Build.0 = Debug|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x86.ActiveCfg = Debug|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x86.Build.0 = Debug|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|Any CPU.Build.0 = Release|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x64.ActiveCfg = Release|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x64.Build.0 = Release|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x86.ActiveCfg = Release|Any CPU - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x86.Build.0 = Release|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Debug|Any CPU.Build.0 = Debug|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x64.ActiveCfg = Debug|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x64.Build.0 = Debug|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x86.ActiveCfg = Debug|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x86.Build.0 = Debug|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Release|Any CPU.ActiveCfg = Release|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Release|Any CPU.Build.0 = Release|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Release|x64.ActiveCfg = Release|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Release|x64.Build.0 = Release|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Release|x86.ActiveCfg = Release|Any CPU - {789085E1-048F-4996-B600-791B9CA3A663}.Release|x86.Build.0 = Release|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x64.ActiveCfg = Debug|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x64.Build.0 = Debug|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x86.ActiveCfg = Debug|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x86.Build.0 = Debug|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|Any CPU.Build.0 = Release|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x64.ActiveCfg = Release|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x64.Build.0 = Release|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x86.ActiveCfg = Release|Any CPU - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x86.Build.0 = Release|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x64.ActiveCfg = Debug|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x64.Build.0 = Debug|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x86.ActiveCfg = Debug|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x86.Build.0 = Debug|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|Any CPU.Build.0 = Release|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x64.ActiveCfg = Release|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x64.Build.0 = Release|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x86.ActiveCfg = Release|Any CPU - {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x86.Build.0 = Release|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x64.ActiveCfg = Debug|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x64.Build.0 = Debug|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x86.ActiveCfg = Debug|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x86.Build.0 = Debug|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|Any CPU.Build.0 = Release|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x64.ActiveCfg = Release|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x64.Build.0 = Release|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x86.ActiveCfg = Release|Any CPU - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x86.Build.0 = Release|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x64.ActiveCfg = Debug|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x64.Build.0 = Debug|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x86.ActiveCfg = Debug|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x86.Build.0 = Debug|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|Any CPU.Build.0 = Release|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x64.ActiveCfg = Release|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x64.Build.0 = Release|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x86.ActiveCfg = Release|Any CPU - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x86.Build.0 = Release|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|Any CPU.Build.0 = Debug|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x64.ActiveCfg = Debug|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x64.Build.0 = Debug|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x86.ActiveCfg = Debug|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x86.Build.0 = Debug|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|Any CPU.ActiveCfg = Release|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|Any CPU.Build.0 = Release|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x64.ActiveCfg = Release|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x64.Build.0 = Release|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.ActiveCfg = Release|Any CPU - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.Build.0 = Release|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|Any CPU.Build.0 = Debug|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x64.ActiveCfg = Debug|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x64.Build.0 = Debug|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x86.ActiveCfg = Debug|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x86.Build.0 = Debug|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|Any CPU.ActiveCfg = Release|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|Any CPU.Build.0 = Release|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x64.ActiveCfg = Release|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x64.Build.0 = Release|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x86.ActiveCfg = Release|Any CPU - {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x86.Build.0 = Release|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x64.ActiveCfg = Debug|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x64.Build.0 = Debug|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x86.ActiveCfg = Debug|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x86.Build.0 = Debug|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|Any CPU.Build.0 = Release|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x64.ActiveCfg = Release|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x64.Build.0 = Release|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x86.ActiveCfg = Release|Any CPU - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x86.Build.0 = Release|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x64.ActiveCfg = Debug|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x64.Build.0 = Debug|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x86.ActiveCfg = Debug|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x86.Build.0 = Debug|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|Any CPU.Build.0 = Release|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x64.ActiveCfg = Release|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x64.Build.0 = Release|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x86.ActiveCfg = Release|Any CPU - {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x86.Build.0 = Release|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x64.ActiveCfg = Debug|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x64.Build.0 = Debug|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x86.ActiveCfg = Debug|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x86.Build.0 = Debug|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|Any CPU.Build.0 = Release|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x64.ActiveCfg = Release|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x64.Build.0 = Release|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x86.ActiveCfg = Release|Any CPU - {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x86.Build.0 = Release|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x64.ActiveCfg = Debug|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x64.Build.0 = Debug|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x86.ActiveCfg = Debug|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x86.Build.0 = Debug|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|Any CPU.ActiveCfg = Release|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|Any CPU.Build.0 = Release|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x64.ActiveCfg = Release|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x64.Build.0 = Release|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x86.ActiveCfg = Release|Any CPU - {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x86.Build.0 = Release|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x64.ActiveCfg = Debug|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x64.Build.0 = Debug|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x86.ActiveCfg = Debug|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x86.Build.0 = Debug|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|Any CPU.Build.0 = Release|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x64.ActiveCfg = Release|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x64.Build.0 = Release|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x86.ActiveCfg = Release|Any CPU - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x86.Build.0 = Release|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|Any CPU.Build.0 = Debug|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x64.ActiveCfg = Debug|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x64.Build.0 = Debug|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x86.ActiveCfg = Debug|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x86.Build.0 = Debug|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|Any CPU.ActiveCfg = Release|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|Any CPU.Build.0 = Release|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x64.ActiveCfg = Release|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x64.Build.0 = Release|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x86.ActiveCfg = Release|Any CPU - {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x86.Build.0 = Release|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.ActiveCfg = Debug|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.Build.0 = Debug|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.ActiveCfg = Debug|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.Build.0 = Debug|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.Build.0 = Release|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.ActiveCfg = Release|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.Build.0 = Release|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.ActiveCfg = Release|Any CPU - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.Build.0 = Release|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.ActiveCfg = Debug|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.Build.0 = Debug|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.ActiveCfg = Debug|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.Build.0 = Debug|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.Build.0 = Release|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.ActiveCfg = Release|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.Build.0 = Release|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.ActiveCfg = Release|Any CPU - {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.Build.0 = Release|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.ActiveCfg = Debug|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.Build.0 = Debug|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.ActiveCfg = Debug|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.Build.0 = Debug|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.Build.0 = Release|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.ActiveCfg = Release|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.Build.0 = Release|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.ActiveCfg = Release|Any CPU - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.Build.0 = Release|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.ActiveCfg = Debug|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.Build.0 = Debug|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.ActiveCfg = Debug|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.Build.0 = Debug|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.Build.0 = Release|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.ActiveCfg = Release|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.Build.0 = Release|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.ActiveCfg = Release|Any CPU - {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.Build.0 = Release|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.ActiveCfg = Debug|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.Build.0 = Debug|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.ActiveCfg = Debug|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.Build.0 = Debug|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.Build.0 = Release|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.ActiveCfg = Release|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.Build.0 = Release|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.ActiveCfg = Release|Any CPU - {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.Build.0 = Release|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x64.ActiveCfg = Debug|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x64.Build.0 = Debug|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x86.ActiveCfg = Debug|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x86.Build.0 = Debug|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|Any CPU.Build.0 = Release|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x64.ActiveCfg = Release|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x64.Build.0 = Release|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x86.ActiveCfg = Release|Any CPU - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x86.Build.0 = Release|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x64.ActiveCfg = Debug|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x64.Build.0 = Debug|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x86.ActiveCfg = Debug|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x86.Build.0 = Debug|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|Any CPU.Build.0 = Release|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x64.ActiveCfg = Release|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x64.Build.0 = Release|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x86.ActiveCfg = Release|Any CPU - {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x86.Build.0 = Release|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x64.ActiveCfg = Debug|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x64.Build.0 = Debug|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x86.ActiveCfg = Debug|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x86.Build.0 = Debug|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|Any CPU.Build.0 = Release|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x64.ActiveCfg = Release|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x64.Build.0 = Release|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x86.ActiveCfg = Release|Any CPU - {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x86.Build.0 = Release|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x64.ActiveCfg = Debug|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x64.Build.0 = Debug|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x86.ActiveCfg = Debug|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x86.Build.0 = Debug|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|Any CPU.Build.0 = Release|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x64.ActiveCfg = Release|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x64.Build.0 = Release|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x86.ActiveCfg = Release|Any CPU - {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {CAF331F8-9255-4D72-A1A8-A54141E99F1E} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {4F15A8F8-5BC6-45A1-BC51-03F921B726A4} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {8788FF65-C2B6-40B2-A3A0-1E3D91C02664} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {03032A2F-664D-4DD8-A82F-AD8A482EDD85} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C} = {076E1AE4-FD25-4684-B826-CAAE37FEA0AA} - {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {789085E1-048F-4996-B600-791B9CA3A663} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {21D27239-138D-4604-8E49-DCBE41BCE4C8} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {6CAFDDBE-00AB-4784-801B-AB419C3C3A26} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {952C0FDE-AFC8-455C-986F-6CC882ED8953} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {83FF097C-C8C6-477B-9FAB-DF99B84978B5} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {60334658-BE51-43B3-9C4D-F2BBF56C89CE} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {24B0C12F-38CD-4245-8785-87BEFAD55B00} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {C1774117-5073-4DF8-B5BE-BF7B538BD1C2} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {80E322F5-5F5D-4670-A30F-02D33C2C7900} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {71287D6F-6C3B-44B4-9FCA-E78FE3F02289} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {B693DE14-BB28-496F-AB39-B4E674ABCA80} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {7FC5DFA3-6F66-4FD8-820D-81E93856F252} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {77F98215-3085-422E-B99D-4C404C2114CF} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {617FCA5D-A2DE-4083-B373-ADCA9901059F} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {39DEAFE8-AE29-48E5-A67D-73776D70FC82} = {026FBC6C-AF76-4568-9B87-EC73457899FD} - {FD86C676-3D80-4971-8D8C-B0729B2251F6} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4} - EndGlobalSection -EndGlobal diff --git a/JsonApiDotNetCore.slnx b/JsonApiDotNetCore.slnx new file mode 100644 index 0000000000..296b8f681a --- /dev/null +++ b/JsonApiDotNetCore.slnx @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/JsonApiDotNetCore.sln.DotSettings b/JsonApiDotNetCore.slnx.DotSettings similarity index 99% rename from JsonApiDotNetCore.sln.DotSettings rename to JsonApiDotNetCore.slnx.DotSettings index e340302b69..d52b9cfc4a 100644 --- a/JsonApiDotNetCore.sln.DotSettings +++ b/JsonApiDotNetCore.slnx.DotSettings @@ -4,7 +4,7 @@ 3000 False True - 83FF097C-C8C6-477B-9FAB-DF99B84978B5/f:ReadOnlySet.cs + 58FE19B6-F84A-990C-B25F-E37C391C3BD3/f:ReadOnlySet.cs swagger.g.json swagger.json SOLUTION diff --git a/cleanupcode.ps1 b/cleanupcode.ps1 index d87c58a342..ac2ad3b8c2 100644 --- a/cleanupcode.ps1 +++ b/cleanupcode.ps1 @@ -19,6 +19,8 @@ VerifySuccessExitCode dotnet restore VerifySuccessExitCode +$solutionFile = 'JsonApiDotNetCore.slnx' + if ($revision) { $headCommitHash = git rev-parse HEAD VerifySuccessExitCode @@ -29,19 +31,19 @@ if ($revision) { if ($baseCommitHash -eq $headCommitHash) { Write-Output "Running code cleanup on staged/unstaged files." dotnet jb cleanupcode --version - dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified + dotnet regitlint -s $solutionFile --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified VerifySuccessExitCode } else { Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash, including staged/unstaged files." dotnet jb cleanupcode --version - dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash + dotnet regitlint -s $solutionFile --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash VerifySuccessExitCode } } else { Write-Output "Running code cleanup on all files." dotnet jb cleanupcode --version - dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN + dotnet regitlint -s $solutionFile --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN VerifySuccessExitCode } diff --git a/inspectcode.ps1 b/inspectcode.ps1 index e3ae50660b..23e857c019 100644 --- a/inspectcode.ps1 +++ b/inspectcode.ps1 @@ -2,20 +2,22 @@ # This script runs code inspection and opens the results in a web browser. -dotnet tool restore - -if ($LastExitCode -ne 0) { - throw "Tool restore failed with exit code $LastExitCode" +function VerifySuccessExitCode { + if ($LastExitCode -ne 0) { + throw "Command failed with exit code $LastExitCode." + } } +dotnet tool restore +VerifySuccessExitCode + +$solutionFile = 'JsonApiDotNetCore.slnx' $outputPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.xml') $resultPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.html') -dotnet jb inspectcode --version -dotnet jb inspectcode JsonApiDotNetCore.sln --dotnetcoresdk=$(dotnet --version) --build --output="$outputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal -if ($LastExitCode -ne 0) { - throw "Code inspection failed with exit code $LastExitCode" -} +dotnet jb inspectcode --version +dotnet jb inspectcode $solutionFile --dotnetcoresdk=$(dotnet --version) --build --output="$outputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal +VerifySuccessExitCode [xml]$xml = Get-Content "$outputPath" if ($xml.report.Issues -and $xml.report.Issues.Project) { From a769245e43857907c3e3e4daab63eb274447fc61 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Fri, 21 Nov 2025 23:41:42 +0100 Subject: [PATCH 21/26] Revert "Convert to slnx" This reverts commit efe5ea5fd6d04d0e94f73d8e9980aac86e17839d. --- .github/workflows/build.yml | 7 +- JsonApiDotNetCore.sln | 479 ++++++++++++++++++ ...tings => JsonApiDotNetCore.sln.DotSettings | 2 +- JsonApiDotNetCore.slnx | 54 -- cleanupcode.ps1 | 8 +- inspectcode.ps1 | 20 +- 6 files changed, 495 insertions(+), 75 deletions(-) create mode 100644 JsonApiDotNetCore.sln rename JsonApiDotNetCore.slnx.DotSettings => JsonApiDotNetCore.sln.DotSettings (99%) delete mode 100644 JsonApiDotNetCore.slnx diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 906a775636..3e9f8edd9c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,6 @@ concurrency: env: DOTNET_NOLOGO: true DOTNET_CLI_TELEMETRY_OPTOUT: true - SOLUTION_FILE: JsonApiDotNetCore.slnx jobs: build-and-test: @@ -172,7 +171,7 @@ jobs: $inspectCodeOutputPath = Join-Path $env:RUNNER_TEMP 'jetbrains-inspectcode-results.xml' Write-Output "INSPECT_CODE_OUTPUT_PATH=$inspectCodeOutputPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append dotnet jb inspectcode --version - dotnet jb inspectcode $env:SOLUTION_FILE --build --dotnetcoresdk=$(dotnet --version) --output="$inspectCodeOutputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal + dotnet jb inspectcode JsonApiDotNetCore.sln --build --dotnetcoresdk=$(dotnet --version) --output="$inspectCodeOutputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal - name: Upload output to artifacts uses: actions/upload-artifact@v4 with: @@ -242,14 +241,14 @@ jobs: Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request." dotnet jb cleanupcode --version - dotnet regitlint -s $env:SOLUTION_FILE --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff + dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff - name: CleanupCode (on branch) if: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'workflow_dispatch' }} shell: pwsh run: | Write-Output 'Running code cleanup on all files.' dotnet jb cleanupcode --version - dotnet regitlint -s $env:SOLUTION_FILE --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff + dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff publish: timeout-minutes: 60 diff --git a/JsonApiDotNetCore.sln b/JsonApiDotNetCore.sln new file mode 100644 index 0000000000..793c01950d --- /dev/null +++ b/JsonApiDotNetCore.sln @@ -0,0 +1,479 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31919.166 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{24B15015-62E5-42E1-9BA0-ECE6BE7AA15F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5B4D998-CECB-454D-9F32-085A897577BE}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore + .github\workflows\build.yml = .github\workflows\build.yml + CodingGuidelines.ruleset = CodingGuidelines.ruleset + CSharpGuidelinesAnalyzer.config = CSharpGuidelinesAnalyzer.config + Directory.Build.props = Directory.Build.props + package-versions.props = package-versions.props + tests.runsettings = tests.runsettings + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{026FBC6C-AF76-4568-9B87-EC73457899FD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{076E1AE4-FD25-4684-B826-CAAE37FEA0AA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GettingStarted", "src\Examples\GettingStarted\GettingStarted.csproj", "{067FFD7A-C66B-473D-8471-37F5C95DF61C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCoreTests", "test\JsonApiDotNetCoreTests\JsonApiDotNetCoreTests.csproj", "{CAF331F8-9255-4D72-A1A8-A54141E99F1E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NoEntityFrameworkTests", "test\NoEntityFrameworkTests\NoEntityFrameworkTests.csproj", "{4F15A8F8-5BC6-45A1-BC51-03F921B726A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "test\UnitTests\UnitTests.csproj", "{8788FF65-C2B6-40B2-A3A0-1E3D91C02664}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscoveryTests", "test\DiscoveryTests\DiscoveryTests.csproj", "{03032A2F-664D-4DD8-A82F-AD8A482EDD85}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "benchmarks\Benchmarks.csproj", "{DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCoreExample", "src\Examples\JsonApiDotNetCoreExample\JsonApiDotNetCoreExample.csproj", "{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NoEntityFrameworkExample", "src\Examples\NoEntityFrameworkExample\NoEntityFrameworkExample.csproj", "{789085E1-048F-4996-B600-791B9CA3A663}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReportsExample", "src\Examples\ReportsExample\ReportsExample.csproj", "{8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\JsonApiDotNetCore\JsonApiDotNetCore.csproj", "{21D27239-138D-4604-8E49-DCBE41BCE4C8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiDbContextExample", "src\Examples\MultiDbContextExample\MultiDbContextExample.csproj", "{6CAFDDBE-00AB-4784-801B-AB419C3C3A26}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiDbContextTests", "test\MultiDbContextTests\MultiDbContextTests.csproj", "{EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestBuildingBlocks", "test\TestBuildingBlocks\TestBuildingBlocks.csproj", "{210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.SourceGenerators", "src\JsonApiDotNetCore.SourceGenerators\JsonApiDotNetCore.SourceGenerators.csproj", "{952C0FDE-AFC8-455C-986F-6CC882ED8953}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGeneratorTests", "test\SourceGeneratorTests\SourceGeneratorTests.csproj", "{0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.Annotations", "src\JsonApiDotNetCore.Annotations\JsonApiDotNetCore.Annotations.csproj", "{83FF097C-C8C6-477B-9FAB-DF99B84978B5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabasePerTenantExample", "src\Examples\DatabasePerTenantExample\DatabasePerTenantExample.csproj", "{60334658-BE51-43B3-9C4D-F2BBF56C89CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnnotationTests", "test\AnnotationTests\AnnotationTests.csproj", "{24B0C12F-38CD-4245-8785-87BEFAD55B00}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DapperExample", "src\Examples\DapperExample\DapperExample.csproj", "{C1774117-5073-4DF8-B5BE-BF7B538BD1C2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DapperTests", "test\DapperTests\DapperTests.csproj", "{80E322F5-5F5D-4670-A30F-02D33C2C7900}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Swashbuckle", "src\JsonApiDotNetCore.OpenApi.Swashbuckle\JsonApiDotNetCore.OpenApi.Swashbuckle.csproj", "{71287D6F-6C3B-44B4-9FCA-E78FE3F02289}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiTests", "test\OpenApiTests\OpenApiTests.csproj", "{B693DE14-BB28-496F-AB39-B4E674ABCA80}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Client.NSwag", "src\JsonApiDotNetCore.OpenApi.Client.NSwag\JsonApiDotNetCore.OpenApi.Client.NSwag.csproj", "{5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagClientExample", "src\Examples\OpenApiNSwagClientExample\OpenApiNSwagClientExample.csproj", "{7FC5DFA3-6F66-4FD8-820D-81E93856F252}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagClientTests", "test\OpenApiNSwagClientTests\OpenApiNSwagClientTests.csproj", "{77F98215-3085-422E-B99D-4C404C2114CF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiNSwagEndToEndTests", "test\OpenApiNSwagEndToEndTests\OpenApiNSwagEndToEndTests.csproj", "{3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore.OpenApi.Client.Kiota", "src\JsonApiDotNetCore.OpenApi.Client.Kiota\JsonApiDotNetCore.OpenApi.Client.Kiota.csproj", "{617FCA5D-A2DE-4083-B373-ADCA9901059F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiKiotaClientExample", "src\Examples\OpenApiKiotaClientExample\OpenApiKiotaClientExample.csproj", "{39DEAFE8-AE29-48E5-A67D-73776D70FC82}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenApiKiotaEndToEndTests", "test\OpenApiKiotaEndToEndTests\OpenApiKiotaEndToEndTests.csproj", "{FD86C676-3D80-4971-8D8C-B0729B2251F6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x64.ActiveCfg = Debug|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x64.Build.0 = Debug|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x86.ActiveCfg = Debug|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x86.Build.0 = Debug|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|Any CPU.Build.0 = Release|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x64.ActiveCfg = Release|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x64.Build.0 = Release|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x86.ActiveCfg = Release|Any CPU + {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x86.Build.0 = Release|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x64.ActiveCfg = Debug|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x64.Build.0 = Debug|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x86.ActiveCfg = Debug|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x86.Build.0 = Debug|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|Any CPU.Build.0 = Release|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x64.ActiveCfg = Release|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x64.Build.0 = Release|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x86.ActiveCfg = Release|Any CPU + {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x86.Build.0 = Release|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x64.ActiveCfg = Debug|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x64.Build.0 = Debug|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x86.ActiveCfg = Debug|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x86.Build.0 = Debug|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|Any CPU.Build.0 = Release|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x64.ActiveCfg = Release|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x64.Build.0 = Release|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x86.ActiveCfg = Release|Any CPU + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Release|x86.Build.0 = Release|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x64.ActiveCfg = Debug|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x64.Build.0 = Debug|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x86.ActiveCfg = Debug|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Debug|x86.Build.0 = Debug|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|Any CPU.Build.0 = Release|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x64.ActiveCfg = Release|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x64.Build.0 = Release|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x86.ActiveCfg = Release|Any CPU + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664}.Release|x86.Build.0 = Release|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x64.ActiveCfg = Debug|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x64.Build.0 = Debug|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x86.ActiveCfg = Debug|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Debug|x86.Build.0 = Debug|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|Any CPU.Build.0 = Release|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x64.ActiveCfg = Release|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x64.Build.0 = Release|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x86.ActiveCfg = Release|Any CPU + {03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x86.Build.0 = Release|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x64.ActiveCfg = Debug|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x64.Build.0 = Debug|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x86.ActiveCfg = Debug|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x86.Build.0 = Debug|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|Any CPU.Build.0 = Release|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x64.ActiveCfg = Release|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x64.Build.0 = Release|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x86.ActiveCfg = Release|Any CPU + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Release|x86.Build.0 = Release|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x64.ActiveCfg = Debug|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x64.Build.0 = Debug|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x86.ActiveCfg = Debug|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x86.Build.0 = Debug|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|Any CPU.Build.0 = Release|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x64.ActiveCfg = Release|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x64.Build.0 = Release|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x86.ActiveCfg = Release|Any CPU + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x86.Build.0 = Release|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Debug|Any CPU.Build.0 = Debug|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x64.ActiveCfg = Debug|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x64.Build.0 = Debug|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x86.ActiveCfg = Debug|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Debug|x86.Build.0 = Debug|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Release|Any CPU.ActiveCfg = Release|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Release|Any CPU.Build.0 = Release|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Release|x64.ActiveCfg = Release|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Release|x64.Build.0 = Release|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Release|x86.ActiveCfg = Release|Any CPU + {789085E1-048F-4996-B600-791B9CA3A663}.Release|x86.Build.0 = Release|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x64.ActiveCfg = Debug|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x64.Build.0 = Debug|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x86.ActiveCfg = Debug|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Debug|x86.Build.0 = Debug|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|Any CPU.Build.0 = Release|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x64.ActiveCfg = Release|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x64.Build.0 = Release|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x86.ActiveCfg = Release|Any CPU + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B}.Release|x86.Build.0 = Release|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x64.ActiveCfg = Debug|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x64.Build.0 = Debug|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x86.ActiveCfg = Debug|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x86.Build.0 = Debug|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|Any CPU.Build.0 = Release|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x64.ActiveCfg = Release|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x64.Build.0 = Release|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x86.ActiveCfg = Release|Any CPU + {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x86.Build.0 = Release|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x64.ActiveCfg = Debug|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x64.Build.0 = Debug|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x86.ActiveCfg = Debug|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Debug|x86.Build.0 = Debug|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|Any CPU.Build.0 = Release|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x64.ActiveCfg = Release|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x64.Build.0 = Release|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x86.ActiveCfg = Release|Any CPU + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26}.Release|x86.Build.0 = Release|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x64.ActiveCfg = Debug|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x64.Build.0 = Debug|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x86.ActiveCfg = Debug|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Debug|x86.Build.0 = Debug|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|Any CPU.Build.0 = Release|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x64.ActiveCfg = Release|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x64.Build.0 = Release|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x86.ActiveCfg = Release|Any CPU + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA}.Release|x86.Build.0 = Release|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x64.ActiveCfg = Debug|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x64.Build.0 = Debug|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x86.ActiveCfg = Debug|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Debug|x86.Build.0 = Debug|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|Any CPU.Build.0 = Release|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x64.ActiveCfg = Release|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x64.Build.0 = Release|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.ActiveCfg = Release|Any CPU + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21}.Release|x86.Build.0 = Release|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|Any CPU.Build.0 = Debug|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x64.ActiveCfg = Debug|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x64.Build.0 = Debug|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x86.ActiveCfg = Debug|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Debug|x86.Build.0 = Debug|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|Any CPU.ActiveCfg = Release|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|Any CPU.Build.0 = Release|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x64.ActiveCfg = Release|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x64.Build.0 = Release|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x86.ActiveCfg = Release|Any CPU + {952C0FDE-AFC8-455C-986F-6CC882ED8953}.Release|x86.Build.0 = Release|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x64.ActiveCfg = Debug|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x64.Build.0 = Debug|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x86.ActiveCfg = Debug|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Debug|x86.Build.0 = Debug|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|Any CPU.Build.0 = Release|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x64.ActiveCfg = Release|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x64.Build.0 = Release|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x86.ActiveCfg = Release|Any CPU + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9}.Release|x86.Build.0 = Release|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x64.ActiveCfg = Debug|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x64.Build.0 = Debug|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x86.ActiveCfg = Debug|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Debug|x86.Build.0 = Debug|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|Any CPU.Build.0 = Release|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x64.ActiveCfg = Release|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x64.Build.0 = Release|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x86.ActiveCfg = Release|Any CPU + {83FF097C-C8C6-477B-9FAB-DF99B84978B5}.Release|x86.Build.0 = Release|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x64.ActiveCfg = Debug|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x64.Build.0 = Debug|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x86.ActiveCfg = Debug|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Debug|x86.Build.0 = Debug|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|Any CPU.Build.0 = Release|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x64.ActiveCfg = Release|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x64.Build.0 = Release|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x86.ActiveCfg = Release|Any CPU + {60334658-BE51-43B3-9C4D-F2BBF56C89CE}.Release|x86.Build.0 = Release|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x64.ActiveCfg = Debug|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x64.Build.0 = Debug|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x86.ActiveCfg = Debug|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Debug|x86.Build.0 = Debug|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|Any CPU.Build.0 = Release|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x64.ActiveCfg = Release|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x64.Build.0 = Release|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x86.ActiveCfg = Release|Any CPU + {24B0C12F-38CD-4245-8785-87BEFAD55B00}.Release|x86.Build.0 = Release|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x64.ActiveCfg = Debug|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x64.Build.0 = Debug|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x86.ActiveCfg = Debug|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Debug|x86.Build.0 = Debug|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|Any CPU.Build.0 = Release|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x64.ActiveCfg = Release|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x64.Build.0 = Release|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x86.ActiveCfg = Release|Any CPU + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2}.Release|x86.Build.0 = Release|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x64.ActiveCfg = Debug|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x64.Build.0 = Debug|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x86.ActiveCfg = Debug|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Debug|x86.Build.0 = Debug|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|Any CPU.Build.0 = Release|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x64.ActiveCfg = Release|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x64.Build.0 = Release|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x86.ActiveCfg = Release|Any CPU + {80E322F5-5F5D-4670-A30F-02D33C2C7900}.Release|x86.Build.0 = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.ActiveCfg = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x64.Build.0 = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.ActiveCfg = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Debug|x86.Build.0 = Debug|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|Any CPU.Build.0 = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.ActiveCfg = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x64.Build.0 = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.ActiveCfg = Release|Any CPU + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289}.Release|x86.Build.0 = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.ActiveCfg = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x64.Build.0 = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.ActiveCfg = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Debug|x86.Build.0 = Debug|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|Any CPU.Build.0 = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.ActiveCfg = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x64.Build.0 = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.ActiveCfg = Release|Any CPU + {B693DE14-BB28-496F-AB39-B4E674ABCA80}.Release|x86.Build.0 = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.ActiveCfg = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x64.Build.0 = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.ActiveCfg = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Debug|x86.Build.0 = Debug|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|Any CPU.Build.0 = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.ActiveCfg = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x64.Build.0 = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.ActiveCfg = Release|Any CPU + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C}.Release|x86.Build.0 = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.ActiveCfg = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x64.Build.0 = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.ActiveCfg = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Debug|x86.Build.0 = Debug|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|Any CPU.Build.0 = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.ActiveCfg = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x64.Build.0 = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.ActiveCfg = Release|Any CPU + {7FC5DFA3-6F66-4FD8-820D-81E93856F252}.Release|x86.Build.0 = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.ActiveCfg = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x64.Build.0 = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.ActiveCfg = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Debug|x86.Build.0 = Debug|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|Any CPU.Build.0 = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.ActiveCfg = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x64.Build.0 = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.ActiveCfg = Release|Any CPU + {77F98215-3085-422E-B99D-4C404C2114CF}.Release|x86.Build.0 = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x64.ActiveCfg = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x64.Build.0 = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x86.ActiveCfg = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Debug|x86.Build.0 = Debug|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|Any CPU.Build.0 = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x64.ActiveCfg = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x64.Build.0 = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x86.ActiveCfg = Release|Any CPU + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225}.Release|x86.Build.0 = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x64.ActiveCfg = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x64.Build.0 = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x86.ActiveCfg = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Debug|x86.Build.0 = Debug|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|Any CPU.Build.0 = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x64.ActiveCfg = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x64.Build.0 = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x86.ActiveCfg = Release|Any CPU + {617FCA5D-A2DE-4083-B373-ADCA9901059F}.Release|x86.Build.0 = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x64.ActiveCfg = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x64.Build.0 = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x86.ActiveCfg = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Debug|x86.Build.0 = Debug|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|Any CPU.Build.0 = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x64.ActiveCfg = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x64.Build.0 = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x86.ActiveCfg = Release|Any CPU + {39DEAFE8-AE29-48E5-A67D-73776D70FC82}.Release|x86.Build.0 = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x64.Build.0 = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Debug|x86.Build.0 = Debug|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|Any CPU.Build.0 = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x64.ActiveCfg = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x64.Build.0 = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x86.ActiveCfg = Release|Any CPU + {FD86C676-3D80-4971-8D8C-B0729B2251F6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {CAF331F8-9255-4D72-A1A8-A54141E99F1E} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {4F15A8F8-5BC6-45A1-BC51-03F921B726A4} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {8788FF65-C2B6-40B2-A3A0-1E3D91C02664} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {03032A2F-664D-4DD8-A82F-AD8A482EDD85} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C} = {076E1AE4-FD25-4684-B826-CAAE37FEA0AA} + {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {789085E1-048F-4996-B600-791B9CA3A663} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {21D27239-138D-4604-8E49-DCBE41BCE4C8} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {6CAFDDBE-00AB-4784-801B-AB419C3C3A26} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {EC3202C6-1D4C-4B14-A599-B9D3F27FE3BA} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {210FD61E-FF5D-4CEE-8E0D-C739ECCCBA21} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {952C0FDE-AFC8-455C-986F-6CC882ED8953} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {0E0B5C51-F7E2-4F40-A4E4-DED0E9731DC9} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {83FF097C-C8C6-477B-9FAB-DF99B84978B5} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {60334658-BE51-43B3-9C4D-F2BBF56C89CE} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {24B0C12F-38CD-4245-8785-87BEFAD55B00} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {C1774117-5073-4DF8-B5BE-BF7B538BD1C2} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {80E322F5-5F5D-4670-A30F-02D33C2C7900} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {71287D6F-6C3B-44B4-9FCA-E78FE3F02289} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {B693DE14-BB28-496F-AB39-B4E674ABCA80} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {5ADAA902-5A75-4ECB-B4B4-03291D63CE9C} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {7FC5DFA3-6F66-4FD8-820D-81E93856F252} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {77F98215-3085-422E-B99D-4C404C2114CF} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {3BA4F9B9-3D90-44B5-B09C-28D98E0B4225} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {617FCA5D-A2DE-4083-B373-ADCA9901059F} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {39DEAFE8-AE29-48E5-A67D-73776D70FC82} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {FD86C676-3D80-4971-8D8C-B0729B2251F6} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4} + EndGlobalSection +EndGlobal diff --git a/JsonApiDotNetCore.slnx.DotSettings b/JsonApiDotNetCore.sln.DotSettings similarity index 99% rename from JsonApiDotNetCore.slnx.DotSettings rename to JsonApiDotNetCore.sln.DotSettings index d52b9cfc4a..e340302b69 100644 --- a/JsonApiDotNetCore.slnx.DotSettings +++ b/JsonApiDotNetCore.sln.DotSettings @@ -4,7 +4,7 @@ 3000 False True - 58FE19B6-F84A-990C-B25F-E37C391C3BD3/f:ReadOnlySet.cs + 83FF097C-C8C6-477B-9FAB-DF99B84978B5/f:ReadOnlySet.cs swagger.g.json swagger.json SOLUTION diff --git a/JsonApiDotNetCore.slnx b/JsonApiDotNetCore.slnx deleted file mode 100644 index 296b8f681a..0000000000 --- a/JsonApiDotNetCore.slnx +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cleanupcode.ps1 b/cleanupcode.ps1 index ac2ad3b8c2..d87c58a342 100644 --- a/cleanupcode.ps1 +++ b/cleanupcode.ps1 @@ -19,8 +19,6 @@ VerifySuccessExitCode dotnet restore VerifySuccessExitCode -$solutionFile = 'JsonApiDotNetCore.slnx' - if ($revision) { $headCommitHash = git rev-parse HEAD VerifySuccessExitCode @@ -31,19 +29,19 @@ if ($revision) { if ($baseCommitHash -eq $headCommitHash) { Write-Output "Running code cleanup on staged/unstaged files." dotnet jb cleanupcode --version - dotnet regitlint -s $solutionFile --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified + dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified VerifySuccessExitCode } else { Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash, including staged/unstaged files." dotnet jb cleanupcode --version - dotnet regitlint -s $solutionFile --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash + dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash VerifySuccessExitCode } } else { Write-Output "Running code cleanup on all files." dotnet jb cleanupcode --version - dotnet regitlint -s $solutionFile --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN + dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN VerifySuccessExitCode } diff --git a/inspectcode.ps1 b/inspectcode.ps1 index 23e857c019..e3ae50660b 100644 --- a/inspectcode.ps1 +++ b/inspectcode.ps1 @@ -2,22 +2,20 @@ # This script runs code inspection and opens the results in a web browser. -function VerifySuccessExitCode { - if ($LastExitCode -ne 0) { - throw "Command failed with exit code $LastExitCode." - } -} - dotnet tool restore -VerifySuccessExitCode -$solutionFile = 'JsonApiDotNetCore.slnx' +if ($LastExitCode -ne 0) { + throw "Tool restore failed with exit code $LastExitCode" +} + $outputPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.xml') $resultPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.html') - dotnet jb inspectcode --version -dotnet jb inspectcode $solutionFile --dotnetcoresdk=$(dotnet --version) --build --output="$outputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal -VerifySuccessExitCode +dotnet jb inspectcode JsonApiDotNetCore.sln --dotnetcoresdk=$(dotnet --version) --build --output="$outputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal + +if ($LastExitCode -ne 0) { + throw "Code inspection failed with exit code $LastExitCode" +} [xml]$xml = Get-Content "$outputPath" if ($xml.report.Issues -and $xml.report.Issues.Project) { From 469dc25b0c21d0bef274a5a0f5e1ed3c28e88236 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 22 Nov 2025 13:19:04 +0100 Subject: [PATCH 22/26] Remove kiota workaround --- .gitignore | 3 -- .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../Headers/GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../Links/GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ .../GeneratedCode/kiota-lock.json | 37 +++++++++++++++++++ 16 files changed, 555 insertions(+), 3 deletions(-) create mode 100644 src/Examples/OpenApiKiotaClientExample/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/AttributeTypes/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/IdObfuscation/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/MixedControllers/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/kiota-lock.json create mode 100644 test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/kiota-lock.json diff --git a/.gitignore b/.gitignore index c1757fc159..85bd0f1080 100644 --- a/.gitignore +++ b/.gitignore @@ -423,6 +423,3 @@ FodyWeavers.xsd **/.idea/**/httpRequests/ **/.idea/**/dataSources/ !**/.idea/**/codeStyles/* - -# Workaround for https://github.com/microsoft/kiota/issues/4228 -kiota-lock.json diff --git a/src/Examples/OpenApiKiotaClientExample/GeneratedCode/kiota-lock.json b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..8679b89855 --- /dev/null +++ b/src/Examples/OpenApiKiotaClientExample/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "19BB642CD5A9FBA03BAFE3C25B95140A5EC2082F079AA92E8814025B74EB0E70AF07CBF99482F06848C77C32049C0F3C8BFB2B25E2519BAE97F8DEC313313960", + "descriptionLocation": "../../JsonApiDotNetCoreExample/GeneratedSwagger/JsonApiDotNetCoreExample.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "ExampleApiClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaClientExample.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..e4edc93a03 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AtomicOperations/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "E396A8DEC9B8AA50A277166B500AF7164B4B296C4E7AF2ED163083395177317DB961290BC614658E91819AD441C99647E9A5935E1E93E661317E83839646B2A5", + "descriptionLocation": "../../../OpenApiTests/AtomicOperations/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "AtomicOperationsClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.AtomicOperations.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/AttributeTypes/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/AttributeTypes/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..def1736d7e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/AttributeTypes/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "470127ED08004882F740911D40E752D8ED53AB130D682C7FD37C01873438236B77BE5DEAE52799294A4633FBFE59880647FA24AADE21FDF11066C1A9CAEE8E9B", + "descriptionLocation": "../../../OpenApiTests/AttributeTypes/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "AttributeTypesClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.AttributeTypes.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..fc28efb7bf --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ClientIdGenerationModes/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "E3404B0AE786DB66FBB2136BB27DDFB3A30C109C791238950B8D7EF7BF58088743C3247DAEB6DA6468DF43EB316422D7B61B04AC5AB7E2710D5E0ADB563CA973", + "descriptionLocation": "../../../OpenApiTests/ClientIdGenerationModes/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "ClientIdGenerationModesClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..3ef4b9e4e1 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Headers/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "1A99CE35AAC1973F25A917E2776BAE0CA542956018D97228B68F200D5156C09C161051FCC1EE0DD4A33CAAAA30338D743CEC978D8622FA2C3AB6BDAB00826DA7", + "descriptionLocation": "../../../OpenApiTests/Headers/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "HeadersClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.Headers.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/IdObfuscation/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/IdObfuscation/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..63b88fc628 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/IdObfuscation/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "31F174FA03099E656F9110485E8476F5E87714B5BB8897F75164B22360E7742473322929D63DDBB5B1ADBF68C2B13908B98F3D93E27C926B3F4F9C646E6F8366", + "descriptionLocation": "../../../OpenApiTests/IdObfuscation/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "IdObfuscationClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.IdObfuscation.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..ee2d122ea3 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/Links/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "162E0C524667DC8B14371D9D28DAA91D9980A2653617C73008E8FB7F0BCF2BF80962FE938F46F09A441CCBA431EDA2BF96300E661A86162C20856522E3FC24F0", + "descriptionLocation": "../../../OpenApiTests/Links/Enabled/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "LinksClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.Links.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/MixedControllers/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/MixedControllers/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..c9c8782a7d --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/MixedControllers/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "0766FE86CC36BDA58ED569AC64F9227C962D8A4A7D11DF94E2C6C4120159610528F063AFB5BDAE8EC8B5D0D7B1C87A7EDF3EF9EA440B795CDE236F37694C0776", + "descriptionLocation": "../../../OpenApiTests/MixedControllers/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "MixedControllersClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.MixedControllers.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..b9820010aa --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ModelStateValidation/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "D23DFE7A559ED17024B4C3751668DB944EECB2B12184B515958D5AB9EBB7BC2632277A3C1D61CFB09764A9AC7A9CD58F006EBD60F79451E5D3748E503537A8D7", + "descriptionLocation": "../../../OpenApiTests/ModelStateValidation/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "ModelStateValidationClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.ModelStateValidation.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..5a68388df6 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/QueryStrings/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "4C9E3EEF14CF44CD2E23C28EE2E4D0FF9D49F130DF4572FB1393E43344DC817EBEF92999A8093FD7BF21242108E0EA37BD38E86808DD9AB256A3F0467C6D80D4", + "descriptionLocation": "../../../OpenApiTests/QueryStrings/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "QueryStringsClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.QueryStrings.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..b21354886f --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/NoOperations/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "D17B596209906FEDB8DEEB009C0D5AD867F633F0B120EB297A2F8149E6D9CEC89FCB9175817EC77C1163E98EF1DDB89548EF4CCC4C4C26B925FF67FEF2FBB0E4", + "descriptionLocation": "../../../../OpenApiTests/ResourceInheritance/NoOperations/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "NoOperationsInheritanceClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.ResourceInheritance.NoOperations.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..160fb8434e --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/OnlyRelationships/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "4DB0EB44353753EA3219D40CD202FCA401EAD5E4A760A40B9FAD50EF913F3D5306B2A1228C92BE886F7DFE3F95F77627272A67D8A1E4BDB02F909034012C26E6", + "descriptionLocation": "../../../../OpenApiTests/ResourceInheritance/OnlyRelationships/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "OnlyRelationshipsInheritanceClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.ResourceInheritance.OnlyRelationships.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..d371893754 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfOperations/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "027F7817A47351EF48A63D99EA54A9168DFBF1365CE9F46C49481F2DBDB3EA6AEE32BAAE3E9D6EC6DC9D40A1E7B79ADCF11E43E426A36CCC1E64B00137B8F018", + "descriptionLocation": "../../../../OpenApiTests/ResourceInheritance/SubsetOfOperations/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "SubsetOfOperationsInheritanceClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfOperations.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..4b3b427b6b --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/ResourceInheritance/SubsetOfVarious/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "000C75DD85639C4386B001907E0BB38E4C6E8FB184F8B4CDA1D4D174C03778881CA74F6ED1315BFF409B5855A14AE25D706E2E4A23C95238BABACFF2AA7AB1BC", + "descriptionLocation": "../../../../OpenApiTests/ResourceInheritance/SubsetOfVarious/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "SubsetOfVariousInheritanceClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.ResourceInheritance.SubsetOfVarious.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file diff --git a/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/kiota-lock.json b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/kiota-lock.json new file mode 100644 index 0000000000..1019346939 --- /dev/null +++ b/test/OpenApiKiotaEndToEndTests/RestrictedControllers/GeneratedCode/kiota-lock.json @@ -0,0 +1,37 @@ +{ + "descriptionHash": "BA45DAE2194A0C5FF2DD6A602A8513729ADAD7DF5F8B9C7C112A90C1162556B76FF931A1661D8D76470265A371B68E453B584D9DAACA39D90DB6621CE5AE6B39", + "descriptionLocation": "../../../OpenApiTests/RestrictedControllers/GeneratedSwagger/swagger.g.json", + "lockFileVersion": "1.0.0", + "kiotaVersion": "1.29.0", + "clientClassName": "RestrictedControllersClient", + "typeAccessModifier": "Public", + "clientNamespaceName": "OpenApiKiotaEndToEndTests.RestrictedControllers.GeneratedCode", + "language": "CSharp", + "usesBackingStore": true, + "excludeBackwardCompatible": true, + "includeAdditionalData": true, + "disableSSLValidation": false, + "serializers": [ + "Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory", + "Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory" + ], + "deserializers": [ + "Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory", + "Microsoft.Kiota.Serialization.Text.TextParseNodeFactory", + "Microsoft.Kiota.Serialization.Form.FormParseNodeFactory" + ], + "structuredMimeTypes": [ + "application/json", + "text/plain;q=0.9", + "application/x-www-form-urlencoded;q=0.2", + "multipart/form-data;q=0.1" + ], + "includePatterns": [], + "excludePatterns": [], + "disabledValidationRules": [ + "KnownAndNotSupportedFormats", + "InconsistentTypeFormatPair" + ] +} \ No newline at end of file From 0663bb57fc5b079bdc19efdcd56f91c3b9f0e17f Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 22 Nov 2025 13:22:27 +0100 Subject: [PATCH 23/26] Remove NSwag workaround --- src/Examples/OpenApiNSwagClientExample/.editorconfig | 3 --- test/OpenApiNSwagClientTests/.editorconfig | 3 --- test/OpenApiNSwagEndToEndTests/.editorconfig | 3 --- 3 files changed, 9 deletions(-) delete mode 100644 src/Examples/OpenApiNSwagClientExample/.editorconfig delete mode 100644 test/OpenApiNSwagClientTests/.editorconfig delete mode 100644 test/OpenApiNSwagEndToEndTests/.editorconfig diff --git a/src/Examples/OpenApiNSwagClientExample/.editorconfig b/src/Examples/OpenApiNSwagClientExample/.editorconfig deleted file mode 100644 index e2ec1cac44..0000000000 --- a/src/Examples/OpenApiNSwagClientExample/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -# Workaround for incorrect nullability in NSwag generated clients. -[*Client.cs] -dotnet_diagnostic.CS8765.severity = none diff --git a/test/OpenApiNSwagClientTests/.editorconfig b/test/OpenApiNSwagClientTests/.editorconfig deleted file mode 100644 index e2ec1cac44..0000000000 --- a/test/OpenApiNSwagClientTests/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -# Workaround for incorrect nullability in NSwag generated clients. -[*Client.cs] -dotnet_diagnostic.CS8765.severity = none diff --git a/test/OpenApiNSwagEndToEndTests/.editorconfig b/test/OpenApiNSwagEndToEndTests/.editorconfig deleted file mode 100644 index e2ec1cac44..0000000000 --- a/test/OpenApiNSwagEndToEndTests/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -# Workaround for incorrect nullability in NSwag generated clients. -[*Client.cs] -dotnet_diagnostic.CS8765.severity = none From 01b95d482a0108f13261dd7001e754078a8806cf Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 22 Nov 2025 13:29:22 +0100 Subject: [PATCH 24/26] Remove R# workaround --- src/JsonApiDotNetCore.SourceGenerators/FullControllerInfo.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/JsonApiDotNetCore.SourceGenerators/FullControllerInfo.cs b/src/JsonApiDotNetCore.SourceGenerators/FullControllerInfo.cs index c11c44b4c5..1a75e0bf58 100644 --- a/src/JsonApiDotNetCore.SourceGenerators/FullControllerInfo.cs +++ b/src/JsonApiDotNetCore.SourceGenerators/FullControllerInfo.cs @@ -22,8 +22,6 @@ public static FullControllerInfo Create(CoreControllerInfo coreController, strin public FullControllerInfo WithHintFileName(string hintFileName) { - // ReSharper disable once UseWithExpressionToCopyRecord - // Justification: Workaround for bug at https://youtrack.jetbrains.com/issue/RSRP-502017/Invalid-suggestion-to-use-with-expression. return new FullControllerInfo(CoreController, ControllerType, LoggerFactoryInterface, hintFileName); } } From 7d86a963141a944bbef50bb687bae3683938fef5 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 22 Nov 2025 15:30:04 +0100 Subject: [PATCH 25/26] Fix incorrect API documentation --- .../AtomicOperations/DefaultOperationFilter.cs | 2 +- src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs b/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs index fb632dd276..cb139180ad 100644 --- a/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs +++ b/src/JsonApiDotNetCore/AtomicOperations/DefaultOperationFilter.cs @@ -6,7 +6,7 @@ namespace JsonApiDotNetCore.AtomicOperations; -/// +/// public class DefaultOperationFilter : IAtomicOperationFilter { /// diff --git a/src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs b/src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs index a9806129f8..97bd528c90 100644 --- a/src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs +++ b/src/JsonApiDotNetCore/Middleware/JsonApiContentNegotiator.cs @@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Middleware; -/// +/// [PublicAPI] public class JsonApiContentNegotiator : IJsonApiContentNegotiator { From 94a821f3d87ba73a184fcfe1896005e12b633872 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 22 Nov 2025 16:45:51 +0100 Subject: [PATCH 26/26] Add temporary workaround until docfx version is available that is compatible with .NET 10 --- docs/.gitignore | 1 + docs/build-dev.ps1 | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/.gitignore b/docs/.gitignore index d69ba1a98f..a55a9b60da 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -3,3 +3,4 @@ api/*.yml api/.manifest request-examples/*.json request-examples/*.temp +docfx-net10-binaries/ diff --git a/docs/build-dev.ps1 b/docs/build-dev.ps1 index 5072111dd6..80bd00b781 100644 --- a/docs/build-dev.ps1 +++ b/docs/build-dev.ps1 @@ -9,12 +9,25 @@ param( [switch] $NoOpen=$False ) +# workaround for bug at https://github.com/PowerShell/PowerShell/issues/23875#issuecomment-2672336383 +$PSDefaultParameterValues['Remove-Item:ProgressAction'] = 'SilentlyContinue' + function VerifySuccessExitCode { if ($LastExitCode -ne 0) { throw "Command failed with exit code $LastExitCode." } } +function EnsureDocfxBinaries() { + # Temporary workaround until a proper DocFX build supporting .NET 10 is available. + $zipFile = [IO.Path]::Combine($env:TEMP, 'docfx-net10-binaries.zip') + + if (!(Test-Path -Path $zipFile)) { + Invoke-WebRequest -Uri 'https://github.com/json-api-dotnet/docfx/raw/refs/heads/dotnet10-rtm/net10-binaries.zip' -Method 'GET' -OutFile $zipFile + Expand-Archive $zipFile -Force + } +} + function EnsureHttpServerIsInstalled { if ((Get-Command "npm" -ErrorAction SilentlyContinue) -eq $null) { throw "Unable to find npm in your PATH. please install Node.js first." @@ -25,9 +38,13 @@ function EnsureHttpServerIsInstalled { if ($LastExitCode -eq 1) { npm install -g httpserver + VerifySuccessExitCode } } +EnsureDocfxBinaries +VerifySuccessExitCode + EnsureHttpServerIsInstalled VerifySuccessExitCode @@ -46,7 +63,7 @@ dotnet tool restore VerifySuccessExitCode $env:DOCFX_SOURCE_BRANCH_NAME="dev" -dotnet docfx ./docfx.json --warningsAsErrors true +docfx-net10-binaries/docfx ./docfx.json --warningsAsErrors true VerifySuccessExitCode Copy-Item -Force home/*.html _site/