From 079f8ea2dfa227325a2ff7905cab86f15ee2347f Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Tue, 7 Jun 2022 00:51:33 +0300 Subject: [PATCH] Provides support for using the range of response status code `2XX` (#215) * UseHTTPStatusCodeClass2XX as a setting to rep. all status codes 200-299 * Implement UseStatusCodeClass2XX setting when generating responses * Update tests to validate use of the setting: UseHTTPStatusCodeClass2XX * Rename property * Update tests * Add schema to responses with 2XX status code; return 204 status code for actions/functions * Rename field variables appropriately * Update csproj with project release notes; fix missing comma --- .../Common/Constants.cs | 5 ++ .../Common/OpenApiOperationExtensions.cs | 28 ++++++- .../Generator/OpenApiResponseGenerator.cs | 2 +- .../Microsoft.OpenAPI.OData.Reader.csproj | 5 +- .../OpenApiConvertSettings.cs | 9 +- .../ComplexPropertyGetOperationHandler.cs | 29 +++---- .../ComplexPropertyPostOperationHandler.cs | 61 +++++++------- .../ComplexPropertyUpdateOperationHandler.cs | 83 ++++++++++--------- .../DollarCountGetOperationHandler.cs | 2 +- .../Operation/EntityDeleteOperationHandler.cs | 25 +++--- .../Operation/EntityGetOperationHandler.cs | 29 +++---- .../Operation/EntitySetGetOperationHandler.cs | 27 +++--- .../EntitySetPostOperationHandler.cs | 29 +++---- .../Operation/EntityUpdateOperationHandler.cs | 67 +++++++-------- .../MediaEntityGetOperationHandler.cs | 2 +- .../Operation/MetadataGetOperationHandler.cs | 2 +- ...avigationPropertyDeleteOperationHandler.cs | 1 - .../NavigationPropertyGetOperationHandler.cs | 4 +- .../NavigationPropertyPostOperationHandler.cs | 2 +- ...avigationPropertyUpdateOperationHandler.cs | 44 +++++----- .../ODataTypeCastGetOperationHandler.cs | 4 +- .../Operation/RefGetOperationHandler.cs | 4 +- .../Operation/RefPostOperationHandler.cs | 6 +- .../Operation/RefPutOperationHandler.cs | 24 ++++-- .../Operation/SingletonGetOperationHandler.cs | 27 +++--- .../SingletonPatchOperationHandler.cs | 69 +++++++-------- .../PublicAPI.Unshipped.txt | 4 +- ...ComplexPropertyGetOperationHandlerTests.cs | 14 ++-- ...mplexPropertyPatchOperationHandlerTests.cs | 24 ++++-- ...omplexPropertyPostOperationHandlerTests.cs | 23 +++-- ...ComplexPropertyPutOperationHandlerTests.cs | 26 ++++-- .../EdmFunctionImportOperationHandlerTests.cs | 15 +++- .../EdmFunctionOperationHandlerTests.cs | 15 +++- .../EntityGetOperationHandlerTests.cs | 14 ++-- .../EntityPatchOperationHandlerTests.cs | 23 +++-- .../EntityPutOperationHandlerTests.cs | 23 +++-- .../EntitySetGetOperationHandlerTests.cs | 18 ++-- .../EntitySetPostOperationHandlerTests.cs | 32 +++---- .../MediaEntityGetOperationHandlerTests.cs | 40 +++++---- ...igationPropertyGetOperationHandlerTests.cs | 14 ++-- ...ationPropertyPatchOperationHandlerTests.cs | 23 +++-- ...gationPropertyPostOperationHandlerTests.cs | 14 ++-- ...igationPropertyPutOperationHandlerTests.cs | 23 +++-- .../ODataTypeCastGetOperationHandlerTests.cs | 17 ++-- .../Operation/RefGetOperationHandlerTests.cs | 14 ++-- .../Operation/RefPostOperationHandlerTests.cs | 14 ++-- .../Operation/RefPutOperationHandlerTests.cs | 14 ++-- .../SingletonGetOperationHandlerTests.cs | 14 ++-- .../SingletonPatchOperationHandlerTests.cs | 23 +++-- 49 files changed, 604 insertions(+), 427 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs index 9288d1cf..2c84bba8 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs @@ -25,6 +25,11 @@ internal static class Constants /// public static string ApplicationOctetStreamMediaType = "application/octet-stream"; + /// + /// Status code class: 2XX + /// + public static string StatusCodeClass2XX = "2XX"; + /// /// Status code: 200 /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs index 9888e452..36150489 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Generator; +using System.Collections.Generic; namespace Microsoft.OpenApi.OData.Common; @@ -20,7 +21,8 @@ public static class OpenApiOperationExtensions /// The operation. /// The settings. /// Whether to add a 204 no content response. - public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, bool addNoContent = false) + /// Optional: The OpenAPI schema of the response. + public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, bool addNoContent = false, OpenApiSchema schema = null) { if (operation == null) { throw Error.ArgumentNull(nameof(operation)); @@ -34,9 +36,29 @@ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiCon operation.Responses = new(); } - if(addNoContent) + if (addNoContent) { - operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse()); + if (settings.UseSuccessStatusCodeRange && schema != null) + { + OpenApiResponse response = new() + { + Content = new Dictionary + { + { + Constants.ApplicationJsonMediaType, + new OpenApiMediaType + { + Schema = schema + } + } + } + }; + operation.Responses.Add(Constants.StatusCodeClass2XX, response); + } + else + { + operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse()); + } } if(settings.ErrorResponsesAsDefault) diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs index 1ee020cd..813a10c7 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs @@ -205,7 +205,7 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp } } }; - responses.Add(Constants.StatusCode200, response); + responses.Add(context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, response); } if (context.Settings.ErrorResponsesAsDefault) diff --git a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj index 9794c15e..3b9f6adb 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj +++ b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj @@ -15,16 +15,17 @@ netstandard2.0 Microsoft.OpenApi.OData true - 1.0.11-preview1 + 1.0.11-preview2 This package contains the codes you need to convert OData CSDL to Open API Document of Model. © Microsoft Corporation. All rights reserved. Microsoft OpenApi OData EDM https://github.com/Microsoft/OpenAPI.NET.OData -- Adds list of all derived types for discriminator mapping #219 - Fixes reading restriction annotations for entity types defining navigation properties #220 - Enables configuring appending bound operations on derived types #221 - Add error ranges for OData actions when ErrorResponsesAsDefault is set to false #218 +- Fixes missing bound operations on some navigation property paths #201 +- Provides support for using success status code range 2XX #153 Microsoft.OpenApi.OData.Reader ..\..\tool\Microsoft.OpenApi.OData.snk diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs index ff5a7f80..5b7ed51e 100644 --- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs @@ -253,6 +253,12 @@ public string PathPrefix /// public bool AppendBoundOperationsOnDerivedTypeCastSegments { get; set; } = false; + /// + /// Gets/Sets a value indicating whether or not to use the HTTP success status code range 2XX + /// to represent all response codes between 200 - 299. + /// + public bool UseSuccessStatusCodeRange { get; set; } = false; + internal OpenApiConvertSettings Clone() { var newSettings = new OpenApiConvertSettings @@ -294,7 +300,8 @@ internal OpenApiConvertSettings Clone() RequireRestrictionAnnotationsToGenerateComplexPropertyPaths = this.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths, ExpandDerivedTypesNavigationProperties = this.ExpandDerivedTypesNavigationProperties, CustomXMLAttributesMapping = this.CustomXMLAttributesMapping, - AppendBoundOperationsOnDerivedTypeCastSegments = this.AppendBoundOperationsOnDerivedTypeCastSegments + AppendBoundOperationsOnDerivedTypeCastSegments = this.AppendBoundOperationsOnDerivedTypeCastSegments, + UseSuccessStatusCodeRange = this.UseSuccessStatusCodeRange }; return newSettings; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs index 1195ffa0..8bd2d6e8 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs @@ -20,16 +20,13 @@ internal class ComplexPropertyGetOperationHandler : ComplexPropertyBaseOperation /// public override OperationType OperationType => OperationType.Get; - /// - /// Gets/Sets the - /// - private ReadRestrictionsType ReadRestrictions { get; set; } + private ReadRestrictionsType _readRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - ReadRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.ReadRestrictions); + _readRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.ReadRestrictions); } /// @@ -45,8 +42,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) // Summary and Description string placeHolder = $"Get {ComplexPropertySegment.Property.Name} property value"; - operation.Summary = ReadRestrictions?.Description ?? placeHolder; - operation.Description = ReadRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(ComplexPropertySegment.Property); + operation.Summary = _readRestrictions?.Description ?? placeHolder; + operation.Description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(ComplexPropertySegment.Property); base.SetBasicInfo(operation); } @@ -155,7 +152,7 @@ private void SetCollectionResponse(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { UnresolvedReference = true, @@ -187,7 +184,7 @@ private void SetSingleResponse(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Result entities", @@ -207,29 +204,29 @@ private void SetSingleResponse(OpenApiOperation operation) } protected override void SetSecurity(OpenApiOperation operation) { - if (ReadRestrictions?.Permissions == null) + if (_readRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(ReadRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions).ToList(); } protected override void AppendCustomParameters(OpenApiOperation operation) { - if (ReadRestrictions == null) + if (_readRestrictions == null) { return; } - if (ReadRestrictions.CustomHeaders != null) + if (_readRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, ReadRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _readRestrictions.CustomHeaders, ParameterLocation.Header); } - if (ReadRestrictions.CustomQueryOptions != null) + if (_readRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, ReadRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _readRestrictions.CustomQueryOptions, ParameterLocation.Query); } } } \ No newline at end of file diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs index 680613a3..25ebf70b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs @@ -26,15 +26,12 @@ protected override void Initialize(ODataContext context, ODataPath path) throw new InvalidOperationException("OData conventions do not support POSTing to a complex property that is not a collection."); } - InsertRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.InsertRestrictions); + _insertRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.InsertRestrictions); } /// public override OperationType OperationType => OperationType.Post; - /// - /// Gets/Sets the - /// - private InsertRestrictionsType InsertRestrictions { get; set; } + private InsertRestrictionsType _insertRestrictions; /// protected override void SetBasicInfo(OpenApiOperation operation) @@ -48,8 +45,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) // Summary and Description string placeHolder = $"Sets a new value for the collection of {ComplexPropertySegment.ComplexType.Name}."; - operation.Summary = InsertRestrictions?.Description ?? placeHolder; - operation.Description = InsertRestrictions?.LongDescription; + operation.Summary = _insertRestrictions?.Description ?? placeHolder; + operation.Description = _insertRestrictions?.LongDescription; base.SetBasicInfo(operation); } @@ -72,20 +69,7 @@ protected override void SetParameters(OpenApiOperation operation) } /// protected override void SetRequestBody(OpenApiOperation operation) - { - OpenApiSchema schema = new() - { - Type = "array", - Items = new OpenApiSchema - { - UnresolvedReference = true, - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = ComplexPropertySegment.ComplexType.FullName() - } - } - }; + { operation.RequestBody = new OpenApiRequestBody { Required = true, @@ -95,7 +79,7 @@ protected override void SetRequestBody(OpenApiOperation operation) { Constants.ApplicationJsonMediaType, new OpenApiMediaType { - Schema = schema + Schema = GetOpenApiSchema() } } } @@ -106,35 +90,52 @@ protected override void SetRequestBody(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - operation.AddErrorResponses(Context.Settings, true); + operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema()); base.SetResponses(operation); } protected override void SetSecurity(OpenApiOperation operation) { - if (InsertRestrictions?.Permissions == null) + if (_insertRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(InsertRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions).ToList(); } protected override void AppendCustomParameters(OpenApiOperation operation) { - if (InsertRestrictions == null) + if (_insertRestrictions == null) { return; } - if (InsertRestrictions.CustomQueryOptions != null) + if (_insertRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, InsertRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _insertRestrictions.CustomQueryOptions, ParameterLocation.Query); } - if (InsertRestrictions.CustomHeaders != null) + if (_insertRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, InsertRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _insertRestrictions.CustomHeaders, ParameterLocation.Header); } } + + private OpenApiSchema GetOpenApiSchema() + { + return new() + { + Type = "array", + Items = new OpenApiSchema + { + UnresolvedReference = true, + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = ComplexPropertySegment.ComplexType.FullName() + } + } + }; + } } \ No newline at end of file diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs index f24d5eb4..c49c5bc6 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs @@ -16,16 +16,14 @@ namespace Microsoft.OpenApi.OData.Operation; internal abstract class ComplexPropertyUpdateOperationHandler : ComplexPropertyBaseOperationHandler { - /// - /// Gets/Sets the - /// - private UpdateRestrictionsType UpdateRestrictions { get; set; } + + private UpdateRestrictionsType _updateRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - UpdateRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.UpdateRestrictions); + _updateRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.UpdateRestrictions); } /// @@ -33,8 +31,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) { // Summary and Description string placeHolder = $"Update property {ComplexPropertySegment.Property.Name} value."; - operation.Summary = UpdateRestrictions?.Description ?? placeHolder; - operation.Description = UpdateRestrictions?.LongDescription; + operation.Summary = _updateRestrictions?.Description ?? placeHolder; + operation.Description = _updateRestrictions?.LongDescription; // OperationId if (Context.Settings.EnableOperationId) @@ -47,31 +45,6 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) { - OpenApiSchema schema = ComplexPropertySegment.Property.Type.IsCollection() ? - new OpenApiSchema - { - Type = "array", - Items = new OpenApiSchema - { - UnresolvedReference = true, - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = ComplexPropertySegment.ComplexType.FullName() - } - } - } - : - new OpenApiSchema - { - UnresolvedReference = true, - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = ComplexPropertySegment.ComplexType.FullName() - } - }; - operation.RequestBody = new OpenApiRequestBody { Required = true, @@ -81,7 +54,7 @@ protected override void SetRequestBody(OpenApiOperation operation) { Constants.ApplicationJsonMediaType, new OpenApiMediaType { - Schema = schema + Schema = GetOpenApiSchema() } } } @@ -93,34 +66,62 @@ protected override void SetRequestBody(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - operation.AddErrorResponses(Context.Settings, true); + operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema()); base.SetResponses(operation); } protected override void SetSecurity(OpenApiOperation operation) { - if (UpdateRestrictions?.Permissions == null) + if (_updateRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(UpdateRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions).ToList(); } protected override void AppendCustomParameters(OpenApiOperation operation) { - if (UpdateRestrictions == null) + if (_updateRestrictions == null) { return; } - if (UpdateRestrictions.CustomHeaders != null) + if (_updateRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, UpdateRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _updateRestrictions.CustomHeaders, ParameterLocation.Header); } - if (UpdateRestrictions.CustomQueryOptions != null) + if (_updateRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, UpdateRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _updateRestrictions.CustomQueryOptions, ParameterLocation.Query); } } + + private OpenApiSchema GetOpenApiSchema() + { + return ComplexPropertySegment.Property.Type.IsCollection() ? + new OpenApiSchema + { + Type = "array", + Items = new OpenApiSchema + { + UnresolvedReference = true, + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = ComplexPropertySegment.ComplexType.FullName() + } + } + } + : + new OpenApiSchema + { + UnresolvedReference = true, + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = ComplexPropertySegment.ComplexType.FullName() + } + }; + } } \ No newline at end of file diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs index 49385a5e..694b1ddf 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs @@ -57,7 +57,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { UnresolvedReference = true, diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs index 107fa0b7..b81cf973 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs @@ -23,16 +23,13 @@ internal class EntityDeleteOperationHandler : EntitySetOperationHandler /// public override OperationType OperationType => OperationType.Delete; - /// - /// Gets/Sets the - /// - private DeleteRestrictionsType DeleteRestrictions { get; set; } + private DeleteRestrictionsType _deleteRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - DeleteRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.DeleteRestrictions); + _deleteRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.DeleteRestrictions); } /// @@ -42,8 +39,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) // Description string placeHolder = "Delete entity from " + EntitySet.Name; - operation.Summary = DeleteRestrictions?.Description ?? placeHolder; - operation.Description = DeleteRestrictions?.LongDescription; + operation.Summary = _deleteRestrictions?.Description ?? placeHolder; + operation.Description = _deleteRestrictions?.LongDescription; // OperationId if (Context.Settings.EnableOperationId) @@ -79,29 +76,29 @@ protected override void SetResponses(OpenApiOperation operation) protected override void SetSecurity(OpenApiOperation operation) { - if (DeleteRestrictions == null || DeleteRestrictions.Permissions == null) + if (_deleteRestrictions == null || _deleteRestrictions.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(DeleteRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_deleteRestrictions.Permissions).ToList(); } protected override void AppendCustomParameters(OpenApiOperation operation) { - if (DeleteRestrictions == null) + if (_deleteRestrictions == null) { return; } - if (DeleteRestrictions.CustomHeaders != null) + if (_deleteRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, DeleteRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _deleteRestrictions.CustomHeaders, ParameterLocation.Header); } - if (DeleteRestrictions.CustomQueryOptions != null) + if (_deleteRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, DeleteRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _deleteRestrictions.CustomQueryOptions, ParameterLocation.Query); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs index d0f493ed..6f21d680 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs @@ -24,16 +24,13 @@ internal class EntityGetOperationHandler : EntitySetOperationHandler /// public override OperationType OperationType => OperationType.Get; - /// - /// Gets/Sets the - /// - private ReadRestrictionsType ReadRestrictions { get; set; } + private ReadRestrictionsType _readRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - ReadRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); + _readRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); } /// @@ -43,8 +40,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) // Description string placeHolder = "Get entity from " + EntitySet.Name + " by key"; - operation.Summary = ReadRestrictions?.ReadByKeyRestrictions?.Description ?? placeHolder; - operation.Description = ReadRestrictions?.ReadByKeyRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(entityType); + operation.Summary = _readRestrictions?.ReadByKeyRestrictions?.Description ?? placeHolder; + operation.Description = _readRestrictions?.ReadByKeyRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(entityType); // OperationId if (Context.Settings.EnableOperationId) @@ -107,7 +104,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Retrieved entity", @@ -132,15 +129,15 @@ protected override void SetResponses(OpenApiOperation operation) protected override void SetSecurity(OpenApiOperation operation) { - if (ReadRestrictions == null) + if (_readRestrictions == null) { return; } - ReadRestrictionsBase readBase = ReadRestrictions; - if (ReadRestrictions.ReadByKeyRestrictions != null) + ReadRestrictionsBase readBase = _readRestrictions; + if (_readRestrictions.ReadByKeyRestrictions != null) { - readBase = ReadRestrictions.ReadByKeyRestrictions; + readBase = _readRestrictions.ReadByKeyRestrictions; } if (readBase == null && readBase.Permissions == null) @@ -153,15 +150,15 @@ protected override void SetSecurity(OpenApiOperation operation) protected override void AppendCustomParameters(OpenApiOperation operation) { - if (ReadRestrictions == null) + if (_readRestrictions == null) { return; } - ReadRestrictionsBase readBase = ReadRestrictions; - if (ReadRestrictions.ReadByKeyRestrictions != null) + ReadRestrictionsBase readBase = _readRestrictions; + if (_readRestrictions.ReadByKeyRestrictions != null) { - readBase = ReadRestrictions.ReadByKeyRestrictions; + readBase = _readRestrictions.ReadByKeyRestrictions; } if (readBase.CustomHeaders != null) diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs index c3559626..b3a90e12 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs @@ -25,16 +25,13 @@ internal class EntitySetGetOperationHandler : EntitySetOperationHandler /// public override OperationType OperationType => OperationType.Get; - /// - /// Gets/Sets the - /// - private ReadRestrictionsType ReadRestrictions { get; set; } + private ReadRestrictionsType _readRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - ReadRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); + _readRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); } /// @@ -42,8 +39,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) { // Summary and Descriptions string placeHolder = "Get entities from " + EntitySet.Name; - operation.Summary = ReadRestrictions?.Description ?? placeHolder; - operation.Description = ReadRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(EntitySet); + operation.Summary = _readRestrictions?.Description ?? placeHolder; + operation.Description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(EntitySet); // OperationId if (Context.Settings.EnableOperationId) @@ -144,7 +141,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { UnresolvedReference = true, @@ -164,29 +161,29 @@ protected override void SetResponses(OpenApiOperation operation) protected override void SetSecurity(OpenApiOperation operation) { - if (ReadRestrictions?.Permissions == null) + if (_readRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(ReadRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions).ToList(); } protected override void AppendCustomParameters(OpenApiOperation operation) { - if (ReadRestrictions == null) + if (_readRestrictions == null) { return; } - if (ReadRestrictions.CustomHeaders != null) + if (_readRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, ReadRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _readRestrictions.CustomHeaders, ParameterLocation.Header); } - if (ReadRestrictions.CustomQueryOptions != null) + if (_readRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, ReadRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _readRestrictions.CustomQueryOptions, ParameterLocation.Query); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs index 7d8fa787..37233f1c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs @@ -23,17 +23,14 @@ internal class EntitySetPostOperationHandler : EntitySetOperationHandler { /// public override OperationType OperationType => OperationType.Post; - - /// - /// Gets/Sets the - /// - private InsertRestrictionsType InsertRestrictions { get; set; } + + private InsertRestrictionsType _insertRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - InsertRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.InsertRestrictions); + _insertRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.InsertRestrictions); } /// @@ -41,8 +38,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) { // Summary and Description string placeHolder = "Add new entity to " + EntitySet.Name; - operation.Summary = InsertRestrictions?.Description ?? placeHolder; - operation.Description = InsertRestrictions?.LongDescription; + operation.Summary = _insertRestrictions?.Description ?? placeHolder; + operation.Description = _insertRestrictions?.LongDescription; // OperationId if (Context.Settings.EnableOperationId) @@ -73,7 +70,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode201, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode201, new OpenApiResponse { Description = "Created entity", @@ -89,29 +86,29 @@ protected override void SetResponses(OpenApiOperation operation) protected override void SetSecurity(OpenApiOperation operation) { - if (InsertRestrictions?.Permissions == null) + if (_insertRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(InsertRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions).ToList(); } protected override void AppendCustomParameters(OpenApiOperation operation) { - if (InsertRestrictions == null) + if (_insertRestrictions == null) { return; } - if (InsertRestrictions.CustomQueryOptions != null) + if (_insertRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, InsertRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _insertRestrictions.CustomQueryOptions, ParameterLocation.Query); } - if (InsertRestrictions.CustomHeaders != null) + if (_insertRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, InsertRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _insertRestrictions.CustomHeaders, ParameterLocation.Header); } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs index f8ce6212..16ff6dab 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs @@ -19,16 +19,13 @@ namespace Microsoft.OpenApi.OData.Operation /// internal abstract class EntityUpdateOperationHandler : EntitySetOperationHandler { - /// - /// Gets/Sets the - /// - private UpdateRestrictionsType UpdateRestrictions { get; set; } + private UpdateRestrictionsType _updateRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - UpdateRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions); + _updateRestrictions = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions); } /// @@ -38,8 +35,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) // Summary and Description string placeHolder = "Update entity in " + EntitySet.Name; - operation.Summary = UpdateRestrictions?.Description ?? placeHolder; - operation.Description = UpdateRestrictions?.LongDescription; + operation.Summary = _updateRestrictions?.Description ?? placeHolder; + operation.Description = _updateRestrictions?.LongDescription; // OperationId if (Context.Settings.EnableOperationId) @@ -52,26 +49,6 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) { - OpenApiSchema schema = null; - - if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) - { - schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); - } - - if (schema == null) - { - schema = new OpenApiSchema - { - UnresolvedReference = true, - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = EntitySet.EntityType().FullName() - } - }; - } - operation.RequestBody = new OpenApiRequestBody { Required = true, @@ -81,7 +58,7 @@ protected override void SetRequestBody(OpenApiOperation operation) { Constants.ApplicationJsonMediaType, new OpenApiMediaType { - Schema = schema + Schema = GetOpenApiSchema() } } } @@ -93,36 +70,54 @@ protected override void SetRequestBody(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - operation.AddErrorResponses(Context.Settings, true); + operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema()); base.SetResponses(operation); } protected override void SetSecurity(OpenApiOperation operation) { - if (UpdateRestrictions?.Permissions == null) + if (_updateRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(UpdateRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions).ToList(); } protected override void AppendCustomParameters(OpenApiOperation operation) { - if (UpdateRestrictions == null) + if (_updateRestrictions == null) { return; } - if (UpdateRestrictions.CustomHeaders != null) + if (_updateRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, UpdateRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _updateRestrictions.CustomHeaders, ParameterLocation.Header); } - if (UpdateRestrictions.CustomQueryOptions != null) + if (_updateRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, UpdateRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _updateRestrictions.CustomQueryOptions, ParameterLocation.Query); } } + + private OpenApiSchema GetOpenApiSchema() + { + if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) + { + return EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); + } + + return new OpenApiSchema + { + UnresolvedReference = true, + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = EntitySet.EntityType().FullName() + } + }; + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs index 33571695..f04af78c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs @@ -70,7 +70,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Retrieved media content", diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs index 6eaf138d..f12e9fa9 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs @@ -52,7 +52,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Retrieved metadata document", diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs index 938a15a4..6c3afe40 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs @@ -4,7 +4,6 @@ // ------------------------------------------------------------ using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Generator; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs index 184e64c3..b85f1b8a 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs @@ -86,7 +86,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { UnresolvedReference = true, @@ -126,7 +126,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Retrieved navigation property", diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs index c7a05bb2..15841b04 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs @@ -107,7 +107,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode201, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode201, new OpenApiResponse { Description = "Created navigation property.", diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs index 1796ef26..8dbc9a76 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs @@ -39,27 +39,7 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) - { - OpenApiSchema schema = null; - - if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) - { - schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model); - } - - if (schema == null) - { - schema = new OpenApiSchema - { - UnresolvedReference = true, - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = NavigationProperty.ToEntityType().FullName() - } - }; - } - + { operation.RequestBody = new OpenApiRequestBody { Required = true, @@ -69,7 +49,7 @@ protected override void SetRequestBody(OpenApiOperation operation) { Constants.ApplicationJsonMediaType, new OpenApiMediaType { - Schema = schema + Schema = GetOpenApiSchema() } } } @@ -81,7 +61,7 @@ protected override void SetRequestBody(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - operation.AddErrorResponses(Context.Settings, true); + operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema()); base.SetResponses(operation); } @@ -112,5 +92,23 @@ protected override void AppendCustomParameters(OpenApiOperation operation) AppendCustomParameters(operation, Restriction.UpdateRestrictions.CustomQueryOptions, ParameterLocation.Query); } } + + private OpenApiSchema GetOpenApiSchema() + { + if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) + { + return EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model); + } + + return new OpenApiSchema + { + UnresolvedReference = true, + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = NavigationProperty.ToEntityType().FullName() + } + }; + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs index bc2a6fe5..0e21b70b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs @@ -185,7 +185,7 @@ private void SetCollectionResponse(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { UnresolvedReference = true, @@ -222,7 +222,7 @@ private void SetSingleResponse(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Result entities", diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs index b9b19a5a..91384ca4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs @@ -72,7 +72,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { UnresolvedReference = true, @@ -105,7 +105,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Retrieved navigation property link", diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs index d706a185..059ae7e4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs @@ -32,9 +32,7 @@ protected override void SetBasicInfo(OpenApiOperation operation) { string prefix = "CreateRef"; operation.OperationId = GetOperationId(prefix); - } - - + } } /// @@ -75,7 +73,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode201, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode201, new OpenApiResponse { Description = "Created navigation property link.", diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs index f37e825f..cd7a2e53 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs @@ -47,14 +47,7 @@ protected override void SetRequestBody(OpenApiOperation operation) { Constants.ApplicationJsonMediaType, new OpenApiMediaType { - Schema = new() - { - UnresolvedReference = true, - Reference = new OpenApiReference { - Id = Constants.ReferenceUpdateSchemaName, - Type = ReferenceType.Schema - }, - } + Schema = GetOpenApiSchema() } } } @@ -66,7 +59,7 @@ protected override void SetRequestBody(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - operation.AddErrorResponses(Context.Settings, true); + operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema()); base.SetResponses(operation); } @@ -97,5 +90,18 @@ protected override void AppendCustomParameters(OpenApiOperation operation) AppendCustomParameters(operation, Restriction.UpdateRestrictions.CustomQueryOptions, ParameterLocation.Query); } } + + private OpenApiSchema GetOpenApiSchema() + { + return new() + { + UnresolvedReference = true, + Reference = new OpenApiReference + { + Id = Constants.ReferenceUpdateSchemaName, + Type = ReferenceType.Schema + }, + }; + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs index 647da6e5..16f6b072 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs @@ -24,16 +24,13 @@ internal class SingletonGetOperationHandler : SingletonOperationHandler /// public override OperationType OperationType => OperationType.Get; - /// - /// Gets/Sets the - /// - private ReadRestrictionsType ReadRestrictions { get; set; } + private ReadRestrictionsType _readRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - ReadRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.ReadRestrictions); + _readRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.ReadRestrictions); } /// @@ -41,8 +38,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) { // Summary and Descriptions string placeHolder = "Get " + Singleton.Name; - operation.Summary = ReadRestrictions?.Description ?? placeHolder; - operation.Description = ReadRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Singleton); + operation.Summary = _readRestrictions?.Description ?? placeHolder; + operation.Description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Singleton); // OperationId, it should be unique among all operations described in the API. if (Context.Settings.EnableOperationId) @@ -105,7 +102,7 @@ protected override void SetResponses(OpenApiOperation operation) operation.Responses = new OpenApiResponses { { - Constants.StatusCode200, + Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, new OpenApiResponse { Description = "Retrieved entity", @@ -132,30 +129,30 @@ protected override void SetResponses(OpenApiOperation operation) /// protected override void SetSecurity(OpenApiOperation operation) { - if (ReadRestrictions?.Permissions == null) + if (_readRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(ReadRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions).ToList(); } /// protected override void AppendCustomParameters(OpenApiOperation operation) { - if (ReadRestrictions == null) + if (_readRestrictions == null) { return; } - if (ReadRestrictions.CustomHeaders != null) + if (_readRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, ReadRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _readRestrictions.CustomHeaders, ParameterLocation.Header); } - if (ReadRestrictions.CustomQueryOptions != null) + if (_readRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, ReadRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _readRestrictions.CustomQueryOptions, ParameterLocation.Query); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs index 3814f1f0..302bac34 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs @@ -24,16 +24,13 @@ internal class SingletonPatchOperationHandler : SingletonOperationHandler /// public override OperationType OperationType => OperationType.Patch; - /// - /// Gets/Sets the - /// - private UpdateRestrictionsType UpdateRestrictions { get; set; } + private UpdateRestrictionsType _updateRestrictions; protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); - UpdateRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.UpdateRestrictions); + _updateRestrictions = Context.Model.GetRecord(Singleton, CapabilitiesConstants.UpdateRestrictions); } /// @@ -41,8 +38,8 @@ protected override void SetBasicInfo(OpenApiOperation operation) { // Summary and Descriptions string placeHolder = "Update " + Singleton.Name; - operation.Summary = UpdateRestrictions?.Description ?? placeHolder; - operation.Description = UpdateRestrictions?.LongDescription; + operation.Summary = _updateRestrictions?.Description ?? placeHolder; + operation.Description = _updateRestrictions?.LongDescription; // OperationId if (Context.Settings.EnableOperationId) @@ -54,27 +51,7 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) - { - OpenApiSchema schema = null; - - if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) - { - schema = EdmModelHelper.GetDerivedTypesReferenceSchema(Singleton.EntityType(), Context.Model); - } - - if (schema == null) - { - schema = new OpenApiSchema - { - UnresolvedReference = true, - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = Singleton.EntityType().FullName() - } - }; - } - + { operation.RequestBody = new OpenApiRequestBody { Required = true, @@ -84,7 +61,7 @@ protected override void SetRequestBody(OpenApiOperation operation) { Constants.ApplicationJsonMediaType, new OpenApiMediaType { - Schema = schema + Schema = GetOpenApiSchema() } } } @@ -96,38 +73,56 @@ protected override void SetRequestBody(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - operation.AddErrorResponses(Context.Settings, true); + operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema()); base.SetResponses(operation); } /// protected override void SetSecurity(OpenApiOperation operation) { - if (UpdateRestrictions?.Permissions == null) + if (_updateRestrictions?.Permissions == null) { return; } - operation.Security = Context.CreateSecurityRequirements(UpdateRestrictions.Permissions).ToList(); + operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions).ToList(); } /// protected override void AppendCustomParameters(OpenApiOperation operation) { - if (UpdateRestrictions == null) + if (_updateRestrictions == null) { return; } - if (UpdateRestrictions.CustomHeaders != null) + if (_updateRestrictions.CustomHeaders != null) { - AppendCustomParameters(operation, UpdateRestrictions.CustomHeaders, ParameterLocation.Header); + AppendCustomParameters(operation, _updateRestrictions.CustomHeaders, ParameterLocation.Header); } - if (UpdateRestrictions.CustomQueryOptions != null) + if (_updateRestrictions.CustomQueryOptions != null) { - AppendCustomParameters(operation, UpdateRestrictions.CustomQueryOptions, ParameterLocation.Query); + AppendCustomParameters(operation, _updateRestrictions.CustomQueryOptions, ParameterLocation.Query); } } + + private OpenApiSchema GetOpenApiSchema() + { + if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) + { + return EdmModelHelper.GetDerivedTypesReferenceSchema(Singleton.EntityType(), Context.Model); + } + + return new OpenApiSchema + { + UnresolvedReference = true, + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = Singleton.EntityType().FullName() + } + }; + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt index a636852e..9ec0d341 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt @@ -13,6 +13,9 @@ Microsoft.OpenApi.OData.OpenApiConvertSettings.CustomXMLAttributesMapping.get -> Microsoft.OpenApi.OData.OpenApiConvertSettings.CustomXMLAttributesMapping.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths.get -> bool Microsoft.OpenApi.OData.OpenApiConvertSettings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths.set -> void +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseSuccessStatusCodeRange.get -> bool +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseSuccessStatusCodeRange.set -> void +static Microsoft.OpenApi.OData.Common.OpenApiOperationExtensions.AddErrorResponses(this Microsoft.OpenApi.Models.OpenApiOperation operation, Microsoft.OpenApi.OData.OpenApiConvertSettings settings, bool addNoContent = false, Microsoft.OpenApi.Models.OpenApiSchema schema = null) -> void static Microsoft.OpenApi.OData.Edm.EdmTypeExtensions.ShouldPathParameterBeQuoted(this Microsoft.OData.Edm.IEdmType edmType, Microsoft.OpenApi.OData.OpenApiConvertSettings settings) -> bool Microsoft.OpenApi.OData.Edm.IODataPathProvider Microsoft.OpenApi.OData.Edm.IODataPathProvider.CanFilter(Microsoft.OData.Edm.IEdmElement element) -> bool @@ -287,4 +290,3 @@ Microsoft.OpenApi.OData.OpenApiExtensions.OpenApiDeprecationExtension.Date.get - Microsoft.OpenApi.OData.OpenApiExtensions.OpenApiDeprecationExtension.Date.set -> void Microsoft.OpenApi.OData.OpenApiExtensions.OpenApiDeprecationExtension.Write(Microsoft.OpenApi.Writers.IOpenApiWriter writer, Microsoft.OpenApi.OpenApiSpecVersion specVersion) -> void Microsoft.OpenApi.OData.Common.OpenApiOperationExtensions -static Microsoft.OpenApi.OData.Common.OpenApiOperationExtensions.AddErrorResponses(this Microsoft.OpenApi.Models.OpenApiOperation operation, Microsoft.OpenApi.OData.OpenApiConvertSettings settings, bool addNoContent = false) -> void diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyGetOperationHandlerTests.cs index 88cdd928..64598cc2 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyGetOperationHandlerTests.cs @@ -56,9 +56,11 @@ public void CreateComplexPropertyGetOperationReturnsCorrectOperationForSingle(bo } } [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateComplexPropertyGetOperationReturnsCorrectOperationForCollection(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateComplexPropertyGetOperationReturnsCorrectOperationForCollection(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange var model = EntitySetGetOperationHandlerTests.GetEdmModel(""); @@ -67,7 +69,8 @@ public void CreateComplexPropertyGetOperationReturnsCorrectOperationForCollectio var property = entity.FindProperty("AlternativeAddresses"); var settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; var context = new ODataContext(model, settings); var path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType()), new ODataComplexPropertySegment(property as IEdmStructuralProperty)); @@ -85,7 +88,8 @@ public void CreateComplexPropertyGetOperationReturnsCorrectOperationForCollectio Assert.NotNull(get.Responses); Assert.Equal(2, get.Responses.Count); - Assert.Equal(new[] { "200", "default" }, get.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new[] { statusCode, "default" }, get.Responses.Select(r => r.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPatchOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPatchOperationHandlerTests.cs index c378bd8d..2c66ccd1 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPatchOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPatchOperationHandlerTests.cs @@ -14,6 +14,7 @@ namespace Microsoft.OpenApi.OData.Operation.Tests; public class ComplexPropertyPatchOperationHandlerTests { private readonly ComplexPropertyPatchOperationHandler _operationHandler = new(); + [Theory] [InlineData(true)] [InlineData(false)] @@ -56,9 +57,11 @@ public void CreateComplexPropertyDeleteOperationReturnsCorrectOperationForSingle } } [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollection(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateComplexPropertyPatchOperationReturnsCorrectOperationForCollection(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange var model = EntitySetGetOperationHandlerTests.GetEdmModel(""); @@ -67,7 +70,8 @@ public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollecti var property = entity.FindProperty("BillingAddress"); var settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; var context = new ODataContext(model, settings); var path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType()), new ODataComplexPropertySegment(property as IEdmStructuralProperty)); @@ -85,7 +89,17 @@ public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollecti Assert.NotNull(patch.Responses); Assert.Equal(2, patch.Responses.Count); - Assert.Equal(new[] { "204", "default" }, patch.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new[] { statusCode, "default" }, patch.Responses.Select(r => r.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(patch.Responses[statusCode].Content); + } + else + { + Assert.Empty(patch.Responses[statusCode].Content); + } if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPostOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPostOperationHandlerTests.cs index 77e0e5cf..f81005c5 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPostOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPostOperationHandlerTests.cs @@ -30,9 +30,11 @@ public void CreateComplexPropertyPostOperationThrowsForSingle() Assert.Throws(() => _operationHandler.CreateOperation(context, path)); } [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollection(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollection(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange var model = EntitySetPostOperationHandlerTests.GetEdmModel(""); @@ -41,7 +43,8 @@ public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollecti var property = entity.FindProperty("AlternativeAddresses"); var settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; var context = new ODataContext(model, settings); var path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType()), new ODataComplexPropertySegment(property as IEdmStructuralProperty)); @@ -59,7 +62,17 @@ public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollecti Assert.NotNull(post.Responses); Assert.Equal(2, post.Responses.Count); - Assert.Equal(new[] { "204", "default" }, post.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new[] { statusCode, "default" }, post.Responses.Select(r => r.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(post.Responses[statusCode].Content); + } + else + { + Assert.Empty(post.Responses[statusCode].Content); + } if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs index ea168026..fd3cac24 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs @@ -14,10 +14,13 @@ namespace Microsoft.OpenApi.OData.Operation.Tests; public class ComplexPropertyPutOperationHandlerTests { private readonly ComplexPropertyPutOperationHandler _operationHandler = new(); + [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateComplexPropertyDeleteOperationReturnsCorrectOperationForSingle(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateComplexPropertyPutOperationReturnsCorrectOperationForSingle(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange var model = EntitySetGetOperationHandlerTests.GetEdmModel(""); @@ -26,7 +29,8 @@ public void CreateComplexPropertyDeleteOperationReturnsCorrectOperationForSingle var property = entity.FindProperty("BillingAddress"); var settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; var context = new ODataContext(model, settings); var path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType()), new ODataComplexPropertySegment(property as IEdmStructuralProperty)); @@ -44,7 +48,17 @@ public void CreateComplexPropertyDeleteOperationReturnsCorrectOperationForSingle Assert.NotNull(put.Responses); Assert.Equal(2, put.Responses.Count); - Assert.Equal(new[] { "204", "default" }, put.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new[] { statusCode, "default" }, put.Responses.Select(r => r.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(put.Responses[statusCode].Content); + } + else + { + Assert.Empty(put.Responses[statusCode].Content); + } if (enableOperationId) { @@ -58,7 +72,7 @@ public void CreateComplexPropertyDeleteOperationReturnsCorrectOperationForSingle [Theory] [InlineData(true)] [InlineData(false)] - public void CreateComplexPropertyPostOperationReturnsCorrectOperationForCollection(bool enableOperationId) + public void CreateComplexPropertyPutOperationReturnsCorrectOperationForCollection(bool enableOperationId) { // Arrange var model = EntitySetGetOperationHandlerTests.GetEdmModel(""); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs index ba44819a..8869dd6d 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs @@ -18,12 +18,18 @@ public class EdmFunctionImportOperationHandlerTests { private EdmFunctionImportOperationHandler _operationHandler = new EdmFunctionImportOperationHandler(); - [Fact] - public void CreateOperationForEdmFunctionImportReturnsCorrectOperation() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CreateOperationForEdmFunctionImportReturnsCorrectOperation(bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; - ODataContext context = new ODataContext(model); + var settings = new OpenApiConvertSettings + { + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX + }; + ODataContext context = new ODataContext(model, settings); var functionImport = model.EntityContainer.FindOperationImports("GetPersonWithMostFriends").FirstOrDefault(); Assert.NotNull(functionImport); ODataPath path = new ODataPath(new ODataOperationImportSegment(functionImport)); @@ -45,7 +51,8 @@ public void CreateOperationForEdmFunctionImportReturnsCorrectOperation() Assert.Null(operation.RequestBody); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); } [Theory] diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs index 662927d2..5edb1fd9 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs @@ -70,12 +70,18 @@ public void DoesntSetDeprecationInformation() #endregion - [Fact] - public void CreateOperationForEdmFunctionReturnsCorrectOperation() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CreateOperationForEdmFunctionReturnsCorrectOperation(bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; - ODataContext context = new ODataContext(model); + var settings = new OpenApiConvertSettings + { + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX + }; + ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); Assert.NotNull(people); @@ -101,7 +107,8 @@ public void CreateOperationForEdmFunctionReturnsCorrectOperation() Assert.Null(operation.RequestBody); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); } [Fact] diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs index 021a8717..f02a3186 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs @@ -18,16 +18,19 @@ public class EntityGetOperationHandlerTests private EntityGetOperationHandler _operationHandler = new EntityGetOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateEntityGetOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateEntityGetOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EntitySetGetOperationHandlerTests.GetEdmModel(""); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType())); @@ -49,7 +52,8 @@ public void CreateEntityGetOperationReturnsCorrectOperation(bool enableOperation Assert.NotNull(get.Responses); Assert.Equal(2, get.Responses.Count); - Assert.Equal(new[] { "200", "default" }, get.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new[] { statusCode, "default" }, get.Responses.Select(r => r.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs index 97c43760..cdfd9ab6 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs @@ -17,16 +17,19 @@ public class EntityPatchOperationHandlerTests private EntityPatchOperationHandler _operationHandler = new EntityPatchOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateEntityPatchOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateEntityPatchOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EntitySetGetOperationHandlerTests.GetEdmModel(""); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType())); @@ -49,7 +52,17 @@ public void CreateEntityPatchOperationReturnsCorrectOperation(bool enableOperati Assert.NotNull(patch.Responses); Assert.Equal(2, patch.Responses.Count); - Assert.Equal(new[] { "204", "default" }, patch.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new[] { statusCode, "default" }, patch.Responses.Select(r => r.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(patch.Responses[statusCode].Content); + } + else + { + Assert.Empty(patch.Responses[statusCode].Content); + } if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs index b67b4abc..5208e579 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs @@ -17,16 +17,19 @@ public class EntityPutOperationHandlerTests private EntityPutOperationHandler _operationHandler = new EntityPutOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EntitySetGetOperationHandlerTests.GetEdmModel(""); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType())); @@ -49,7 +52,17 @@ public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperation Assert.NotNull(putOperation.Responses); Assert.Equal(2, putOperation.Responses.Count); - Assert.Equal(new[] { "204", "default" }, putOperation.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new[] { statusCode, "default" }, putOperation.Responses.Select(r => r.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(putOperation.Responses[statusCode].Content); + } + else + { + Assert.Empty(putOperation.Responses[statusCode].Content); + } if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs index 792796bb..ea35ff07 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs @@ -21,11 +21,11 @@ public class EntitySetGetOperationHandlerTests private EntitySetGetOperationHandler _operationHandler = new EntitySetGetOperationHandler(); [Theory] - [InlineData(true, true)] - [InlineData(false, true)] - [InlineData(false, false)] - [InlineData(true, false)] - public void CreateEntitySetGetOperationReturnsCorrectOperation(bool enableOperationId, bool enablePagination) + [InlineData(true, true, true)] + [InlineData(false, true, true)] + [InlineData(false, false, false)] + [InlineData(true, false, false)] + public void CreateEntitySetGetOperationReturnsCorrectOperation(bool enableOperationId, bool enablePagination, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = GetEdmModel(""); @@ -33,7 +33,8 @@ public void CreateEntitySetGetOperationReturnsCorrectOperation(bool enableOperat OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableOperationId = enableOperationId, - EnablePagination = enablePagination + EnablePagination = enablePagination, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet)); @@ -53,7 +54,10 @@ public void CreateEntitySetGetOperationReturnsCorrectOperation(bool enableOperat Assert.Equal(8, get.Parameters.Count); Assert.NotNull(get.Responses); - Assert.Equal(2, get.Responses.Count); + Assert.Equal(2, get.Responses.Count); + + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new string[] { statusCode, "default" }, get.Responses.Select(e => e.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs index ccbc420e..dd2dc983 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs @@ -21,11 +21,11 @@ public class EntitySetPostOperationHandlerTests private EntitySetPostOperationHandler _operationHandler = new EntitySetPostOperationHandler(); [Theory] - [InlineData(true, true)] - [InlineData(false, true)] - [InlineData(true, false)] - [InlineData(false, false)] - public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOperationId, bool hasStream) + [InlineData(true, true, true)] + [InlineData(false, true, true)] + [InlineData(true, false, false)] + [InlineData(false, false, false)] + public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOperationId, bool hasStream, bool useHTTPStatusCodeClass2XX) { // Arrange string qualifiedName = CapabilitiesConstants.AcceptableMediaTypes; @@ -37,18 +37,19 @@ public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOpera "; // Assert - VerifyEntitySetPostOperation("", enableOperationId, hasStream); - VerifyEntitySetPostOperation(annotation, enableOperationId, hasStream); + VerifyEntitySetPostOperation("", enableOperationId, hasStream, useHTTPStatusCodeClass2XX); + VerifyEntitySetPostOperation(annotation, enableOperationId, hasStream, useHTTPStatusCodeClass2XX); } - private void VerifyEntitySetPostOperation(string annotation, bool enableOperationId, bool hasStream) + private void VerifyEntitySetPostOperation(string annotation, bool enableOperationId, bool hasStream, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = GetEdmModel(annotation, hasStream); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet)); @@ -70,6 +71,7 @@ private void VerifyEntitySetPostOperation(string annotation, bool enableOperatio Assert.NotNull(post.Responses); Assert.Equal(2, post.Responses.Count); + var statusCode = useHTTPStatusCodeClass2XX ? Constants.StatusCodeClass2XX : Constants.StatusCode201; if (hasStream) { Assert.NotNull(post.RequestBody); @@ -82,9 +84,9 @@ private void VerifyEntitySetPostOperation(string annotation, bool enableOperatio Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); // Response - Assert.Equal(2, post.Responses[Constants.StatusCode201].Content.Keys.Count); - Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey("application/todo")); - Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey(Constants.ApplicationJsonMediaType)); + Assert.Equal(2, post.Responses[statusCode].Content.Keys.Count); + Assert.True(post.Responses[statusCode].Content.ContainsKey("application/todo")); + Assert.True(post.Responses[statusCode].Content.ContainsKey(Constants.ApplicationJsonMediaType)); } else { @@ -94,9 +96,9 @@ private void VerifyEntitySetPostOperation(string annotation, bool enableOperatio Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); // Response - Assert.Equal(2, post.Responses[Constants.StatusCode201].Content.Keys.Count); - Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); - Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey(Constants.ApplicationJsonMediaType)); + Assert.Equal(2, post.Responses[statusCode].Content.Keys.Count); + Assert.True(post.Responses[statusCode].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(post.Responses[statusCode].Content.ContainsKey(Constants.ApplicationJsonMediaType)); } } else diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs index 7779ce49..86adc19b 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs @@ -19,9 +19,11 @@ public class MediaEntityGetOperationHandlerTests private readonly MediaEntityGetOperationHandler _operationalHandler = new MediaEntityGetOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange string qualifiedName = CapabilitiesConstants.AcceptableMediaTypes; @@ -35,17 +37,18 @@ public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOper "; // Assert - VerifyMediaEntityGetOperation("", enableOperationId); - VerifyMediaEntityGetOperation(annotation, enableOperationId); + VerifyMediaEntityGetOperation("", enableOperationId, useHTTPStatusCodeClass2XX); + VerifyMediaEntityGetOperation(annotation, enableOperationId, useHTTPStatusCodeClass2XX); } - private void VerifyMediaEntityGetOperation(string annotation, bool enableOperationId) + private void VerifyMediaEntityGetOperation(string annotation, bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = GetEdmModel(annotation); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); @@ -87,25 +90,26 @@ private void VerifyMediaEntityGetOperation(string annotation, bool enableOperati Assert.NotNull(getOperation2.Responses); Assert.Equal(2, getOperation.Responses.Count); Assert.Equal(2, getOperation2.Responses.Count); - Assert.Equal(new[] { "200", "default" }, getOperation.Responses.Select(r => r.Key)); - Assert.Equal(new[] { "200", "default" }, getOperation2.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? Constants.StatusCodeClass2XX : Constants.StatusCode200; + Assert.Equal(new[] { statusCode, "default" }, getOperation.Responses.Select(r => r.Key)); + Assert.Equal(new[] { statusCode, "default" }, getOperation2.Responses.Select(r => r.Key)); if (!string.IsNullOrEmpty(annotation)) { - Assert.Equal(2, getOperation.Responses[Constants.StatusCode200].Content.Keys.Count); - Assert.True(getOperation.Responses[Constants.StatusCode200].Content.ContainsKey("image/png")); - Assert.True(getOperation.Responses[Constants.StatusCode200].Content.ContainsKey("image/jpeg")); + Assert.Equal(2, getOperation.Responses[statusCode].Content.Keys.Count); + Assert.True(getOperation.Responses[statusCode].Content.ContainsKey("image/png")); + Assert.True(getOperation.Responses[statusCode].Content.ContainsKey("image/jpeg")); Assert.Equal("The logo image.", getOperation.Description); - Assert.Equal(1, getOperation2.Responses[Constants.StatusCode200].Content.Keys.Count); - Assert.True(getOperation2.Responses[Constants.StatusCode200].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.Equal(1, getOperation2.Responses[statusCode].Content.Keys.Count); + Assert.True(getOperation2.Responses[statusCode].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); } else { - Assert.Equal(1, getOperation.Responses[Constants.StatusCode200].Content.Keys.Count); - Assert.Equal(1, getOperation2.Responses[Constants.StatusCode200].Content.Keys.Count); - Assert.True(getOperation.Responses[Constants.StatusCode200].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); - Assert.True(getOperation2.Responses[Constants.StatusCode200].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.Equal(1, getOperation.Responses[statusCode].Content.Keys.Count); + Assert.Equal(1, getOperation2.Responses[statusCode].Content.Keys.Count); + Assert.True(getOperation.Responses[statusCode].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(getOperation2.Responses[statusCode].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); } if (enableOperationId) diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyGetOperationHandlerTests.cs index 8f8b3118..b403b107 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyGetOperationHandlerTests.cs @@ -18,15 +18,18 @@ public class NavigationPropertyGetOperationHandlerTests private NavigationPropertyGetOperationHandler _operationHandler = new NavigationPropertyGetOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateNavigationGetOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateNavigationGetOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -53,7 +56,8 @@ public void CreateNavigationGetOperationReturnsCorrectOperation(bool enableOpera Assert.Null(operation.RequestBody); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPatchOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPatchOperationHandlerTests.cs index 620d4fbe..ed705ede 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPatchOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPatchOperationHandlerTests.cs @@ -18,15 +18,18 @@ public class NavigationPropertyPatchOperationHandlerTests private NavigationPropertyPatchOperationHandler _operationHandler = new NavigationPropertyPatchOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateNavigationPatchOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateNavigationPatchOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -54,7 +57,17 @@ public void CreateNavigationPatchOperationReturnsCorrectOperation(bool enableOpe Assert.Equal("New navigation property values", operation.RequestBody.Description); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "204", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(operation.Responses[statusCode].Content); + } + else + { + Assert.Empty(operation.Responses[statusCode].Content); + } if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPostOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPostOperationHandlerTests.cs index dd2d2c8e..34824c6b 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPostOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPostOperationHandlerTests.cs @@ -18,15 +18,18 @@ public class NavigationPropertyPostOperationHandlerTests private NavigationPropertyPostOperationHandler _operationHandler = new NavigationPropertyPostOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateNavigationPostOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateNavigationPostOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -54,7 +57,8 @@ public void CreateNavigationPostOperationReturnsCorrectOperation(bool enableOper Assert.Equal("New navigation property", operation.RequestBody.Description); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "201", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "201"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPutOperationHandlerTests.cs index f0966898..ddd328f5 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPutOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/NavigationPropertyPutOperationHandlerTests.cs @@ -18,15 +18,18 @@ public class NavigationPropertyPutOperationHandlerTests private NavigationPropertyPutOperationHandler _operationHandler = new NavigationPropertyPutOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateNavigationPutOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateNavigationPutOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -54,7 +57,17 @@ public void CreateNavigationPutOperationReturnsCorrectOperation(bool enableOpera Assert.Equal("New navigation property values", operation.RequestBody.Description); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "204", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(operation.Responses[statusCode].Content); + } + else + { + Assert.Empty(operation.Responses[statusCode].Content); + } if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ODataTypeCastGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ODataTypeCastGetOperationHandlerTests.cs index 06f839fe..2ffba325 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ODataTypeCastGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ODataTypeCastGetOperationHandlerTests.cs @@ -15,11 +15,12 @@ public class ODataTypeCastGetOperationHandlerTests private readonly ODataTypeCastGetOperationHandler _operationHandler = new (); [Theory] - [InlineData(true, true)] - [InlineData(true, false)] - [InlineData(false, true)] - [InlineData(false, false)] - public void CreateODataTypeCastGetOperationReturnsCorrectOperationForCollectionNavigationProperty(bool enableOperationId, bool enablePagination) + [InlineData(true, true, true)] + [InlineData(true, false, true)] + [InlineData(false, true, false)] + [InlineData(false, false, false)] + public void CreateODataTypeCastGetOperationReturnsCorrectOperationForCollectionNavigationProperty( + bool enableOperationId, bool enablePagination, bool useHTTPStatusCodeClass2XX) {// ../People/{id}/Friends/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; @@ -27,6 +28,7 @@ public void CreateODataTypeCastGetOperationReturnsCorrectOperationForCollectionN { EnableOperationId = enableOperationId, EnablePagination = enablePagination, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -59,7 +61,8 @@ public void CreateODataTypeCastGetOperationReturnsCorrectOperationForCollectionN Assert.Equal(2, operation.Extensions.Count); //deprecated, pagination Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { @@ -69,7 +72,7 @@ public void CreateODataTypeCastGetOperationReturnsCorrectOperationForCollectionN { Assert.Null(operation.OperationId); } - Assert.True(operation.Responses.ContainsKey("200")); + Assert.True(operation.Responses.ContainsKey(statusCode)); } [Theory] [InlineData(true, true)] diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefGetOperationHandlerTests.cs index b54705ec..93bcf94e 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefGetOperationHandlerTests.cs @@ -16,15 +16,18 @@ public class RefGetOperationHandlerTests private RefGetOperationHandler _operationHandler = new RefGetOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateNavigationRefGetOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateNavigationRefGetOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -54,7 +57,8 @@ public void CreateNavigationRefGetOperationReturnsCorrectOperation(bool enableOp Assert.Null(operation.RequestBody); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPostOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPostOperationHandlerTests.cs index a6845f94..a38be62d 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPostOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPostOperationHandlerTests.cs @@ -16,15 +16,18 @@ public class RefPostOperationHandlerTests private RefPostOperationHandler _operationHandler = new RefPostOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateNavigationRefPostOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateNavigationRefPostOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -55,7 +58,8 @@ public void CreateNavigationRefPostOperationReturnsCorrectOperation(bool enableO Assert.Equal("New navigation property ref value", operation.RequestBody.Description); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "201", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "201"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPutOperationHandlerTests.cs index ff953438..12ada3b2 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPutOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPutOperationHandlerTests.cs @@ -16,15 +16,18 @@ public class RefPutOperationHandlerTests private RefPutOperationHandler _operationHandler = new RefPutOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateNavigationRefPutOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateNavigationRefPutOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); @@ -55,7 +58,8 @@ public void CreateNavigationRefPutOperationReturnsCorrectOperation(bool enableOp Assert.Equal("New navigation property ref values", operation.RequestBody.Description); Assert.Equal(2, operation.Responses.Count); - Assert.Equal(new string[] { "204", "default" }, operation.Responses.Select(e => e.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs index d4d3a30a..acff34e1 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs @@ -22,9 +22,11 @@ public class SingletonGetOperationHandlerTests private SingletonGetOperationHandler _operationHandler = new SingletonGetOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateSingletonGetOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateSingletonGetOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange string annotation = @" @@ -38,7 +40,8 @@ public void CreateSingletonGetOperationReturnsCorrectOperation(bool enableOperat IEdmSingleton singleton = model.EntityContainer.FindSingleton("Me"); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(singleton)); @@ -61,7 +64,8 @@ public void CreateSingletonGetOperationReturnsCorrectOperation(bool enableOperat Assert.NotNull(get.Responses); Assert.Equal(2, get.Responses.Count); - Assert.Equal(new[] { "200", "default" }, get.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "200"; + Assert.Equal(new[] { statusCode, "default" }, get.Responses.Select(r => r.Key)); if (enableOperationId) { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs index dba73e73..ca8d3f7a 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs @@ -19,9 +19,11 @@ public class SingletonPatchOperationHandlerTests private SingletonPatchOperationHandler _operationHandler = new SingletonPatchOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateSingletonPatchOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateSingletonPatchOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange string annotation = @" @@ -35,7 +37,8 @@ public void CreateSingletonPatchOperationReturnsCorrectOperation(bool enableOper IEdmSingleton singleton = model.EntityContainer.FindSingleton("Me"); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(singleton)); @@ -56,7 +59,17 @@ public void CreateSingletonPatchOperationReturnsCorrectOperation(bool enableOper Assert.NotNull(patch.Responses); Assert.Equal(2, patch.Responses.Count); - Assert.Equal(new[] { "204", "default" }, patch.Responses.Select(r => r.Key)); + var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; + Assert.Equal(new[] { statusCode, "default" }, patch.Responses.Select(r => r.Key)); + + if (useHTTPStatusCodeClass2XX) + { + Assert.Single(patch.Responses[statusCode].Content); + } + else + { + Assert.Empty(patch.Responses[statusCode].Content); + } if (enableOperationId) {