From d2a6719fedf7e9f0ea6ea4484b723a7d39d41424 Mon Sep 17 00:00:00 2001 From: Steven Yeh Date: Fri, 16 Jan 2026 19:32:14 -0600 Subject: [PATCH 01/18] Fix Typo in IOpenApiReadOnlyExtensible.cs --- src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs index fac742d7d..c059842c0 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs @@ -3,7 +3,7 @@ namespace Microsoft.OpenApi; /// -/// Represents an Extensible Open API element elements can be rad from. +/// Represents an Extensible Open API element elements can be read from. /// public interface IOpenApiReadOnlyExtensible { From e38e511de5c90a4e73868cb292a2fff7cd7071a4 Mon Sep 17 00:00:00 2001 From: Steven Yeh Date: Fri, 16 Jan 2026 19:32:14 -0600 Subject: [PATCH 02/18] Fix Typo in IOpenApiReadOnlyExtensible.cs --- src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs index fac742d7d..c059842c0 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReadOnlyExtensible.cs @@ -3,7 +3,7 @@ namespace Microsoft.OpenApi; /// -/// Represents an Extensible Open API element elements can be rad from. +/// Represents an Extensible Open API element elements can be read from. /// public interface IOpenApiReadOnlyExtensible { From a8fb81cf9524a3f2f721aa808db244434e1cd177 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 19 Jan 2026 11:15:25 -0500 Subject: [PATCH 03/18] fix: discriminator property validation fails any/allOf cases when it shouldn't Signed-off-by: Vincent Biret --- .../Validations/Rules/OpenApiSchemaRules.cs | 41 ++++---- .../PublicApi/PublicApi.approved.txt | 4 + .../OpenApiSchemaValidationTests.cs | 99 ++++++++++++++++++- 3 files changed, 126 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs index 70d558a13..4f2a122a9 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs @@ -5,6 +5,8 @@ namespace Microsoft.OpenApi { + using System; + using System.ComponentModel; using System.Linq; /// @@ -48,6 +50,7 @@ public static class OpenApiSchemaRules { var discriminatorName = schema.Discriminator?.PropertyName; +#pragma warning disable CS0618 // Type or member is obsolete if (!ValidateChildSchemaAgainstDiscriminator(schema, discriminatorName)) { context.Enter("discriminator"); @@ -56,6 +59,7 @@ public static class OpenApiSchemaRules schema is OpenApiSchemaReference { Reference: not null} schemaReference ? schemaReference.Reference.Id : string.Empty, discriminatorName)); context.Exit(); } +#pragma warning restore CS0618 // Type or member is obsolete } }); @@ -65,6 +69,8 @@ public static class OpenApiSchemaRules /// The parent schema. /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate /// between other schemas which may satisfy the payload description. + [Obsolete("This method will be made private in future versions.")] + [Browsable(false)] public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema, string? discriminatorName) { if (discriminatorName is not null) @@ -72,15 +78,15 @@ public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema if (schema.Required is null || !schema.Required.Contains(discriminatorName)) { // recursively check nested schema.OneOf, schema.AnyOf or schema.AllOf and their required fields for the discriminator - if (schema.OneOf?.Count != 0) + if (schema.OneOf is { Count: > 0}) { return TraverseSchemaElements(discriminatorName, schema.OneOf); } - if (schema.AnyOf?.Count != 0) + if (schema.AnyOf is { Count: > 0}) { return TraverseSchemaElements(discriminatorName, schema.AnyOf); } - if (schema.AllOf?.Count != 0) + if (schema.AllOf is { Count: > 0}) { return TraverseSchemaElements(discriminatorName, schema.AllOf); } @@ -102,25 +108,26 @@ public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema /// between other schemas which may satisfy the payload description. /// The child schema. /// + [Obsolete("This method will be made private in future versions.")] + [Browsable(false)] public static bool TraverseSchemaElements(string discriminatorName, IList? childSchema) { - if (childSchema is not null) + if (childSchema is null) { - foreach (var childItem in childSchema) + return false; + } + foreach (var childItem in childSchema) + { + if ((!childItem.Properties?.ContainsKey(discriminatorName) ?? false) && + (!childItem.Required?.Contains(discriminatorName) ?? false)) { - if ((!childItem.Properties?.ContainsKey(discriminatorName) ?? false) && - (!childItem.Required?.Contains(discriminatorName) ?? false)) - { - return ValidateChildSchemaAgainstDiscriminator(childItem, discriminatorName); - } - else - { - return true; - } + return ValidateChildSchemaAgainstDiscriminator(childItem, discriminatorName); } - return false; - } - + else + { + return true; + } + } return false; } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 1446cb8d7..6a8ad3955 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1352,7 +1352,11 @@ namespace Microsoft.OpenApi { public static Microsoft.OpenApi.ValidationRule ValidateSchemaDiscriminator { get; } public static Microsoft.OpenApi.ValidationRule ValidateSchemaPropertyHasValue { get; } + [System.ComponentModel.Browsable(false)] + [System.Obsolete("This method will be made private in future versions.")] public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList? childSchema) { } + [System.ComponentModel.Browsable(false)] + [System.Obsolete("This method will be made private in future versions.")] public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.IOpenApiSchema schema, string? discriminatorName) { } } public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiSerializable diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs index f22806825..fdf36e0b4 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs @@ -246,7 +246,7 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD } [Fact] - public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminator() + public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminatorOneOf() { // Arrange var components = new OpenApiComponents @@ -293,5 +293,102 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim //Assert Assert.Empty(errors); } + + [Fact] + public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminatorAnyOf() + { + // Arrange + var components = new OpenApiComponents + { + Schemas = new Dictionary + { + { + "Person", + new OpenApiSchema + { + Type = JsonSchemaType.Array, + Discriminator = new() + { + PropertyName = "type" + }, + AnyOf = + [ + new OpenApiSchema() + { + Properties = new Dictionary + { + { + "type", + new OpenApiSchema + { + Type = JsonSchemaType.Array + } + } + }, + } + ], + } + } + } + }; + + // Act + var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); + var walker = new OpenApiWalker(validator); + walker.Walk(components); + + var errors = validator.Errors; + + //Assert + Assert.Empty(errors); + } + [Fact] + public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminatorAllOf() + { + // Arrange + var components = new OpenApiComponents + { + Schemas = new Dictionary + { + { + "Person", + new OpenApiSchema + { + Type = JsonSchemaType.Array, + Discriminator = new() + { + PropertyName = "type" + }, + AllOf = + [ + new OpenApiSchema() + { + Properties = new Dictionary + { + { + "type", + new OpenApiSchema + { + Type = JsonSchemaType.Array + } + } + }, + } + ], + } + } + } + }; + + // Act + var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); + var walker = new OpenApiWalker(validator); + walker.Walk(components); + + var errors = validator.Errors; + + //Assert + Assert.Empty(errors); + } } } From 7def73d774d1f0e96118e92b636e52cbea371f2d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 19 Jan 2026 11:15:25 -0500 Subject: [PATCH 04/18] fix: discriminator property validation fails any/allOf cases when it shouldn't Signed-off-by: Vincent Biret --- .../Validations/Rules/OpenApiSchemaRules.cs | 41 ++++---- .../PublicApi/PublicApi.approved.txt | 4 + .../OpenApiSchemaValidationTests.cs | 99 ++++++++++++++++++- 3 files changed, 126 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs index 70d558a13..4f2a122a9 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs @@ -5,6 +5,8 @@ namespace Microsoft.OpenApi { + using System; + using System.ComponentModel; using System.Linq; /// @@ -48,6 +50,7 @@ public static class OpenApiSchemaRules { var discriminatorName = schema.Discriminator?.PropertyName; +#pragma warning disable CS0618 // Type or member is obsolete if (!ValidateChildSchemaAgainstDiscriminator(schema, discriminatorName)) { context.Enter("discriminator"); @@ -56,6 +59,7 @@ public static class OpenApiSchemaRules schema is OpenApiSchemaReference { Reference: not null} schemaReference ? schemaReference.Reference.Id : string.Empty, discriminatorName)); context.Exit(); } +#pragma warning restore CS0618 // Type or member is obsolete } }); @@ -65,6 +69,8 @@ public static class OpenApiSchemaRules /// The parent schema. /// Adds support for polymorphism. The discriminator is an object name that is used to differentiate /// between other schemas which may satisfy the payload description. + [Obsolete("This method will be made private in future versions.")] + [Browsable(false)] public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema, string? discriminatorName) { if (discriminatorName is not null) @@ -72,15 +78,15 @@ public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema if (schema.Required is null || !schema.Required.Contains(discriminatorName)) { // recursively check nested schema.OneOf, schema.AnyOf or schema.AllOf and their required fields for the discriminator - if (schema.OneOf?.Count != 0) + if (schema.OneOf is { Count: > 0}) { return TraverseSchemaElements(discriminatorName, schema.OneOf); } - if (schema.AnyOf?.Count != 0) + if (schema.AnyOf is { Count: > 0}) { return TraverseSchemaElements(discriminatorName, schema.AnyOf); } - if (schema.AllOf?.Count != 0) + if (schema.AllOf is { Count: > 0}) { return TraverseSchemaElements(discriminatorName, schema.AllOf); } @@ -102,25 +108,26 @@ public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema /// between other schemas which may satisfy the payload description. /// The child schema. /// + [Obsolete("This method will be made private in future versions.")] + [Browsable(false)] public static bool TraverseSchemaElements(string discriminatorName, IList? childSchema) { - if (childSchema is not null) + if (childSchema is null) { - foreach (var childItem in childSchema) + return false; + } + foreach (var childItem in childSchema) + { + if ((!childItem.Properties?.ContainsKey(discriminatorName) ?? false) && + (!childItem.Required?.Contains(discriminatorName) ?? false)) { - if ((!childItem.Properties?.ContainsKey(discriminatorName) ?? false) && - (!childItem.Required?.Contains(discriminatorName) ?? false)) - { - return ValidateChildSchemaAgainstDiscriminator(childItem, discriminatorName); - } - else - { - return true; - } + return ValidateChildSchemaAgainstDiscriminator(childItem, discriminatorName); } - return false; - } - + else + { + return true; + } + } return false; } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 39cfb8ccc..d0b8989ef 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1261,7 +1261,11 @@ namespace Microsoft.OpenApi { public static Microsoft.OpenApi.ValidationRule ValidateSchemaDiscriminator { get; } public static Microsoft.OpenApi.ValidationRule ValidateSchemaPropertyHasValue { get; } + [System.ComponentModel.Browsable(false)] + [System.Obsolete("This method will be made private in future versions.")] public static bool TraverseSchemaElements(string discriminatorName, System.Collections.Generic.IList? childSchema) { } + [System.ComponentModel.Browsable(false)] + [System.Obsolete("This method will be made private in future versions.")] public static bool ValidateChildSchemaAgainstDiscriminator(Microsoft.OpenApi.IOpenApiSchema schema, string? discriminatorName) { } } public class OpenApiSecurityRequirement : System.Collections.Generic.Dictionary>, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiSerializable diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs index f22806825..fdf36e0b4 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiSchemaValidationTests.cs @@ -246,7 +246,7 @@ public void ValidateSchemaRequiredFieldListMustContainThePropertySpecifiedInTheD } [Fact] - public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminator() + public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminatorOneOf() { // Arrange var components = new OpenApiComponents @@ -293,5 +293,102 @@ public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscrim //Assert Assert.Empty(errors); } + + [Fact] + public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminatorAnyOf() + { + // Arrange + var components = new OpenApiComponents + { + Schemas = new Dictionary + { + { + "Person", + new OpenApiSchema + { + Type = JsonSchemaType.Array, + Discriminator = new() + { + PropertyName = "type" + }, + AnyOf = + [ + new OpenApiSchema() + { + Properties = new Dictionary + { + { + "type", + new OpenApiSchema + { + Type = JsonSchemaType.Array + } + } + }, + } + ], + } + } + } + }; + + // Act + var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); + var walker = new OpenApiWalker(validator); + walker.Walk(components); + + var errors = validator.Errors; + + //Assert + Assert.Empty(errors); + } + [Fact] + public void ValidateOneOfSchemaPropertyNameContainsPropertySpecifiedInTheDiscriminatorAllOf() + { + // Arrange + var components = new OpenApiComponents + { + Schemas = new Dictionary + { + { + "Person", + new OpenApiSchema + { + Type = JsonSchemaType.Array, + Discriminator = new() + { + PropertyName = "type" + }, + AllOf = + [ + new OpenApiSchema() + { + Properties = new Dictionary + { + { + "type", + new OpenApiSchema + { + Type = JsonSchemaType.Array + } + } + }, + } + ], + } + } + } + }; + + // Act + var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); + var walker = new OpenApiWalker(validator); + walker.Walk(components); + + var errors = validator.Errors; + + //Assert + Assert.Empty(errors); + } } } From 62e7d56ac0863875999240d68a2766d2cc2d594c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 19 Jan 2026 13:13:05 -0500 Subject: [PATCH 05/18] feat: hidi validate command now logs warnings Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 48f1d1c3e..a494b4f2e 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -398,6 +398,7 @@ private static async Task ParseOpenApiAsync(string openApiFile, bool logger.LogTrace("{Timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds); LogErrors(logger, result); + LogWarnings(logger, result); stopwatch.Stop(); } @@ -652,7 +653,7 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl private static void LogErrors(ILogger logger, ReadResult result) { var context = result.Diagnostic; - if (context is not null && context.Errors.Count != 0) + if (context is { Errors.Count: > 0 }) { using (logger.BeginScope("Detected errors")) { @@ -664,6 +665,21 @@ private static void LogErrors(ILogger logger, ReadResult result) } } + private static void LogWarnings(ILogger logger, ReadResult result) + { + var context = result.Diagnostic; + if (context is { Warnings.Count: > 0 }) + { + using (logger.BeginScope("Detected warnings")) + { + foreach (var warning in context.Warnings) + { + logger.LogWarning("Detected warning during parsing: {Warning}", warning.ToString()); + } + } + } + } + internal static void WriteTreeDocumentAsMarkdown(string openapiUrl, OpenApiDocument document, StreamWriter writer) { var rootNode = OpenApiUrlTreeNode.Create(document, "main"); From 18ed5acce9661639e1698f19c194e520eb5c93c1 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 19 Jan 2026 13:13:05 -0500 Subject: [PATCH 06/18] feat: hidi validate command now logs warnings Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 797ec2359..b35cc2cbb 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -398,6 +398,7 @@ private static async Task ParseOpenApiAsync(string openApiFile, bool logger.LogTrace("{Timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds); LogErrors(logger, result); + LogWarnings(logger, result); stopwatch.Stop(); } @@ -652,7 +653,7 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl private static void LogErrors(ILogger logger, ReadResult result) { var context = result.Diagnostic; - if (context is not null && context.Errors.Count != 0) + if (context is { Errors.Count: > 0 }) { using (logger.BeginScope("Detected errors")) { @@ -664,6 +665,21 @@ private static void LogErrors(ILogger logger, ReadResult result) } } + private static void LogWarnings(ILogger logger, ReadResult result) + { + var context = result.Diagnostic; + if (context is { Warnings.Count: > 0 }) + { + using (logger.BeginScope("Detected warnings")) + { + foreach (var warning in context.Warnings) + { + logger.LogWarning("Detected warning during parsing: {Warning}", warning.ToString()); + } + } + } + } + internal static void WriteTreeDocumentAsMarkdown(string openapiUrl, OpenApiDocument document, StreamWriter writer) { var rootNode = OpenApiUrlTreeNode.Create(document, "main"); From 686ca47a0c533cde12f51ef55c843a6c85cf8b7a Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 19 Jan 2026 13:26:59 -0500 Subject: [PATCH 07/18] docs: adds missing mention of references resolution in the upgrade guide Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 14eaacdf0..752b60c95 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -32,7 +32,7 @@ One of the key features of OpenAPI.NET is its performance. This version makes it In v1, instances of `$ref` were resolved in a second pass of the document to ensure the target of the reference has been parsed before attempting to resolve it. In v2, reference targets are lazily resolved when reference objects are accessed. This improves load time performance for documents that make heavy use of references. -[How does this change the behavior of external references?] +Because references are lazily loaded and depend on the workspace context, loading a document with unresolved references (internal or external) does not lead to an exception being thrown anymore. Instead warnings are logged in the diagnostics object. This gives you an opportunity to load additional documents in the workspace if needed, [more information](#component-registration-in-a-documents-workspace). ### Results From f09ce7915b3a43d18b68a9d155d2a838a71833fc Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 18:59:57 +0000 Subject: [PATCH 08/18] chore(support/v2): release 2.5.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 14 ++++++++++++++ Directory.Build.props | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2b7962cdd..4dedeaebc 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.4.3" + ".": "2.5.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 457ff02e5..3098a8f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.5.0](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.3...v2.5.0) (2026-01-19) + + +### Features + +* hidi validate command now logs warnings ([1d3d085](https://github.com/microsoft/OpenAPI.NET/commit/1d3d085e0278d9341d7bd10065eba584cb25773c)) +* hidi validate command now logs warnings ([18ed5ac](https://github.com/microsoft/OpenAPI.NET/commit/18ed5acce9661639e1698f19c194e520eb5c93c1)) + + +### Bug Fixes + +* discriminator property validation fails any/allOf cases when it shouldn't ([ff6e411](https://github.com/microsoft/OpenAPI.NET/commit/ff6e4115dcab8c893bbc6b97639fd620b50f105e)) +* discriminator property validation fails any/allOf cases when it shouldn't ([7def73d](https://github.com/microsoft/OpenAPI.NET/commit/7def73d774d1f0e96118e92b636e52cbea371f2d)) + ## [2.4.3](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.2...v2.4.3) (2026-01-16) diff --git a/Directory.Build.props b/Directory.Build.props index 7b6a763dc..a4b8c77a1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,7 +12,7 @@ https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET - 2.4.3 + 2.5.0 From b0dbb301261a50a0ebe8e47b7680739cd6d024f4 Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 19:00:33 +0000 Subject: [PATCH 09/18] chore(main): release 3.2.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 14 ++++++++++++++ Directory.Build.props | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 534c8ff8b..1f73031b8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.1.3" + ".": "3.2.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 44e6eba95..a863b9118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [3.2.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.1.3...v3.2.0) (2026-01-19) + + +### Features + +* hidi validate command now logs warnings ([76a3c0f](https://github.com/microsoft/OpenAPI.NET/commit/76a3c0fe33a6c953263d9d91669b2f1bab562a79)) +* hidi validate command now logs warnings ([62e7d56](https://github.com/microsoft/OpenAPI.NET/commit/62e7d56ac0863875999240d68a2766d2cc2d594c)) + + +### Bug Fixes + +* discriminator property validation fails any/allOf cases when it shouldn't ([fb6cecc](https://github.com/microsoft/OpenAPI.NET/commit/fb6cecccafd5713bc1eb22e0cf07619cf495ebb5)) +* discriminator property validation fails any/allOf cases when it shouldn't ([a8fb81c](https://github.com/microsoft/OpenAPI.NET/commit/a8fb81cf9524a3f2f721aa808db244434e1cd177)) + ## [3.1.3](https://github.com/microsoft/OpenAPI.NET/compare/v3.1.2...v3.1.3) (2026-01-16) diff --git a/Directory.Build.props b/Directory.Build.props index b0681cf72..028c4e6c5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,7 +12,7 @@ https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET - 3.1.3 + 3.2.0 From a4efdfe43ee310fba4bb643d9fd28ce92da32338 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 21 Jan 2026 07:41:01 -0800 Subject: [PATCH 10/18] Support mutualTLS security scheme type (#2696) feat(models): support mutualTLS security scheme * fix(writers): throw for mutualTLS in OAS 3.0 --- .../Models/OpenApiSecurityScheme.cs | 16 ++++++++++++++++ .../Models/SecuritySchemeType.cs | 7 ++++++- .../V32Tests/OpenApiSecuritySchemeTests.cs | 19 +++++++++++++++++++ .../mutualTlsSecurityScheme.yaml | 2 ++ .../Models/OpenApiSecuritySchemeTests.cs | 19 +++++++++++++++++++ .../PublicApi/PublicApi.approved.txt | 2 ++ 6 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index 4bee59619..57603e0aa 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -126,6 +126,14 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version // openIdConnectUrl writer.WriteProperty(OpenApiConstants.OpenIdConnectUrl, OpenIdConnectUrl?.ToString()); break; + case SecuritySchemeType.MutualTLS: + // No additional properties for mutualTLS + if (version < OpenApiSpecVersion.OpenApi3_1) + { + // mutualTLS is introduced in OpenAPI 3.1 + throw new OpenApiException($"mutualTLS security scheme is only supported in OpenAPI 3.1 and later versions. Current version: {version}"); + } + break; } // deprecated - serialize as native field for v3.2+ or as extension for earlier versions @@ -170,6 +178,14 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) return; } + if (Type == SecuritySchemeType.MutualTLS) + { + // Bail because V2 does not support mutualTLS + writer.WriteStartObject(); + writer.WriteEndObject(); + return; + } + writer.WriteStartObject(); // type diff --git a/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs b/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs index 6c304597a..5640caa9a 100644 --- a/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs +++ b/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs @@ -26,6 +26,11 @@ public enum SecuritySchemeType /// /// Use OAuth2 with OpenId Connect URL to discover OAuth2 configuration value. /// - [Display("openIdConnect")] OpenIdConnect + [Display("openIdConnect")] OpenIdConnect, + + /// + /// Use mutual TLS authentication. + /// + [Display("mutualTLS")] MutualTLS } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V32Tests/OpenApiSecuritySchemeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V32Tests/OpenApiSecuritySchemeTests.cs index e053d7405..ea0937237 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V32Tests/OpenApiSecuritySchemeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V32Tests/OpenApiSecuritySchemeTests.cs @@ -102,6 +102,25 @@ public async Task ParseOpenIdConnectSecuritySchemeShouldSucceed() }, securityScheme); } + [Fact] + public async Task ParseMutualTlsSecuritySchemeShouldSucceed() + { + // Act + var securityScheme = await OpenApiModelFactory.LoadAsync( + Path.Combine(SampleFolderPath, "mutualTlsSecurityScheme.yaml"), + OpenApiSpecVersion.OpenApi3_2, + new(), + SettingsFixture.ReaderSettings); + + // Assert + Assert.Equivalent( + new OpenApiSecurityScheme + { + Type = SecuritySchemeType.MutualTLS, + Description = "Sample Description" + }, securityScheme); + } + [Fact] public async Task ParseOAuth2SecuritySchemeWithDeviceAuthorizationUrlShouldSucceed() { diff --git a/test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml b/test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml new file mode 100644 index 000000000..72b4e9ae8 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml @@ -0,0 +1,2 @@ +type: mutualTLS +description: Sample Description diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs index 1432d07cc..cd8499b9f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs @@ -101,6 +101,12 @@ public class OpenApiSecuritySchemeTests OpenIdConnectUrl = new("https://example.com/openIdConnect") }; + private static OpenApiSecurityScheme MutualTlsSecurityScheme => new() + { + Description = "description1", + Type = SecuritySchemeType.MutualTLS + }; + private static OpenApiSecuritySchemeReference OpenApiSecuritySchemeReference => new("sampleSecurityScheme"); private static OpenApiSecurityScheme ReferencedSecurityScheme => new() { @@ -208,6 +214,19 @@ public async Task SerializeHttpBearerSecuritySchemeAsV3JsonWorks() Assert.Equal(expected, actual); } + [Fact] + public void SerializeMutualTlsSecuritySchemeAsV3Throws() + { + // Arrange + var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); + var writer = new OpenApiJsonWriter(outputStringWriter); + + // Act & Assert + var exception = Assert.Throws(() => MutualTlsSecurityScheme.SerializeAsV3(writer)); + Assert.Contains("mutualTLS security scheme is only supported in OpenAPI 3.1 and later versions", exception.Message); + Assert.Contains($"Current version: {OpenApiSpecVersion.OpenApi3_0}", exception.Message); + } + [Fact] public async Task SerializeOAuthSingleFlowSecuritySchemeAsV3JsonWorks() { diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 6a8ad3955..59f1bce31 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1933,6 +1933,8 @@ namespace Microsoft.OpenApi OAuth2 = 2, [Microsoft.OpenApi.Display("openIdConnect")] OpenIdConnect = 3, + [Microsoft.OpenApi.Display("mutualTLS")] + MutualTLS = 4, } public abstract class SourceExpression : Microsoft.OpenApi.RuntimeExpression { From f9cf5b807d71c49e5bd7e2bec97f12d3b50ca180 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 21 Jan 2026 07:41:01 -0800 Subject: [PATCH 11/18] Support mutualTLS security scheme type (#2696) feat(models): support mutualTLS security scheme * fix(writers): throw for mutualTLS in OAS 3.0 --- .../Models/OpenApiSecurityScheme.cs | 16 ++++++++++++++++ .../Models/SecuritySchemeType.cs | 7 ++++++- .../mutualTlsSecurityScheme.yaml | 2 ++ .../Models/OpenApiSecuritySchemeTests.cs | 19 +++++++++++++++++++ .../PublicApi/PublicApi.approved.txt | 2 ++ 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs index 7d82f3219..50c2ba545 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs @@ -115,6 +115,14 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version // openIdConnectUrl writer.WriteProperty(OpenApiConstants.OpenIdConnectUrl, OpenIdConnectUrl?.ToString()); break; + case SecuritySchemeType.MutualTLS: + // No additional properties for mutualTLS + if (version < OpenApiSpecVersion.OpenApi3_1) + { + // mutualTLS is introduced in OpenAPI 3.1 + throw new OpenApiException($"mutualTLS security scheme is only supported in OpenAPI 3.1 and later versions. Current version: {version}"); + } + break; } // extensions @@ -146,6 +154,14 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) return; } + if (Type == SecuritySchemeType.MutualTLS) + { + // Bail because V2 does not support mutualTLS + writer.WriteStartObject(); + writer.WriteEndObject(); + return; + } + writer.WriteStartObject(); // type diff --git a/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs b/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs index 6c304597a..5640caa9a 100644 --- a/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs +++ b/src/Microsoft.OpenApi/Models/SecuritySchemeType.cs @@ -26,6 +26,11 @@ public enum SecuritySchemeType /// /// Use OAuth2 with OpenId Connect URL to discover OAuth2 configuration value. /// - [Display("openIdConnect")] OpenIdConnect + [Display("openIdConnect")] OpenIdConnect, + + /// + /// Use mutual TLS authentication. + /// + [Display("mutualTLS")] MutualTLS } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml b/test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml new file mode 100644 index 000000000..72b4e9ae8 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V32Tests/Samples/OpenApiSecurityScheme/mutualTlsSecurityScheme.yaml @@ -0,0 +1,2 @@ +type: mutualTLS +description: Sample Description diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs index 1415d62a1..0b69e9de7 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecuritySchemeTests.cs @@ -100,6 +100,12 @@ public class OpenApiSecuritySchemeTests OpenIdConnectUrl = new("https://example.com/openIdConnect") }; + private static OpenApiSecurityScheme MutualTlsSecurityScheme => new() + { + Description = "description1", + Type = SecuritySchemeType.MutualTLS + }; + private static OpenApiSecuritySchemeReference OpenApiSecuritySchemeReference => new("sampleSecurityScheme"); private static OpenApiSecurityScheme ReferencedSecurityScheme => new() { @@ -198,6 +204,19 @@ public async Task SerializeHttpBearerSecuritySchemeAsV3JsonWorks() Assert.Equal(expected, actual); } + [Fact] + public void SerializeMutualTlsSecuritySchemeAsV3Throws() + { + // Arrange + var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); + var writer = new OpenApiJsonWriter(outputStringWriter); + + // Act & Assert + var exception = Assert.Throws(() => MutualTlsSecurityScheme.SerializeAsV3(writer)); + Assert.Contains("mutualTLS security scheme is only supported in OpenAPI 3.1 and later versions", exception.Message); + Assert.Contains($"Current version: {OpenApiSpecVersion.OpenApi3_0}", exception.Message); + } + [Fact] public async Task SerializeOAuthSingleFlowSecuritySchemeAsV3JsonWorks() { diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index d0b8989ef..fc0b3db73 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1808,6 +1808,8 @@ namespace Microsoft.OpenApi OAuth2 = 2, [Microsoft.OpenApi.Display("openIdConnect")] OpenIdConnect = 3, + [Microsoft.OpenApi.Display("mutualTLS")] + MutualTLS = 4, } public abstract class SourceExpression : Microsoft.OpenApi.RuntimeExpression { From 9e13b2574e68387ecc01c453b571208c40124b46 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 21 Jan 2026 08:32:08 -0800 Subject: [PATCH 12/18] feat(models): add shared Content interface (#2695) feat(models): add shared Content interface * Update src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs Co-authored-by: Vincent Biret * Update src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs Co-authored-by: Vincent Biret * Update src/Microsoft.OpenApi/Models/OpenApiHeader.cs Co-authored-by: Vincent Biret * Update src/Microsoft.OpenApi/Models/OpenApiResponse.cs Co-authored-by: Vincent Biret * Remove inheritance from IOpenApiReadOnlyContentElement revert commit 7758a8193a391629d82995881763bba3911b767e * Update src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs Co-authored-by: Vincent Biret * test(publicapi): approve content interface surface --------- Co-authored-by: Vincent Biret --- .../Interfaces/IOpenApiContentElement.cs | 27 ++++++++++++++ .../Models/Interfaces/IOpenApiHeader.cs | 7 +--- .../Models/Interfaces/IOpenApiParameter.cs | 13 +------ .../Models/Interfaces/IOpenApiRequestBody.cs | 7 +--- .../Models/Interfaces/IOpenApiResponse.cs | 8 +---- src/Microsoft.OpenApi/Models/OpenApiHeader.cs | 7 ++-- .../Models/OpenApiParameter.cs | 21 +++++++---- .../Models/OpenApiRequestBody.cs | 19 +++++----- .../Models/OpenApiResponse.cs | 6 ++-- .../PublicApi/PublicApi.approved.txt | 36 ++++++++++--------- 10 files changed, 84 insertions(+), 67 deletions(-) create mode 100644 src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs new file mode 100644 index 000000000..15725d4fc --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace Microsoft.OpenApi; + +/// +/// Describes an element that has content. +/// +public interface IOpenApiContentElement +{ + /// + /// A map containing descriptions of potential payloads. + /// The key is a media type or media type range and the value describes it. + /// + IDictionary? Content { get; set; } +} + +/// +/// Describes an element that has content. +/// +public interface IOpenApiReadOnlyContentElement +{ + /// + /// A map containing descriptions of potential payloads. + /// The key is a media type or media type range and the value describes it. + /// + IDictionary? Content { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs index 55e484555..8104c72ed 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the headers object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable +public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement { /// /// Determines whether this header is mandatory. @@ -58,9 +58,4 @@ public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExte /// public IDictionary? Examples { get; } - /// - /// A map containing the representations for the header. - /// - public IDictionary? Content { get; } - } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs index 5669a0bb3..405d04fab 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs @@ -7,7 +7,7 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the parameter object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable +public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement { /// /// REQUIRED. The name of the parameter. Parameter names are case sensitive. @@ -93,15 +93,4 @@ public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyE /// Assign to use get null as a serialized value. /// public JsonNode? Example { get; } - - /// - /// A map containing the representations for the parameter. - /// The key is the media type and the value describes it. - /// The map MUST only contain one entry. - /// For more complex scenarios, the content property can define the media type and schema of the parameter. - /// A parameter MUST contain either a schema property, or a content property, but not both. - /// When example or examples are provided in conjunction with the schema object, - /// the example MUST follow the prescribed serialization strategy for the parameter. - /// - public IDictionary? Content { get; } } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs index 5ab2f7174..2e722b0f5 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs @@ -6,18 +6,13 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the request body object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable +public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement { /// /// Determines if the request body is required in the request. Defaults to false. /// public bool Required { get; } - /// - /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. - /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* - /// - public IDictionary? Content { get; } /// /// Converts the request body to a body parameter in preparation for a v2 serialization. /// diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs index d0423771f..6823868f2 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs @@ -6,19 +6,13 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the response object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiSummarizedElement +public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiSummarizedElement, IOpenApiReadOnlyContentElement { /// /// Maps a header name to its definition. /// public IDictionary? Headers { get; } - /// - /// A map containing descriptions of potential response payloads. - /// The key is a media type or media type range and the value describes it. - /// - public IDictionary? Content { get; } - /// /// A map of operations links that can be followed from the response. /// The key of the map is a short name for the link, diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index 7e5ea273f..9ec42aa06 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -11,7 +11,7 @@ namespace Microsoft.OpenApi /// Header Object. /// The Header Object follows the structure of the Parameter Object. /// - public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible + public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible, IOpenApiContentElement { /// public string? Description { get; set; } @@ -98,7 +98,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -175,7 +175,8 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - var targetSchema = Schema switch { + var targetSchema = Schema switch + { OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget, OpenApiSchema schema => schema, _ => null, diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index d6b060a78..14294cbd8 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -11,7 +11,7 @@ namespace Microsoft.OpenApi /// /// Parameter Object. /// - public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter + public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter, IOpenApiContentElement { private bool? _explode; private ParameterStyle? _style; @@ -60,7 +60,15 @@ public bool Explode /// public JsonNode? Example { get; set; } - /// + /// + /// A map containing the representations for the parameter. + /// The key is the media type and the value describes it. + /// The map MUST only contain one entry. + /// For more complex scenarios, the content property can define the media type and schema of the parameter. + /// A parameter MUST contain either a schema property, or a content property, but not both. + /// When example or examples are provided in conjunction with the schema object, + /// the example MUST follow the prescribed serialization strategy for the parameter. + /// public IDictionary? Content { get; set; } /// @@ -111,11 +119,11 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); - + // Validate that Cookie style is only used in OpenAPI 3.2 and later if (Style == ParameterStyle.Cookie && version < OpenApiSpecVersion.OpenApi3_2) { @@ -226,7 +234,8 @@ internal virtual void WriteRequestBodySchemaForV2(IOpenApiWriter writer, Diction // uniqueItems // enum // multipleOf - var targetSchema = Schema switch { + var targetSchema = Schema switch + { OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget, OpenApiSchema schema => schema, _ => null, @@ -271,7 +280,7 @@ internal virtual void WriteRequestBodySchemaForV2(IOpenApiWriter writer, Diction public virtual void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); - + // Validate that Cookie style is only used in OpenAPI 3.2 and later if (Style == ParameterStyle.Cookie) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index fa29d3ea0..225837544 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -10,7 +10,7 @@ namespace Microsoft.OpenApi /// /// Request Body Object /// - public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody + public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody, IOpenApiContentElement { /// public string? Description { get; set; } @@ -18,7 +18,10 @@ public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody /// public bool Required { get; set; } - /// + /// + /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. + /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* + /// public IDictionary? Content { get; set; } /// @@ -64,7 +67,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { @@ -110,7 +113,7 @@ public IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) Extensions = Extensions?.ToDictionary(static k => k.Key, static v => v.Value) }; // Clone extensions so we can remove the x-bodyName extensions from the output V2 model. - if (bodyParameter.Extensions is not null && + if (bodyParameter.Extensions is not null && bodyParameter.Extensions.TryGetValue(OpenApiConstants.BodyName, out var bodyNameExtension) && bodyNameExtension is JsonNodeExtension bodyName) { @@ -126,7 +129,7 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter if (Content == null || !Content.Any()) yield break; var properties = Content.First().Value.Schema?.Properties; - if(properties != null) + if (properties != null) { foreach (var property in properties) { @@ -144,11 +147,11 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter OpenApiSchemaReference => throw new InvalidOperationException("Unresolved reference target"), _ => throw new InvalidOperationException("Unexpected schema type") }; - + updatedSchema.Type = "file".ToJsonSchemaType(); updatedSchema.Format = null; paramSchema = updatedSchema; - + } yield return new OpenApiFormDataParameter() { @@ -159,7 +162,7 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter Required = Content.First().Value.Schema?.Required?.Contains(property.Key) ?? false }; } - } + } } /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 4ee39336e..6cc0000df 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -10,7 +10,7 @@ namespace Microsoft.OpenApi /// /// Response object. /// - public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse + public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse, IOpenApiContentElement { /// public string? Summary { get; set; } @@ -73,7 +73,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -177,7 +177,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) // so remove it from the cloned collection so we don't write it again. extensionsClone?.Remove(key); } - } + } } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 59f1bce31..5413879c0 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -109,6 +109,10 @@ namespace Microsoft.OpenApi { System.Collections.Generic.Dictionary? PathItems { get; } } + public interface IOpenApiContentElement + { + System.Collections.Generic.IDictionary? Content { get; set; } + } public interface IOpenApiDescribedElement : Microsoft.OpenApi.IOpenApiElement { string? Description { get; set; } @@ -129,11 +133,10 @@ namespace Microsoft.OpenApi { void Write(Microsoft.OpenApi.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion specVersion); } - public interface IOpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { bool AllowEmptyValue { get; } bool AllowReserved { get; } - System.Collections.Generic.IDictionary? Content { get; } bool Deprecated { get; } System.Text.Json.Nodes.JsonNode? Example { get; } System.Collections.Generic.IDictionary? Examples { get; } @@ -160,11 +163,10 @@ namespace Microsoft.OpenApi System.Collections.Generic.IList? PrefixEncoding { get; } Microsoft.OpenApi.IOpenApiSchema? Schema { get; } } - public interface IOpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { bool AllowEmptyValue { get; } bool AllowReserved { get; } - System.Collections.Generic.IDictionary? Content { get; } bool Deprecated { get; } System.Text.Json.Nodes.JsonNode? Example { get; } System.Collections.Generic.IDictionary? Examples { get; } @@ -181,6 +183,10 @@ namespace Microsoft.OpenApi System.Collections.Generic.IList? Parameters { get; } System.Collections.Generic.IList? Servers { get; } } + public interface IOpenApiReadOnlyContentElement + { + System.Collections.Generic.IDictionary? Content { get; } + } public interface IOpenApiReadOnlyDescribedElement : Microsoft.OpenApi.IOpenApiElement { string? Description { get; } @@ -214,16 +220,14 @@ namespace Microsoft.OpenApi U CopyReferenceAsTargetElementWithOverrides(U source); } public interface IOpenApiReferenceable : Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiSerializable { } - public interface IOpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { - System.Collections.Generic.IDictionary? Content { get; } bool Required { get; } Microsoft.OpenApi.IOpenApiParameter? ConvertToBodyParameter(Microsoft.OpenApi.IOpenApiWriter writer); System.Collections.Generic.IEnumerable? ConvertToFormDataParameters(Microsoft.OpenApi.IOpenApiWriter writer); } - public interface IOpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable { - System.Collections.Generic.IDictionary? Content { get; } System.Collections.Generic.IDictionary? Headers { get; } System.Collections.Generic.IDictionary? Links { get; } } @@ -787,7 +791,7 @@ namespace Microsoft.OpenApi public static Microsoft.OpenApi.OpenApiUrlTreeNode CreateOpenApiUrlTreeNode(System.Collections.Generic.Dictionary sources) { } public static System.Func CreatePredicate(string? operationIds = null, string? tags = null, System.Collections.Generic.Dictionary>? requestUrls = null, Microsoft.OpenApi.OpenApiDocument? source = null) { } } - public class OpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiHeader : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiHeader() { } public bool AllowEmptyValue { get; set; } @@ -808,7 +812,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiHeaderReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiHeaderReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public bool AllowEmptyValue { get; } @@ -1023,7 +1027,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiParameter : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiParameter() { } public bool AllowEmptyValue { get; set; } @@ -1046,7 +1050,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiParameterReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiParameterReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiParameterReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public bool AllowEmptyValue { get; } @@ -1151,7 +1155,7 @@ namespace Microsoft.OpenApi protected override void SerializeAdditionalV32Properties(Microsoft.OpenApi.IOpenApiWriter writer) { } protected override void SetAdditional31MetadataFromMapNode(System.Text.Json.Nodes.JsonObject jsonObject) { } } - public class OpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiRequestBody : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiRequestBody() { } public System.Collections.Generic.IDictionary? Content { get; set; } @@ -1166,7 +1170,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiRequestBodyReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiRequestBodyReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiRequestBodyReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public System.Collections.Generic.IDictionary? Content { get; } @@ -1180,7 +1184,7 @@ namespace Microsoft.OpenApi public Microsoft.OpenApi.IOpenApiRequestBody CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable + public class OpenApiResponse : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable { public OpenApiResponse() { } public System.Collections.Generic.IDictionary? Content { get; set; } @@ -1195,7 +1199,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiResponseReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable + public class OpenApiResponseReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable { public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public System.Collections.Generic.IDictionary? Content { get; } From 069f8432788b2ac1dca3d27b07f4e68b40f53c46 Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:32:59 +0000 Subject: [PATCH 13/18] chore(main): release 3.3.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ Directory.Build.props | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1f73031b8..ff1c7af58 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.2.0" + ".": "3.3.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a863b9118..8855d4438 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [3.3.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.2.0...v3.3.0) (2026-01-21) + + +### Features + +* **models:** add shared Content interface ([9e13b25](https://github.com/microsoft/OpenAPI.NET/commit/9e13b2574e68387ecc01c453b571208c40124b46)) +* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([9e13b25](https://github.com/microsoft/OpenAPI.NET/commit/9e13b2574e68387ecc01c453b571208c40124b46)) +* **models:** support mutualTLS security scheme ([a4efdfe](https://github.com/microsoft/OpenAPI.NET/commit/a4efdfe43ee310fba4bb643d9fd28ce92da32338)) + ## [3.2.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.1.3...v3.2.0) (2026-01-19) diff --git a/Directory.Build.props b/Directory.Build.props index 028c4e6c5..36284217c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,7 +12,7 @@ https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET - 3.2.0 + 3.3.0 From 80e4bbfa4ab31d3af69fe29751714d001c1f9566 Mon Sep 17 00:00:00 2001 From: mdaneri Date: Wed, 21 Jan 2026 08:32:08 -0800 Subject: [PATCH 14/18] feat(models): add shared Content interface (#2695) feat(models): add shared Content interface * Update src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs Co-authored-by: Vincent Biret * Update src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs Co-authored-by: Vincent Biret * Update src/Microsoft.OpenApi/Models/OpenApiHeader.cs Co-authored-by: Vincent Biret * Update src/Microsoft.OpenApi/Models/OpenApiResponse.cs Co-authored-by: Vincent Biret * Remove inheritance from IOpenApiReadOnlyContentElement revert commit 7758a8193a391629d82995881763bba3911b767e * Update src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs Co-authored-by: Vincent Biret * test(publicapi): approve content interface surface --------- Co-authored-by: Vincent Biret Signed-off-by: Vincent Biret --- .../Interfaces/IOpenApiContentElement.cs | 27 ++++++++++++++ .../Models/Interfaces/IOpenApiHeader.cs | 8 +---- .../Models/Interfaces/IOpenApiParameter.cs | 13 +------ .../Models/Interfaces/IOpenApiRequestBody.cs | 7 +--- .../Models/Interfaces/IOpenApiResponse.cs | 8 +---- src/Microsoft.OpenApi/Models/OpenApiHeader.cs | 7 ++-- .../Models/OpenApiParameter.cs | 17 ++++++--- .../Models/OpenApiRequestBody.cs | 19 +++++----- .../Models/OpenApiResponse.cs | 6 ++-- .../PublicApi/PublicApi.approved.txt | 36 ++++++++++--------- 10 files changed, 82 insertions(+), 66 deletions(-) create mode 100644 src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs new file mode 100644 index 000000000..15dcd955e --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace Microsoft.OpenApi; + +/// +/// Describes an element that has content. +/// +public interface IOpenApiContentElement +{ + /// + /// A map containing descriptions of potential payloads. + /// The key is a media type or media type range and the value describes it. + /// + IDictionary? Content { get; set; } +} + +/// +/// Describes an element that has content. +/// +public interface IOpenApiReadOnlyContentElement +{ + /// + /// A map containing descriptions of potential payloads. + /// The key is a media type or media type range and the value describes it. + /// + IDictionary? Content { get; } +} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs index 04c24b5b2..5f65c39b4 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the headers object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable +public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement { /// /// Determines whether this header is mandatory. @@ -57,10 +57,4 @@ public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExte /// Examples of the media type. /// public IDictionary? Examples { get; } - - /// - /// A map containing the representations for the header. - /// - public IDictionary? Content { get; } - } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs index 312517acb..405d04fab 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs @@ -7,7 +7,7 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the parameter object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable +public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement { /// /// REQUIRED. The name of the parameter. Parameter names are case sensitive. @@ -93,15 +93,4 @@ public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyE /// Assign to use get null as a serialized value. /// public JsonNode? Example { get; } - - /// - /// A map containing the representations for the parameter. - /// The key is the media type and the value describes it. - /// The map MUST only contain one entry. - /// For more complex scenarios, the content property can define the media type and schema of the parameter. - /// A parameter MUST contain either a schema property, or a content property, but not both. - /// When example or examples are provided in conjunction with the schema object, - /// the example MUST follow the prescribed serialization strategy for the parameter. - /// - public IDictionary? Content { get; } } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs index dfe1e1715..2e722b0f5 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs @@ -6,18 +6,13 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the request body object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable +public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement { /// /// Determines if the request body is required in the request. Defaults to false. /// public bool Required { get; } - /// - /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. - /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* - /// - public IDictionary? Content { get; } /// /// Converts the request body to a body parameter in preparation for a v2 serialization. /// diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs index dfddd7838..07ef60f3d 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs @@ -6,19 +6,13 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the response object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable +public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement { /// /// Maps a header name to its definition. /// public IDictionary? Headers { get; } - /// - /// A map containing descriptions of potential response payloads. - /// The key is a media type or media type range and the value describes it. - /// - public IDictionary? Content { get; } - /// /// A map of operations links that can be followed from the response. /// The key of the map is a short name for the link, diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index 8bb155f85..33f119e4d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -11,7 +11,7 @@ namespace Microsoft.OpenApi /// Header Object. /// The Header Object follows the structure of the Parameter Object. /// - public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible + public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible, IOpenApiContentElement { /// public string? Description { get; set; } @@ -90,7 +90,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -167,7 +167,8 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - var targetSchema = Schema switch { + var targetSchema = Schema switch + { OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget, OpenApiSchema schema => schema, _ => null, diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index 63b3735e2..0ea9ef57b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -11,7 +11,7 @@ namespace Microsoft.OpenApi /// /// Parameter Object. /// - public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter + public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter, IOpenApiContentElement { private bool? _explode; private ParameterStyle? _style; @@ -60,7 +60,15 @@ public bool Explode /// public JsonNode? Example { get; set; } - /// + /// + /// A map containing the representations for the parameter. + /// The key is the media type and the value describes it. + /// The map MUST only contain one entry. + /// For more complex scenarios, the content property can define the media type and schema of the parameter. + /// A parameter MUST contain either a schema property, or a content property, but not both. + /// When example or examples are provided in conjunction with the schema object, + /// the example MUST follow the prescribed serialization strategy for the parameter. + /// public IDictionary? Content { get; set; } /// @@ -105,7 +113,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -200,7 +208,8 @@ internal virtual void WriteRequestBodySchemaForV2(IOpenApiWriter writer, Diction // uniqueItems // enum // multipleOf - var targetSchema = Schema switch { + var targetSchema = Schema switch + { OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget, OpenApiSchema schema => schema, _ => null, diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index 8f4c1bd90..73d5e9a98 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -10,7 +10,7 @@ namespace Microsoft.OpenApi /// /// Request Body Object /// - public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody + public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody, IOpenApiContentElement { /// public string? Description { get; set; } @@ -18,7 +18,10 @@ public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody /// public bool Required { get; set; } - /// + /// + /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. + /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* + /// public IDictionary? Content { get; set; } /// @@ -56,7 +59,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { @@ -102,7 +105,7 @@ public IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) Extensions = Extensions?.ToDictionary(static k => k.Key, static v => v.Value) }; // Clone extensions so we can remove the x-bodyName extensions from the output V2 model. - if (bodyParameter.Extensions is not null && + if (bodyParameter.Extensions is not null && bodyParameter.Extensions.TryGetValue(OpenApiConstants.BodyName, out var bodyNameExtension) && bodyNameExtension is JsonNodeExtension bodyName) { @@ -118,7 +121,7 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter if (Content == null || !Content.Any()) yield break; var properties = Content.First().Value.Schema?.Properties; - if(properties != null) + if (properties != null) { foreach (var property in properties) { @@ -136,11 +139,11 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter OpenApiSchemaReference => throw new InvalidOperationException("Unresolved reference target"), _ => throw new InvalidOperationException("Unexpected schema type") }; - + updatedSchema.Type = "file".ToJsonSchemaType(); updatedSchema.Format = null; paramSchema = updatedSchema; - + } yield return new OpenApiFormDataParameter() { @@ -151,7 +154,7 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter Required = Content.First().Value.Schema?.Required?.Contains(property.Key) ?? false }; } - } + } } /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 6c1af10f1..4023efaf5 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -10,7 +10,7 @@ namespace Microsoft.OpenApi /// /// Response object. /// - public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse + public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse, IOpenApiContentElement { /// public string? Description { get; set; } @@ -61,7 +61,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -153,7 +153,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) // so remove it from the cloned collection so we don't write it again. extensionsClone?.Remove(key); } - } + } } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index d0b8989ef..167896e37 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -106,6 +106,10 @@ namespace Microsoft.OpenApi { System.Collections.Generic.Dictionary? PathItems { get; } } + public interface IOpenApiContentElement + { + System.Collections.Generic.IDictionary? Content { get; set; } + } public interface IOpenApiDescribedElement : Microsoft.OpenApi.IOpenApiElement { string? Description { get; set; } @@ -124,11 +128,10 @@ namespace Microsoft.OpenApi { void Write(Microsoft.OpenApi.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion specVersion); } - public interface IOpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { bool AllowEmptyValue { get; } bool AllowReserved { get; } - System.Collections.Generic.IDictionary? Content { get; } bool Deprecated { get; } System.Text.Json.Nodes.JsonNode? Example { get; } System.Collections.Generic.IDictionary? Examples { get; } @@ -145,11 +148,10 @@ namespace Microsoft.OpenApi Microsoft.OpenApi.RuntimeExpressionAnyWrapper? RequestBody { get; } Microsoft.OpenApi.OpenApiServer? Server { get; } } - public interface IOpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { bool AllowEmptyValue { get; } bool AllowReserved { get; } - System.Collections.Generic.IDictionary? Content { get; } bool Deprecated { get; } System.Text.Json.Nodes.JsonNode? Example { get; } System.Collections.Generic.IDictionary? Examples { get; } @@ -166,6 +168,10 @@ namespace Microsoft.OpenApi System.Collections.Generic.IList? Parameters { get; } System.Collections.Generic.IList? Servers { get; } } + public interface IOpenApiReadOnlyContentElement + { + System.Collections.Generic.IDictionary? Content { get; } + } public interface IOpenApiReadOnlyDescribedElement : Microsoft.OpenApi.IOpenApiElement { string? Description { get; } @@ -199,16 +205,14 @@ namespace Microsoft.OpenApi U CopyReferenceAsTargetElementWithOverrides(U source); } public interface IOpenApiReferenceable : Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiSerializable { } - public interface IOpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { - System.Collections.Generic.IDictionary? Content { get; } bool Required { get; } Microsoft.OpenApi.IOpenApiParameter? ConvertToBodyParameter(Microsoft.OpenApi.IOpenApiWriter writer); System.Collections.Generic.IEnumerable? ConvertToFormDataParameters(Microsoft.OpenApi.IOpenApiWriter writer); } - public interface IOpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { - System.Collections.Generic.IDictionary? Content { get; } System.Collections.Generic.IDictionary? Headers { get; } System.Collections.Generic.IDictionary? Links { get; } } @@ -736,7 +740,7 @@ namespace Microsoft.OpenApi public static Microsoft.OpenApi.OpenApiUrlTreeNode CreateOpenApiUrlTreeNode(System.Collections.Generic.Dictionary sources) { } public static System.Func CreatePredicate(string? operationIds = null, string? tags = null, System.Collections.Generic.Dictionary>? requestUrls = null, Microsoft.OpenApi.OpenApiDocument? source = null) { } } - public class OpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiHeader : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiHeader() { } public bool AllowEmptyValue { get; set; } @@ -756,7 +760,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV3(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiHeaderReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiHeaderReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public bool AllowEmptyValue { get; } @@ -941,7 +945,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV3(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiParameter : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiParameter() { } public bool AllowEmptyValue { get; set; } @@ -963,7 +967,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV3(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiParameterReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiParameterReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiParameterReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public bool AllowEmptyValue { get; } @@ -1065,7 +1069,7 @@ namespace Microsoft.OpenApi protected override void SerializeAdditionalV31Properties(Microsoft.OpenApi.IOpenApiWriter writer) { } protected override void SetAdditional31MetadataFromMapNode(System.Text.Json.Nodes.JsonObject jsonObject) { } } - public class OpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiRequestBody : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiRequestBody() { } public System.Collections.Generic.IDictionary? Content { get; set; } @@ -1079,7 +1083,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV3(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiRequestBodyReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiRequestBodyReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiRequestBodyReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public System.Collections.Generic.IDictionary? Content { get; } @@ -1093,7 +1097,7 @@ namespace Microsoft.OpenApi public Microsoft.OpenApi.IOpenApiRequestBody CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiResponse : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiResponse() { } public System.Collections.Generic.IDictionary? Content { get; set; } @@ -1106,7 +1110,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV3(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiResponseReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiResponseReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public System.Collections.Generic.IDictionary? Content { get; } From 67899ae3c64615be6e743594cd01b63a70e9ff0d Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 17:55:22 +0000 Subject: [PATCH 15/18] chore(support/v2): release 2.6.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 10 ++++++++++ Directory.Build.props | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4dedeaebc..511dd5165 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.5.0" + ".": "2.6.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3098a8f17..00819c348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.6.0](https://github.com/microsoft/OpenAPI.NET/compare/v2.5.0...v2.6.0) (2026-01-21) + + +### Features + +* **models:** add shared Content interface ([80e4bbf](https://github.com/microsoft/OpenAPI.NET/commit/80e4bbfa4ab31d3af69fe29751714d001c1f9566)) +* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([338566f](https://github.com/microsoft/OpenAPI.NET/commit/338566fafce04ee1329f4ead61fe1e87e01144ad)) +* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([80e4bbf](https://github.com/microsoft/OpenAPI.NET/commit/80e4bbfa4ab31d3af69fe29751714d001c1f9566)) +* **models:** support mutualTLS security scheme ([f9cf5b8](https://github.com/microsoft/OpenAPI.NET/commit/f9cf5b807d71c49e5bd7e2bec97f12d3b50ca180)) + ## [2.5.0](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.3...v2.5.0) (2026-01-19) diff --git a/Directory.Build.props b/Directory.Build.props index a4b8c77a1..76cd2b183 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,7 +12,7 @@ https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET - 2.5.0 + 2.6.0 From 110b3b9611dbeb5a241dfcc2be4a7850c3e1bd41 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 22 Jan 2026 13:37:04 -0500 Subject: [PATCH 16/18] Revert "Merge pull request #2702 from microsoft/chore/sync-v2" This reverts commit 615d66109641b72071a014eece52d78ba79a1317, reversing changes made to 2258501030355fbda99c62df5a8d6a0579906360. --- CHANGELOG.md | 23 ------------------- .../Models/Interfaces/IOpenApiHeader.cs | 1 + 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4219e0dd4..8855d4438 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,29 +87,6 @@ * adds support for OpenAPI 3.2.0 ([765a8dd](https://github.com/microsoft/OpenAPI.NET/commit/765a8dd4d6efd1a31b6a76d282ccffa5877a845a)) -## [2.6.0](https://github.com/microsoft/OpenAPI.NET/compare/v2.5.0...v2.6.0) (2026-01-21) - -### Features - -* **models:** add shared Content interface ([80e4bbf](https://github.com/microsoft/OpenAPI.NET/commit/80e4bbfa4ab31d3af69fe29751714d001c1f9566)) -* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([338566f](https://github.com/microsoft/OpenAPI.NET/commit/338566fafce04ee1329f4ead61fe1e87e01144ad)) -* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([80e4bbf](https://github.com/microsoft/OpenAPI.NET/commit/80e4bbfa4ab31d3af69fe29751714d001c1f9566)) -* **models:** support mutualTLS security scheme ([f9cf5b8](https://github.com/microsoft/OpenAPI.NET/commit/f9cf5b807d71c49e5bd7e2bec97f12d3b50ca180)) - -## [2.5.0](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.3...v2.5.0) (2026-01-19) - -## Features - -* hidi validate command now logs warnings ([1d3d085](https://github.com/microsoft/OpenAPI.NET/commit/1d3d085e0278d9341d7bd10065eba584cb25773c)) -* hidi validate command now logs warnings ([18ed5ac](https://github.com/microsoft/OpenAPI.NET/commit/18ed5acce9661639e1698f19c194e520eb5c93c1)) - - -### Bug Fixes - -* discriminator property validation fails any/allOf cases when it shouldn't ([ff6e411](https://github.com/microsoft/OpenAPI.NET/commit/ff6e4115dcab8c893bbc6b97639fd620b50f105e)) -* discriminator property validation fails any/allOf cases when it shouldn't ([7def73d](https://github.com/microsoft/OpenAPI.NET/commit/7def73d774d1f0e96118e92b636e52cbea371f2d)) - - ## [2.4.3](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.2...v2.4.3) (2026-01-16) ## Bug Fixes diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs index 5f65c39b4..8104c72ed 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -57,4 +57,5 @@ public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExte /// Examples of the media type. /// public IDictionary? Examples { get; } + } From e4514afcc9baf74df60736bbd59215b611f1c488 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 22 Jan 2026 13:37:24 -0500 Subject: [PATCH 17/18] Revert "feat(models): add shared Content interface (#2695)" This reverts commit 9e13b2574e68387ecc01c453b571208c40124b46. --- .../Interfaces/IOpenApiContentElement.cs | 27 -------------- .../Models/Interfaces/IOpenApiHeader.cs | 7 +++- .../Models/Interfaces/IOpenApiParameter.cs | 13 ++++++- .../Models/Interfaces/IOpenApiRequestBody.cs | 7 +++- .../Models/Interfaces/IOpenApiResponse.cs | 8 ++++- src/Microsoft.OpenApi/Models/OpenApiHeader.cs | 7 ++-- .../Models/OpenApiParameter.cs | 21 ++++------- .../Models/OpenApiRequestBody.cs | 19 +++++----- .../Models/OpenApiResponse.cs | 6 ++-- .../PublicApi/PublicApi.approved.txt | 36 +++++++++---------- 10 files changed, 67 insertions(+), 84 deletions(-) delete mode 100644 src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs deleted file mode 100644 index 15725d4fc..000000000 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiContentElement.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; - -namespace Microsoft.OpenApi; - -/// -/// Describes an element that has content. -/// -public interface IOpenApiContentElement -{ - /// - /// A map containing descriptions of potential payloads. - /// The key is a media type or media type range and the value describes it. - /// - IDictionary? Content { get; set; } -} - -/// -/// Describes an element that has content. -/// -public interface IOpenApiReadOnlyContentElement -{ - /// - /// A map containing descriptions of potential payloads. - /// The key is a media type or media type range and the value describes it. - /// - IDictionary? Content { get; } -} diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs index 8104c72ed..55e484555 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -8,7 +8,7 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the headers object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement +public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable { /// /// Determines whether this header is mandatory. @@ -58,4 +58,9 @@ public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiReadOnlyExte /// public IDictionary? Examples { get; } + /// + /// A map containing the representations for the header. + /// + public IDictionary? Content { get; } + } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs index 405d04fab..5669a0bb3 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiParameter.cs @@ -7,7 +7,7 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the parameter object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement +public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable { /// /// REQUIRED. The name of the parameter. Parameter names are case sensitive. @@ -93,4 +93,15 @@ public interface IOpenApiParameter : IOpenApiDescribedElement, IOpenApiReadOnlyE /// Assign to use get null as a serialized value. /// public JsonNode? Example { get; } + + /// + /// A map containing the representations for the parameter. + /// The key is the media type and the value describes it. + /// The map MUST only contain one entry. + /// For more complex scenarios, the content property can define the media type and schema of the parameter. + /// A parameter MUST contain either a schema property, or a content property, but not both. + /// When example or examples are provided in conjunction with the schema object, + /// the example MUST follow the prescribed serialization strategy for the parameter. + /// + public IDictionary? Content { get; } } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs index 2e722b0f5..5ab2f7174 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiRequestBody.cs @@ -6,13 +6,18 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the request body object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiReadOnlyContentElement +public interface IOpenApiRequestBody : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable { /// /// Determines if the request body is required in the request. Defaults to false. /// public bool Required { get; } + /// + /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. + /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* + /// + public IDictionary? Content { get; } /// /// Converts the request body to a body parameter in preparation for a v2 serialization. /// diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs index 6823868f2..d0423771f 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiResponse.cs @@ -6,13 +6,19 @@ namespace Microsoft.OpenApi; /// Defines the base properties for the response object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiSummarizedElement, IOpenApiReadOnlyContentElement +public interface IOpenApiResponse : IOpenApiDescribedElement, IOpenApiReadOnlyExtensible, IShallowCopyable, IOpenApiReferenceable, IOpenApiSummarizedElement { /// /// Maps a header name to its definition. /// public IDictionary? Headers { get; } + /// + /// A map containing descriptions of potential response payloads. + /// The key is a media type or media type range and the value describes it. + /// + public IDictionary? Content { get; } + /// /// A map of operations links that can be followed from the response. /// The key of the map is a short name for the link, diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index 9ec42aa06..7e5ea273f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -11,7 +11,7 @@ namespace Microsoft.OpenApi /// Header Object. /// The Header Object follows the structure of the Parameter Object. /// - public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible, IOpenApiContentElement + public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible { /// public string? Description { get; set; } @@ -98,7 +98,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -175,8 +175,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); // schema - var targetSchema = Schema switch - { + var targetSchema = Schema switch { OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget, OpenApiSchema schema => schema, _ => null, diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index 14294cbd8..d6b060a78 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -11,7 +11,7 @@ namespace Microsoft.OpenApi /// /// Parameter Object. /// - public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter, IOpenApiContentElement + public class OpenApiParameter : IOpenApiExtensible, IOpenApiParameter { private bool? _explode; private ParameterStyle? _style; @@ -60,15 +60,7 @@ public bool Explode /// public JsonNode? Example { get; set; } - /// - /// A map containing the representations for the parameter. - /// The key is the media type and the value describes it. - /// The map MUST only contain one entry. - /// For more complex scenarios, the content property can define the media type and schema of the parameter. - /// A parameter MUST contain either a schema property, or a content property, but not both. - /// When example or examples are provided in conjunction with the schema object, - /// the example MUST follow the prescribed serialization strategy for the parameter. - /// + /// public IDictionary? Content { get; set; } /// @@ -119,11 +111,11 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); - + // Validate that Cookie style is only used in OpenAPI 3.2 and later if (Style == ParameterStyle.Cookie && version < OpenApiSpecVersion.OpenApi3_2) { @@ -234,8 +226,7 @@ internal virtual void WriteRequestBodySchemaForV2(IOpenApiWriter writer, Diction // uniqueItems // enum // multipleOf - var targetSchema = Schema switch - { + var targetSchema = Schema switch { OpenApiSchemaReference schemaReference => schemaReference.RecursiveTarget, OpenApiSchema schema => schema, _ => null, @@ -280,7 +271,7 @@ internal virtual void WriteRequestBodySchemaForV2(IOpenApiWriter writer, Diction public virtual void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); - + // Validate that Cookie style is only used in OpenAPI 3.2 and later if (Style == ParameterStyle.Cookie) { diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index 225837544..fa29d3ea0 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -10,7 +10,7 @@ namespace Microsoft.OpenApi /// /// Request Body Object /// - public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody, IOpenApiContentElement + public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody { /// public string? Description { get; set; } @@ -18,10 +18,7 @@ public class OpenApiRequestBody : IOpenApiExtensible, IOpenApiRequestBody, IOpen /// public bool Required { get; set; } - /// - /// REQUIRED. The content of the request body. The key is a media type or media type range and the value describes it. - /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* - /// + /// public IDictionary? Content { get; set; } /// @@ -67,7 +64,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { @@ -113,7 +110,7 @@ public IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) Extensions = Extensions?.ToDictionary(static k => k.Key, static v => v.Value) }; // Clone extensions so we can remove the x-bodyName extensions from the output V2 model. - if (bodyParameter.Extensions is not null && + if (bodyParameter.Extensions is not null && bodyParameter.Extensions.TryGetValue(OpenApiConstants.BodyName, out var bodyNameExtension) && bodyNameExtension is JsonNodeExtension bodyName) { @@ -129,7 +126,7 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter if (Content == null || !Content.Any()) yield break; var properties = Content.First().Value.Schema?.Properties; - if (properties != null) + if(properties != null) { foreach (var property in properties) { @@ -147,11 +144,11 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter OpenApiSchemaReference => throw new InvalidOperationException("Unresolved reference target"), _ => throw new InvalidOperationException("Unexpected schema type") }; - + updatedSchema.Type = "file".ToJsonSchemaType(); updatedSchema.Format = null; paramSchema = updatedSchema; - + } yield return new OpenApiFormDataParameter() { @@ -162,7 +159,7 @@ public IEnumerable ConvertToFormDataParameters(IOpenApiWriter Required = Content.First().Value.Schema?.Required?.Contains(property.Key) ?? false }; } - } + } } /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 6cc0000df..4ee39336e 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -10,7 +10,7 @@ namespace Microsoft.OpenApi /// /// Response object. /// - public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse, IOpenApiContentElement + public class OpenApiResponse : IOpenApiExtensible, IOpenApiResponse { /// public string? Summary { get; set; } @@ -73,7 +73,7 @@ public virtual void SerializeAsV3(IOpenApiWriter writer) SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -177,7 +177,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) // so remove it from the cloned collection so we don't write it again. extensionsClone?.Remove(key); } - } + } } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 5413879c0..59f1bce31 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -109,10 +109,6 @@ namespace Microsoft.OpenApi { System.Collections.Generic.Dictionary? PathItems { get; } } - public interface IOpenApiContentElement - { - System.Collections.Generic.IDictionary? Content { get; set; } - } public interface IOpenApiDescribedElement : Microsoft.OpenApi.IOpenApiElement { string? Description { get; set; } @@ -133,10 +129,11 @@ namespace Microsoft.OpenApi { void Write(Microsoft.OpenApi.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion specVersion); } - public interface IOpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { bool AllowEmptyValue { get; } bool AllowReserved { get; } + System.Collections.Generic.IDictionary? Content { get; } bool Deprecated { get; } System.Text.Json.Nodes.JsonNode? Example { get; } System.Collections.Generic.IDictionary? Examples { get; } @@ -163,10 +160,11 @@ namespace Microsoft.OpenApi System.Collections.Generic.IList? PrefixEncoding { get; } Microsoft.OpenApi.IOpenApiSchema? Schema { get; } } - public interface IOpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { bool AllowEmptyValue { get; } bool AllowReserved { get; } + System.Collections.Generic.IDictionary? Content { get; } bool Deprecated { get; } System.Text.Json.Nodes.JsonNode? Example { get; } System.Collections.Generic.IDictionary? Examples { get; } @@ -183,10 +181,6 @@ namespace Microsoft.OpenApi System.Collections.Generic.IList? Parameters { get; } System.Collections.Generic.IList? Servers { get; } } - public interface IOpenApiReadOnlyContentElement - { - System.Collections.Generic.IDictionary? Content { get; } - } public interface IOpenApiReadOnlyDescribedElement : Microsoft.OpenApi.IOpenApiElement { string? Description { get; } @@ -220,14 +214,16 @@ namespace Microsoft.OpenApi U CopyReferenceAsTargetElementWithOverrides(U source); } public interface IOpenApiReferenceable : Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiSerializable { } - public interface IOpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { + System.Collections.Generic.IDictionary? Content { get; } bool Required { get; } Microsoft.OpenApi.IOpenApiParameter? ConvertToBodyParameter(Microsoft.OpenApi.IOpenApiWriter writer); System.Collections.Generic.IEnumerable? ConvertToFormDataParameters(Microsoft.OpenApi.IOpenApiWriter writer); } - public interface IOpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable + public interface IOpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable { + System.Collections.Generic.IDictionary? Content { get; } System.Collections.Generic.IDictionary? Headers { get; } System.Collections.Generic.IDictionary? Links { get; } } @@ -791,7 +787,7 @@ namespace Microsoft.OpenApi public static Microsoft.OpenApi.OpenApiUrlTreeNode CreateOpenApiUrlTreeNode(System.Collections.Generic.Dictionary sources) { } public static System.Func CreatePredicate(string? operationIds = null, string? tags = null, System.Collections.Generic.Dictionary>? requestUrls = null, Microsoft.OpenApi.OpenApiDocument? source = null) { } } - public class OpenApiHeader : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiHeader : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiHeader() { } public bool AllowEmptyValue { get; set; } @@ -812,7 +808,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiHeaderReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiHeaderReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiHeader, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public bool AllowEmptyValue { get; } @@ -1027,7 +1023,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiParameter : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiParameter : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiParameter() { } public bool AllowEmptyValue { get; set; } @@ -1050,7 +1046,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiParameterReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiParameterReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiParameter, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiParameterReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public bool AllowEmptyValue { get; } @@ -1155,7 +1151,7 @@ namespace Microsoft.OpenApi protected override void SerializeAdditionalV32Properties(Microsoft.OpenApi.IOpenApiWriter writer) { } protected override void SetAdditional31MetadataFromMapNode(System.Text.Json.Nodes.JsonObject jsonObject) { } } - public class OpenApiRequestBody : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiRequestBody : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiRequestBody() { } public System.Collections.Generic.IDictionary? Content { get; set; } @@ -1170,7 +1166,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiRequestBodyReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable + public class OpenApiRequestBodyReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiRequestBody, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IShallowCopyable { public OpenApiRequestBodyReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public System.Collections.Generic.IDictionary? Content { get; } @@ -1184,7 +1180,7 @@ namespace Microsoft.OpenApi public Microsoft.OpenApi.IOpenApiRequestBody CreateShallowCopy() { } public override void SerializeAsV2(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiResponse : Microsoft.OpenApi.IOpenApiContentElement, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable + public class OpenApiResponse : Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiExtensible, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable { public OpenApiResponse() { } public System.Collections.Generic.IDictionary? Content { get; set; } @@ -1199,7 +1195,7 @@ namespace Microsoft.OpenApi public virtual void SerializeAsV31(Microsoft.OpenApi.IOpenApiWriter writer) { } public virtual void SerializeAsV32(Microsoft.OpenApi.IOpenApiWriter writer) { } } - public class OpenApiResponseReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyContentElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable + public class OpenApiResponseReference : Microsoft.OpenApi.BaseOpenApiReferenceHolder, Microsoft.OpenApi.IOpenApiDescribedElement, Microsoft.OpenApi.IOpenApiElement, Microsoft.OpenApi.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.IOpenApiReferenceable, Microsoft.OpenApi.IOpenApiResponse, Microsoft.OpenApi.IOpenApiSerializable, Microsoft.OpenApi.IOpenApiSummarizedElement, Microsoft.OpenApi.IShallowCopyable { public OpenApiResponseReference(string referenceId, Microsoft.OpenApi.OpenApiDocument? hostDocument = null, string? externalResource = null) { } public System.Collections.Generic.IDictionary? Content { get; } From e1b234cfe357e869b4900f8162ce93cb67424b16 Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 18:53:14 +0000 Subject: [PATCH 18/18] chore(main): release 3.3.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 12 ++++++++++++ Directory.Build.props | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ff1c7af58..0befe35d6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.3.0" + ".": "3.3.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8855d4438..3d8605bbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [3.3.1](https://github.com/microsoft/OpenAPI.NET/compare/v3.3.0...v3.3.1) (2026-01-22) + + +### Features + +* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([338566f](https://github.com/microsoft/OpenAPI.NET/commit/338566fafce04ee1329f4ead61fe1e87e01144ad)) + + +### Bug Fixes + +* broken binary compatibility due to interface changes in previous version ([d96bba7](https://github.com/microsoft/OpenAPI.NET/commit/d96bba72c383cd5db2b7032530aee3b4d944ebc6)) + ## [3.3.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.2.0...v3.3.0) (2026-01-21) diff --git a/Directory.Build.props b/Directory.Build.props index 36284217c..13c72dd49 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,7 +12,7 @@ https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET - 3.3.0 + 3.3.1