diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmTypeExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmTypeExtensions.cs new file mode 100644 index 00000000..bb728848 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmTypeExtensions.cs @@ -0,0 +1,37 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OData.Edm; + +namespace Microsoft.OpenApi.OData.Edm +{ + /// + /// Extension methods for + /// + public static class EdmTypeExtensions + { + /// + /// Determines wether a path parameter should be wrapped in quotes based on the type of the parameter. + /// + /// The type of the parameter. + /// The conversion settings. + /// True if the parameter should be wrapped in quotes, false otherwise. + public static bool ShouldPathParameterBeQuoted(this IEdmType edmType, OpenApiConvertSettings settings) + { + if (edmType == null || settings == null || !settings.AddSingleQuotesForStringParameters) + { + return false; + } + + return edmType.TypeKind switch + { + EdmTypeKind.Enum => true, + EdmTypeKind.Primitive when edmType.IsString() || edmType.IsTemporal() => true, + _ => false, + }; + } + } + +} \ No newline at end of file diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs index 59bf3ef6..1add0574 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs @@ -77,13 +77,7 @@ public override string GetPathItemName(OpenApiConvertSettings settings, HashSet< } else { - IList keyStrings = new List(); - foreach (var key in KeyMappings) - { - keyStrings.Add(key.Key + "={" + key.Value + "}"); - } - - return String.Join(",", keyStrings); + return string.Join(",", KeyMappings.Select(x => x.Key + "='{" + x.Value + "}'")); } } @@ -109,7 +103,8 @@ public override string GetPathItemName(OpenApiConvertSettings settings, HashSet< foreach (var keyProperty in keys) { string name = Utils.GetUniqueName(keyProperty.Name, parameters); - keyStrings.Add(keyProperty.Name + "={" + name + "}"); + var quote = keyProperty.Type.Definition.ShouldPathParameterBeQuoted(settings) ? "'" : string.Empty; + keyStrings.Add($"{keyProperty.Name}={quote}{{{name}}}{quote}"); } return String.Join(",", keyStrings); diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs index 0aa44a48..8eb6c4d9 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationImportSegment.cs @@ -83,7 +83,8 @@ private string FunctionImportName(IEdmFunctionImport functionImport, OpenApiConv } else { - return p.Name + "={" + uniqueName + "}"; + var quote = p.Type.Definition.ShouldPathParameterBeQuoted(settings) ? "'" : string.Empty; + return $"{p.Name}={quote}{{{uniqueName}}}{quote}"; } }))); diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs index baae828b..d64fd0bd 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs @@ -148,7 +148,8 @@ private string FunctionName(IEdmFunction function, OpenApiConvertSettings settin } else { - return p.Name + "={" + uniqueName + "}"; + var quote = p.Type.Definition.ShouldPathParameterBeQuoted(settings) ? "'" : string.Empty; + return p.Name + $"={quote}{{{uniqueName}}}{quote}"; } }))); diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs index e79ddcc5..c5567697 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs @@ -26,7 +26,7 @@ public enum ODataPathKind Singleton, /// - /// Represents an operation (function or action) path, for example: ~/users/NS.findRooms(roomId={roomId}) + /// Represents an operation (function or action) path, for example: ~/users/NS.findRooms(roomId='{roomId}') /// Operation, diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs index 3427d024..85bf8fd4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs @@ -297,7 +297,7 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr { // Non-Contained // Single-Valued: ~/entityset/{key}/single-valued-Nav/$ref - // Collection-valued: ~/entityset/{key}/collection-valued-Nav/$ref?$id ={navKey} + // Collection-valued: ~/entityset/{key}/collection-valued-Nav/$ref?$id='{navKey}' CreateRefPath(currentPath); if (targetsMany) diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs index aa62303e..8b6abdce 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs @@ -136,7 +136,8 @@ public static IList CreateParameters(this ODataContext context if (parameterNameMapping != null) { - parameter.Description = $"Usage: {edmParameter.Name}={{{parameterNameMapping[edmParameter.Name]}}}"; + var quote = edmParameter.Type.Definition.ShouldPathParameterBeQuoted(context.Settings) ? "'" : string.Empty; + parameter.Description = $"Usage: {edmParameter.Name}={quote}{{{parameterNameMapping[edmParameter.Name]}}}{quote}"; } parameters.Add(parameter); @@ -203,7 +204,8 @@ public static IList CreateKeyParameters(this ODataContext cont if (keySegment.KeyMappings != null) { - parameter.Description = parameter.Description + $", {keyProperty.Name}={{{parameter.Name}}}"; + var quote = keyProperty.Type.Definition.ShouldPathParameterBeQuoted(context.Settings) ? "'" : string.Empty; + parameter.Description += $", {keyProperty.Name}={quote}{{{parameter.Name}}}{quote}"; } parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name)); diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs index be319c33..e5faf574 100644 --- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs @@ -188,6 +188,11 @@ public string PathPrefix /// public bool EnableDollarCountPath { get; set; } = true; + /// + /// Gets/sets a value indicating whether or not single quotes surrounding string parameters in url templates should be added. + /// + public bool AddSingleQuotesForStringParameters { get; set; } = false; + internal OpenApiConvertSettings Clone() { var newSettings = new OpenApiConvertSettings @@ -219,6 +224,7 @@ internal OpenApiConvertSettings Clone() ShowRootPath = this.ShowRootPath, PathProvider = this.PathProvider, EnableDollarCountPath = this.EnableDollarCountPath, + AddSingleQuotesForStringParameters = this.AddSingleQuotesForStringParameters, }; return newSettings; diff --git a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt index 97ec543c..e067bf0c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt @@ -3,6 +3,8 @@ abstract Microsoft.OpenApi.OData.Edm.ODataSegment.Identifier.get -> string abstract Microsoft.OpenApi.OData.Edm.ODataSegment.Kind.get -> Microsoft.OpenApi.OData.Edm.ODataSegmentKind Microsoft.OpenApi.OData.Common.Utils Microsoft.OpenApi.OData.Edm.EdmModelExtensions +Microsoft.OpenApi.OData.Edm.EdmTypeExtensions +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 Microsoft.OpenApi.OData.Edm.IODataPathProvider.GetPaths(Microsoft.OData.Edm.IEdmModel model, Microsoft.OpenApi.OData.OpenApiConvertSettings settings) -> System.Collections.Generic.IEnumerable @@ -130,6 +132,8 @@ Microsoft.OpenApi.OData.OpenApiConvertSettings.PathProvider.get -> Microsoft.Ope Microsoft.OpenApi.OData.OpenApiConvertSettings.PathProvider.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.EnableDollarCountPath.get -> bool Microsoft.OpenApi.OData.OpenApiConvertSettings.EnableDollarCountPath.set -> void +Microsoft.OpenApi.OData.OpenApiConvertSettings.AddSingleQuotesForStringParameters.get -> bool +Microsoft.OpenApi.OData.OpenApiConvertSettings.AddSingleQuotesForStringParameters.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.PrefixEntityTypeNameBeforeKey.get -> bool Microsoft.OpenApi.OData.OpenApiConvertSettings.PrefixEntityTypeNameBeforeKey.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.RequireDerivedTypesConstraintForBoundOperations.get -> bool diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataKeySegmentTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataKeySegmentTests.cs index c57fdb14..a0318779 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataKeySegmentTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataKeySegmentTests.cs @@ -71,19 +71,22 @@ public void GetPathItemNameReturnsCorrectKeyLiteralForSimpleKey(bool prefix, str } [Theory] - [InlineData(true)] - [InlineData(false)] - public void GetPathItemNameReturnsCorrectKeyLiteralForCompositeKey(bool prefix) + [InlineData(true, true, "firstName='{firstName}',lastName='{lastName}'")] + [InlineData(false, true, "firstName='{firstName}',lastName='{lastName}'")] + [InlineData(true, false, "firstName={firstName},lastName={lastName}")] + [InlineData(false, false, "firstName={firstName},lastName={lastName}")] + public void GetPathItemNameReturnsCorrectKeyLiteralForCompositeKey(bool prefix, bool addQuotes, string expected) { // Arrange & Act ODataKeySegment segment = new ODataKeySegment(_customer); OpenApiConvertSettings settings = new OpenApiConvertSettings { - PrefixEntityTypeNameBeforeKey = prefix + PrefixEntityTypeNameBeforeKey = prefix, + AddSingleQuotesForStringParameters = addQuotes, }; // Assert - Assert.Equal("firstName={firstName},lastName={lastName}", segment.GetPathItemName(settings)); + Assert.Equal(expected, segment.GetPathItemName(settings)); } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationImportSegmentTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationImportSegmentTests.cs index 504f8a01..257ffe11 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationImportSegmentTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationImportSegmentTests.cs @@ -80,8 +80,10 @@ public void GetPathItemNameReturnsCorrectFunctionImportLiteral() var segment = new ODataOperationImportSegment(_functionImport); // Assert - Assert.Equal("MyFunction(firstName={firstName},lastName={lastName})", - segment.GetPathItemName(new OpenApiConvertSettings())); + Assert.Equal("MyFunction(firstName='{firstName}',lastName='{lastName}')", + segment.GetPathItemName(new OpenApiConvertSettings() { + AddSingleQuotesForStringParameters = true + })); } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs index 198943ab..12f6254e 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataOperationSegmentTests.cs @@ -98,9 +98,9 @@ public void GetPathItemNameReturnsCorrectFunctionLiteral(bool unqualifiedCall, b [Theory] [InlineData(true, true, "{param}")] - [InlineData(true, false, "NS.MyFunction(param={param})")] - [InlineData(false, true, "NS.MyFunction(param={param})")] - [InlineData(false, false, "NS.MyFunction(param={param})")] + [InlineData(true, false, "NS.MyFunction(param='{param}')")] + [InlineData(false, true, "NS.MyFunction(param='{param}')")] + [InlineData(false, false, "NS.MyFunction(param='{param}')")] public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedFunction(bool isEscapedFunction, bool enableEscapeFunctionCall, string expected) { // Arrange & Act @@ -112,7 +112,8 @@ public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedFunction(bool var segment = new ODataOperationSegment(boundFunction, isEscapedFunction); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableUriEscapeFunctionCall = enableEscapeFunctionCall + EnableUriEscapeFunctionCall = enableEscapeFunctionCall, + AddSingleQuotesForStringParameters = true, }; // Assert @@ -121,9 +122,9 @@ public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedFunction(bool [Theory] [InlineData(true, true, "{param}:")] - [InlineData(true, false, "NS.MyFunction(param={param})")] - [InlineData(false, true, "NS.MyFunction(param={param})")] - [InlineData(false, false, "NS.MyFunction(param={param})")] + [InlineData(true, false, "NS.MyFunction(param='{param}')")] + [InlineData(false, true, "NS.MyFunction(param='{param}')")] + [InlineData(false, false, "NS.MyFunction(param='{param}')")] public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedComposableFunction(bool isEscapedFunction, bool enableEscapeFunctionCall, string expected) { // Arrange & Act @@ -135,7 +136,8 @@ public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedComposableFunc var segment = new ODataOperationSegment(boundFunction, isEscapedFunction); OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableUriEscapeFunctionCall = enableEscapeFunctionCall + EnableUriEscapeFunctionCall = enableEscapeFunctionCall, + AddSingleQuotesForStringParameters = true }; // Assert diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs index 57045cda..39bf6c09 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs @@ -249,10 +249,10 @@ public void GetPathItemNameReturnsCorrectWithSingleKeySegment(bool keyAsSegment, } [Theory] - [InlineData(true, true, "/Customers/FirstName={FirstName},LastName={LastName}")] - [InlineData(true, false, "/Customers/FirstName={FirstName},LastName={LastName}")] - [InlineData(false, true, "/Customers(FirstName={FirstName},LastName={LastName})")] - [InlineData(false, false, "/Customers(FirstName={FirstName},LastName={LastName})")] + [InlineData(true, true, "/Customers/FirstName='{FirstName}',LastName='{LastName}'")] + [InlineData(true, false, "/Customers/FirstName='{FirstName}',LastName='{LastName}'")] + [InlineData(false, true, "/Customers(FirstName='{FirstName}',LastName='{LastName}')")] + [InlineData(false, false, "/Customers(FirstName='{FirstName}',LastName='{LastName}')")] public void GetPathItemNameReturnsCorrectStringWithMultipleKeySegment(bool keyAsSegment, bool prefix, string expected) { // Arrange @@ -262,7 +262,8 @@ public void GetPathItemNameReturnsCorrectStringWithMultipleKeySegment(bool keyAs OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableKeyAsSegment = keyAsSegment, - PrefixEntityTypeNameBeforeKey = prefix + PrefixEntityTypeNameBeforeKey = prefix, + AddSingleQuotesForStringParameters = true, }; // Act diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs index ebb661cb..0a71c2ec 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs @@ -208,7 +208,8 @@ public void TripServiceMetadataToOpenApiJsonWorks(OpenApiSpecVersion specVersion Version = new Version(1, 0, 1), ServiceRoot = new Uri("http://services.odata.org/TrippinRESTierService"), IEEE754Compatible = true, - OpenApiSpecVersion = specVersion + OpenApiSpecVersion = specVersion, + AddSingleQuotesForStringParameters = true, }; // Act string json = WriteEdmModelAsOpenApi(model, OpenApiFormat.Json, settings); @@ -239,7 +240,8 @@ public void TripServiceMetadataToOpenApiYamlWorks(OpenApiSpecVersion specVersion Version = new Version(1, 0, 1), ServiceRoot = new Uri("http://services.odata.org/TrippinRESTierService"), IEEE754Compatible = true, - OpenApiSpecVersion = specVersion + OpenApiSpecVersion = specVersion, + AddSingleQuotesForStringParameters = true, }; // Act diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs index 9eae7de1..6eeccac2 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs @@ -75,12 +75,12 @@ public void CreatePathItemsReturnsForBasicModel() [InlineData(true, true, true, "/Customers({ID}):/{param}:")] [InlineData(true, true, false, "/Customers({ID}):/{param}")] - [InlineData(true, false, true, "/Customers({ID})/NS.MyFunction(param={param})")] - [InlineData(true, false, false, "/Customers({ID})/NS.MyFunction(param={param})")] - [InlineData(false, true, true, "/Customers({ID})/NS.MyFunction(param={param})")] - [InlineData(false, true, false, "/Customers({ID})/NS.MyFunction(param={param})")] - [InlineData(false, false, true, "/Customers({ID})/NS.MyFunction(param={param})")] - [InlineData(false, false, false, "/Customers({ID})/NS.MyFunction(param={param})")] + [InlineData(true, false, true, "/Customers({ID})/NS.MyFunction(param='{param}')")] + [InlineData(true, false, false, "/Customers({ID})/NS.MyFunction(param='{param}')")] + [InlineData(false, true, true, "/Customers({ID})/NS.MyFunction(param='{param}')")] + [InlineData(false, true, false, "/Customers({ID})/NS.MyFunction(param='{param}')")] + [InlineData(false, false, true, "/Customers({ID})/NS.MyFunction(param='{param}')")] + [InlineData(false, false, false, "/Customers({ID})/NS.MyFunction(param='{param}')")] public void CreatePathItemsReturnsForEscapeFunctionModel(bool enableEscaped, bool hasEscapedAnnotation, bool isComposable, string expected) { // Arrange @@ -108,7 +108,8 @@ public void CreatePathItemsReturnsForEscapeFunctionModel(bool enableEscaped, boo OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableUriEscapeFunctionCall = enableEscaped + EnableUriEscapeFunctionCall = enableEscaped, + AddSingleQuotesForStringParameters = true, }; ODataContext context = new ODataContext(model, settings); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs index 4ce92f90..ba44819a 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs @@ -120,7 +120,8 @@ public void CreateOperationIdWithSHA5ForOverloadEdmFunctionImport(bool enableOpe OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + AddSingleQuotesForStringParameters = true, }; ODataContext context = new ODataContext(model, settings); @@ -134,7 +135,7 @@ public void CreateOperationIdWithSHA5ForOverloadEdmFunctionImport(bool enableOpe if (enableOperationId) { - Assert.Equal("FunctionImport.MyFunction-3e3f", operation.OperationId); + Assert.Equal("FunctionImport.MyFunction-cc1c", operation.OperationId); } else { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs index e48d7f0f..2f918782 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs @@ -213,7 +213,8 @@ public void CreateOperationForOverloadEdmFunctionReturnsCorrectOperationId(bool OpenApiConvertSettings settings = new OpenApiConvertSettings { - EnableOperationId = enableOperationId + EnableOperationId = enableOperationId, + AddSingleQuotesForStringParameters = true, }; ODataContext context = new ODataContext(model, settings); @@ -229,7 +230,7 @@ public void CreateOperationForOverloadEdmFunctionReturnsCorrectOperationId(bool if (enableOperationId) { - Assert.Equal("Customers.Customer.MyFunction-28ae", operation.OperationId); + Assert.Equal("Customers.Customer.MyFunction-df74", operation.OperationId); } else { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json index 31c8c740..9e91ea9e 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json @@ -1,4 +1,4 @@ -{ +{ "swagger": "2.0", "info": { "title": "OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models", @@ -1206,7 +1206,7 @@ "x-ms-docs-operation-type": "function" } }, - "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { + "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": { "get": { "tags": [ "Me.Functions" @@ -1220,7 +1220,7 @@ { "in": "path", "name": "userName", - "description": "Usage: userName={userName}", + "description": "Usage: userName='{userName}'", "required": true, "type": "string" } @@ -1350,7 +1350,7 @@ "x-ms-docs-operation-type": "action" } }, - "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": { "get": { "tags": [ "Me.Functions" @@ -1364,7 +1364,7 @@ { "in": "path", "name": "lastName", - "description": "Usage: lastName={lastName}", + "description": "Usage: lastName='{lastName}'", "required": true, "type": "string" } @@ -2949,7 +2949,7 @@ "x-ms-docs-operation-type": "function" } }, - "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { + "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": { "get": { "tags": [ "NewComePeople.Functions" @@ -2971,7 +2971,7 @@ { "in": "path", "name": "userName", - "description": "Usage: userName={userName}", + "description": "Usage: userName='{userName}'", "required": true, "type": "string" } @@ -3117,7 +3117,7 @@ "x-ms-docs-operation-type": "action" } }, - "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": { "get": { "tags": [ "NewComePeople.Functions" @@ -3139,7 +3139,7 @@ { "in": "path", "name": "lastName", - "description": "Usage: lastName={lastName}", + "description": "Usage: lastName='{lastName}'", "required": true, "type": "string" } @@ -4842,7 +4842,7 @@ "x-ms-docs-operation-type": "function" } }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": { "get": { "tags": [ "People.Functions" @@ -4864,7 +4864,7 @@ { "in": "path", "name": "userName", - "description": "Usage: userName={userName}", + "description": "Usage: userName='{userName}'", "required": true, "type": "string" } @@ -5010,7 +5010,7 @@ "x-ms-docs-operation-type": "action" } }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": { "get": { "tags": [ "People.Functions" @@ -5032,7 +5032,7 @@ { "in": "path", "name": "lastName", - "description": "Usage: lastName={lastName}", + "description": "Usage: lastName='{lastName}'", "required": true, "type": "string" } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml index 9f81cb60..0a4631f7 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml @@ -1,4 +1,4 @@ -swagger: '2.0' +swagger: '2.0' info: title: OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models description: This OData service is located at http://services.odata.org/TrippinRESTierService @@ -822,7 +822,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: function - '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})': + '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')': get: tags: - Me.Functions @@ -833,7 +833,7 @@ paths: parameters: - in: path name: userName - description: 'Usage: userName={userName}' + description: 'Usage: userName=''{userName}''' required: true type: string responses: @@ -919,7 +919,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: action - '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})': + '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')': get: tags: - Me.Functions @@ -930,7 +930,7 @@ paths: parameters: - in: path name: lastName - description: 'Usage: lastName={lastName}' + description: 'Usage: lastName=''{lastName}''' required: true type: string responses: @@ -2038,7 +2038,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: function - '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})': + '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')': get: tags: - NewComePeople.Functions @@ -2055,7 +2055,7 @@ paths: x-ms-docs-key-type: Person - in: path name: userName - description: 'Usage: userName={userName}' + description: 'Usage: userName=''{userName}''' required: true type: string responses: @@ -2153,7 +2153,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: action - '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})': + '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')': get: tags: - NewComePeople.Functions @@ -2170,7 +2170,7 @@ paths: x-ms-docs-key-type: Person - in: path name: lastName - description: 'Usage: lastName={lastName}' + description: 'Usage: lastName=''{lastName}''' required: true type: string responses: @@ -3364,7 +3364,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: function - '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})': + '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')': get: tags: - People.Functions @@ -3381,7 +3381,7 @@ paths: x-ms-docs-key-type: Person - in: path name: userName - description: 'Usage: userName={userName}' + description: 'Usage: userName=''{userName}''' required: true type: string responses: @@ -3479,7 +3479,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: action - '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})': + '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')': get: tags: - People.Functions @@ -3496,7 +3496,7 @@ paths: x-ms-docs-key-type: Person - in: path name: lastName - description: 'Usage: lastName={lastName}' + description: 'Usage: lastName=''{lastName}''' required: true type: string responses: diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json index c74a395c..1652d7d4 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json @@ -1,4 +1,4 @@ -{ +{ "openapi": "3.0.1", "info": { "title": "OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models", @@ -1370,7 +1370,7 @@ "x-ms-docs-operation-type": "function" } }, - "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { + "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": { "get": { "tags": [ "Me.Functions" @@ -1381,7 +1381,7 @@ { "name": "userName", "in": "path", - "description": "Usage: userName={userName}", + "description": "Usage: userName='{userName}'", "required": true, "schema": { "type": "string" @@ -1522,7 +1522,7 @@ "x-ms-docs-operation-type": "action" } }, - "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": { "get": { "tags": [ "Me.Functions" @@ -1533,7 +1533,7 @@ { "name": "lastName", "in": "path", - "description": "Usage: lastName={lastName}", + "description": "Usage: lastName='{lastName}'", "required": true, "schema": { "type": "string" @@ -3304,7 +3304,7 @@ "x-ms-docs-operation-type": "function" } }, - "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { + "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": { "get": { "tags": [ "NewComePeople.Functions" @@ -3325,7 +3325,7 @@ { "name": "userName", "in": "path", - "description": "Usage: userName={userName}", + "description": "Usage: userName='{userName}'", "required": true, "schema": { "type": "string" @@ -3490,7 +3490,7 @@ "x-ms-docs-operation-type": "action" } }, - "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": { "get": { "tags": [ "NewComePeople.Functions" @@ -3511,7 +3511,7 @@ { "name": "lastName", "in": "path", - "description": "Usage: lastName={lastName}", + "description": "Usage: lastName='{lastName}'", "required": true, "schema": { "type": "string" @@ -5427,7 +5427,7 @@ "x-ms-docs-operation-type": "function" } }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": { "get": { "tags": [ "People.Functions" @@ -5448,7 +5448,7 @@ { "name": "userName", "in": "path", - "description": "Usage: userName={userName}", + "description": "Usage: userName='{userName}'", "required": true, "schema": { "type": "string" @@ -5613,7 +5613,7 @@ "x-ms-docs-operation-type": "action" } }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": { "get": { "tags": [ "People.Functions" @@ -5634,7 +5634,7 @@ { "name": "lastName", "in": "path", - "description": "Usage: lastName={lastName}", + "description": "Usage: lastName='{lastName}'", "required": true, "schema": { "type": "string" diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml index 1003e1a1..cf22387a 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.1 +openapi: 3.0.1 info: title: OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models description: This OData service is located at http://services.odata.org/TrippinRESTierService @@ -914,7 +914,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: function - '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})': + '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')': get: tags: - Me.Functions @@ -923,7 +923,7 @@ paths: parameters: - name: userName in: path - description: 'Usage: userName={userName}' + description: 'Usage: userName=''{userName}''' required: true schema: type: string @@ -1012,7 +1012,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: action - '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})': + '/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')': get: tags: - Me.Functions @@ -1021,7 +1021,7 @@ paths: parameters: - name: lastName in: path - description: 'Usage: lastName={lastName}' + description: 'Usage: lastName=''{lastName}''' required: true schema: type: string @@ -2238,7 +2238,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: function - '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})': + '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')': get: tags: - NewComePeople.Functions @@ -2254,7 +2254,7 @@ paths: x-ms-docs-key-type: Person - name: userName in: path - description: 'Usage: userName={userName}' + description: 'Usage: userName=''{userName}''' required: true schema: type: string @@ -2359,7 +2359,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: action - '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})': + '/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')': get: tags: - NewComePeople.Functions @@ -2375,7 +2375,7 @@ paths: x-ms-docs-key-type: Person - name: lastName in: path - description: 'Usage: lastName={lastName}' + description: 'Usage: lastName=''{lastName}''' required: true schema: type: string @@ -3691,7 +3691,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: function - '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})': + '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')': get: tags: - People.Functions @@ -3707,7 +3707,7 @@ paths: x-ms-docs-key-type: Person - name: userName in: path - description: 'Usage: userName={userName}' + description: 'Usage: userName=''{userName}''' required: true schema: type: string @@ -3812,7 +3812,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: action - '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})': + '/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')': get: tags: - People.Functions @@ -3828,7 +3828,7 @@ paths: x-ms-docs-key-type: Person - name: lastName in: path - description: 'Usage: lastName={lastName}' + description: 'Usage: lastName=''{lastName}''' required: true schema: type: string