From ca899f39902ab28d2fd392e80b3ce812e8f82491 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 6 Jan 2026 14:10:51 -0500 Subject: [PATCH 01/11] ci: removes outdated compilation files causing failure --- Build.props | 2 - Microsoft.OpenApi.OData.sln | 15 +-- tool/After.Common.targets | 105 --------------------- tool/Before.Common.targets | 27 ------ tool/Build.props | 30 ------ tool/GetNugetPackageMetadata.proj | 14 --- tool/PoliCheck/RunPoliCheck.ps1 | 34 ------- tool/UpdateDocs/Program.cs | 88 ----------------- tool/UpdateDocs/Properties/AssemblyInfo.cs | 36 ------- tool/UpdateDocs/UpdateDocs.csproj | 17 ---- tool/versioning.props | 52 ---------- 11 files changed, 2 insertions(+), 418 deletions(-) delete mode 100644 tool/After.Common.targets delete mode 100644 tool/Before.Common.targets delete mode 100644 tool/Build.props delete mode 100644 tool/GetNugetPackageMetadata.proj delete mode 100644 tool/PoliCheck/RunPoliCheck.ps1 delete mode 100644 tool/UpdateDocs/Program.cs delete mode 100644 tool/UpdateDocs/Properties/AssemblyInfo.cs delete mode 100644 tool/UpdateDocs/UpdateDocs.csproj delete mode 100644 tool/versioning.props diff --git a/Build.props b/Build.props index 2bf36d01..16042ae9 100644 --- a/Build.props +++ b/Build.props @@ -15,6 +15,4 @@ $(MSBuildThisFileDirectory.TrimEnd('\')) - - diff --git a/Microsoft.OpenApi.OData.sln b/Microsoft.OpenApi.OData.sln index a385330d..085f0a15 100644 --- a/Microsoft.OpenApi.OData.sln +++ b/Microsoft.OpenApi.OData.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30907.101 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.OData.Reader", "src\Microsoft.OpenApi.OData.Reader\Microsoft.OpenAPI.OData.Reader.csproj", "{FF3ACD93-19E0-486C-9C0F-FA1C2E7FC8C2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenAPI.OData.Reader", "src\Microsoft.OpenApi.OData.Reader\Microsoft.OpenAPI.OData.Reader.csproj", "{FF3ACD93-19E0-486C-9C0F-FA1C2E7FC8C2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.OData.Reader.Tests", "test\Microsoft.OpenAPI.OData.Reader.Tests\Microsoft.OpenAPI.OData.Reader.Tests.csproj", "{90A98718-75EB-4E2B-A51E-66ACF66F15B4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenAPI.OData.Reader.Tests", "test\Microsoft.OpenAPI.OData.Reader.Tests\Microsoft.OpenAPI.OData.Reader.Tests.csproj", "{90A98718-75EB-4E2B-A51E-66ACF66F15B4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OoasUtil", "src\OoasUtil\OoasUtil.csproj", "{2D06C660-B550-432C-8062-D4070F7C371F}" EndProject @@ -16,10 +16,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tool", "tool", "{DE8F8E75-A119-4CF3-AFDD-4132B55DAE76}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateDocs", "tool\UpdateDocs\UpdateDocs.csproj", "{AAC31ECB-05F9-444A-9B86-42ECD50AA468}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -42,10 +38,6 @@ Global {79B190E8-EDB0-4C03-8FD8-EB48E4807CFB}.Debug|Any CPU.Build.0 = Debug|Any CPU {79B190E8-EDB0-4C03-8FD8-EB48E4807CFB}.Release|Any CPU.ActiveCfg = Release|Any CPU {79B190E8-EDB0-4C03-8FD8-EB48E4807CFB}.Release|Any CPU.Build.0 = Release|Any CPU - {AAC31ECB-05F9-444A-9B86-42ECD50AA468}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AAC31ECB-05F9-444A-9B86-42ECD50AA468}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AAC31ECB-05F9-444A-9B86-42ECD50AA468}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AAC31ECB-05F9-444A-9B86-42ECD50AA468}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -53,7 +45,4 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9AE22713-F94E-45CA-81F4-0806CA195B69} EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {AAC31ECB-05F9-444A-9B86-42ECD50AA468} = {DE8F8E75-A119-4CF3-AFDD-4132B55DAE76} - EndGlobalSection EndGlobal diff --git a/tool/After.Common.targets b/tool/After.Common.targets deleted file mode 100644 index 6bad46e4..00000000 --- a/tool/After.Common.targets +++ /dev/null @@ -1,105 +0,0 @@ - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - GenerateAssemblyAttributeFile; - ExcludeAssemblyFilesFromSourceAnalysis; - $(BuildDependsOn); - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - UNDEFINED_GenerateAssemblyAttributeTemplate - -using System.Reflection; -using System.Resources; - -[assembly: AssemblyDescription("%AssemblyNameFull%")] -[assembly: AssemblyTitle("%AssemblyNameFull%")] -[assembly: AssemblyDefaultAlias("%AssemblyNameFull%")] -[assembly: AssemblyFileVersion("%VersionFull%")] -[assembly: AssemblyInformationalVersion("%VersionFull%")] -[assembly: AssemblyVersion("%VersionFullSemantic%")] -[assembly: SatelliteContractVersion("%VersionFull%")] -[assembly: AssemblyMetadata("Serviceable", "True")] - - - - - - $(GenerateAssemblyAttributeTemplateCSharp) - - - - $(IntermediateOutputPath.TrimEnd("\\"))\OpenApiODataAssemblyAttributes$(DefaultLanguageSourceExtension) - $(AssemblyName)$(TargetExt) - $([System.String]::Copy('$(GenerateAssemblyAttributeTemplate)').Replace("%25AssemblyNameFull%25",$(AssemblyNameFull)).Replace("%25VersionFull%25",$(VersionFull)).Replace("%25VersionFullSemantic%25",$(VersionFullSemantic))) - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tool/Before.Common.targets b/tool/Before.Common.targets deleted file mode 100644 index a54c3e71..00000000 --- a/tool/Before.Common.targets +++ /dev/null @@ -1,27 +0,0 @@ - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - $(VersionRunBeforeTargets);CoreCompile - - $(EnlistmentRoot)\src\AssemblyInfo - - AssemblyInfoCommon$(DefaultLanguageSourceExtension) - - - - - - true - $(AssemblyInfoCommonFile) - - - - diff --git a/tool/Build.props b/tool/Build.props deleted file mode 100644 index 3403d53e..00000000 --- a/tool/Build.props +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root)) - - $(EnlistmentRoot)\tool - - - - - - - - $(MSBuildThisFileDirectory)Before.Common.targets - - $(MSBuildThisFileDirectory)After.Common.targets - - - diff --git a/tool/GetNugetPackageMetadata.proj b/tool/GetNugetPackageMetadata.proj deleted file mode 100644 index 5f120f9a..00000000 --- a/tool/GetNugetPackageMetadata.proj +++ /dev/null @@ -1,14 +0,0 @@ - - - - $([System.DateTime]::Now.ToString("yyyyMMddHHmm")) - - - - - - - - - - \ No newline at end of file diff --git a/tool/PoliCheck/RunPoliCheck.ps1 b/tool/PoliCheck/RunPoliCheck.ps1 deleted file mode 100644 index 3eb663fb..00000000 --- a/tool/PoliCheck/RunPoliCheck.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -param( - [string]$BuildSourceDir, - [string]$folderName, - [string]$branchName, - [string]$resultRoot, - [string]$PoliCheckPath -) - -# -#Example: -# RunPoliCheck.ps1 -BuildSourceDir "C:\BuildAgent\_work\32\s" -# -folderName "src" -# -branchName "odata.net-main" -# -resultRoot "C:\Users\ODatabld\Documents\PoliCheck\LatestRunResult" -# -PoliCheckPath "C:\Program Files (x86)\Microsoft\PoliCheck\" -# - -$targetPath= "${BuildSourceDir}\${folderName}" -Write-Output "targetPath: ${targetPath}" -$result="${resultRoot}\${branchName}\poli_result_${folderName}.xml" - -cd "${PoliCheckPath}" - -.\Policheck.exe /F:$targetPath /T:9 /Sev:"1|2" /PE:2 /O:$result - -$FileContent = Get-Content $result -$PassResult = Select-String -InputObject $FileContent -Pattern "" - -If ($PassResult.Matches.Count -eq 0) { - Write-Error "PoliCheck failed for target ${targetPath}. For details, please check this result file on build machine: ${result}: section ." - exit 1 -} - -Write-Output "PoliCheck pass for target ${targetPath}" \ No newline at end of file diff --git a/tool/UpdateDocs/Program.cs b/tool/UpdateDocs/Program.cs deleted file mode 100644 index 22cad799..00000000 --- a/tool/UpdateDocs/Program.cs +++ /dev/null @@ -1,88 +0,0 @@ -//--------------------------------------------------------------------- -// -// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. -// -//--------------------------------------------------------------------- - -using System; -using System.IO; -using System.Xml.Linq; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi; -using Microsoft.OpenApi.OData; -using System.Threading.Tasks; - -namespace UpdateDocs -{ - class Program - { - static async Task Main(string[] args) - { - // we assume the path are existed for simplicity. - string path = Directory.GetCurrentDirectory(); - string parentPath = Path.Combine(path, "..", "..", "..", "..", ".."); - string csdl = Path.Combine(parentPath, "docs", "csdl"); - string oas20 = Path.Combine(parentPath, "docs", "oas_2_0"); - string oas30 = Path.Combine(parentPath, "docs", "oas3_0_0"); - string oas31 = Path.Combine(parentPath, "docs", "oas3_1_0"); - - foreach (var filePath in Directory.GetFiles(csdl, "*.xml")) - { - Console.WriteLine(filePath); - - IEdmModel model = await LoadEdmModelAsync(filePath); - if (model == null) - { - continue; - } - - FileInfo fileInfo = new FileInfo(filePath); - string fileName = fileInfo.Name.Substring(0, fileInfo.Name.Length - 4); - - OpenApiConvertSettings settings = new OpenApiConvertSettings(); - if (fileName.Contains("graph.beta")) - { - settings.PrefixEntityTypeNameBeforeKey = true; - settings.ServiceRoot = new Uri("https://graph.microsoft.com/beta"); - } - else if (fileName.Contains("graph1.0")) - { - settings.PrefixEntityTypeNameBeforeKey = true; - settings.ServiceRoot = new Uri("https://graph.microsoft.com/v1.0"); - } - - settings.EnableKeyAsSegment = true; - settings.EnableUnqualifiedCall = true; - var output = Path.Combine(oas31, fileName + ".json"); - var document = model.ConvertToOpenApi(settings); - await File.WriteAllTextAsync(output, await document.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_1)); - - output = Path.Combine(oas30, fileName + ".json"); - await File.WriteAllTextAsync(output, await document.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0)); - - output = Path.Combine(oas20, fileName + ".json"); - await File.WriteAllTextAsync(output, await document.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0)); - - Console.WriteLine("Output [ " + fileName + " ] Successful!"); - } - - Console.WriteLine("\n==> All Done!"); - return 0; - } - - private static async Task LoadEdmModelAsync(string file) - { - try - { - string csdl = await File.ReadAllTextAsync(file); - return CsdlReader.Parse(XElement.Parse(csdl).CreateReader()); - } - catch - { - Console.WriteLine("Cannot load EDM from file: " + file); - return null; - } - } - } -} diff --git a/tool/UpdateDocs/Properties/AssemblyInfo.cs b/tool/UpdateDocs/Properties/AssemblyInfo.cs deleted file mode 100644 index 89d8a5d5..00000000 --- a/tool/UpdateDocs/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("UpdateDocs")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("UpdateDocs")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("6d5453c2-e35f-4cc6-b774-4c676f5f33d1")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tool/UpdateDocs/UpdateDocs.csproj b/tool/UpdateDocs/UpdateDocs.csproj deleted file mode 100644 index d0d903dd..00000000 --- a/tool/UpdateDocs/UpdateDocs.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - net8.0 - Exe - false - - - - - - - - - - - - \ No newline at end of file diff --git a/tool/versioning.props b/tool/versioning.props deleted file mode 100644 index b6bd275b..00000000 --- a/tool/versioning.props +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - 1 - 0 - 9 - - - - - - [1.2.3, 2.0.0) - [7.10.0, 8.0.0) - - - - - 2020 - - - $([System.Convert]::ToInt32('$([MSBuild]::Add(1, $([MSBuild]::Subtract($([System.DateTime]::Now.Year), $(VersionStartYear)))))$([System.DateTime]::Now.ToString("MMdd"))')) - - $([System.Convert]::ToString($(VersionDateCode))) - - - - - $(VersionMajor).$(VersionMinor).$(VersionBuild) - $(VersionFullSemantic).$(VersionRevision) - - - - - $(VersionFullSemantic) - $(VersionFullSemantic)-$(VersionRelease) - - - From b794f3b6c7384cbf079f22ebc4513d727b27c24c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 6 Jan 2026 16:06:13 -0500 Subject: [PATCH 02/11] ci: sync with main Signed-off-by: Vincent Biret --- .../OpenAPI.NET.OData-branch-protection.yml | 36 ++++++++++++++++ .github/release-please.yml | 3 ++ .github/workflows/ci-cd.yml | 4 +- .github/workflows/codeql-analysis.yml | 12 +++--- .github/workflows/release-please-gha.yml | 43 +++++++++++++++++++ .github/workflows/sonarcloud.yml | 9 ++-- .github/workflows/validate-descriptions.yml | 10 ++--- 7 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/release-please-gha.yml diff --git a/.github/policies/OpenAPI.NET.OData-branch-protection.yml b/.github/policies/OpenAPI.NET.OData-branch-protection.yml index 7a91aec7..ffd1f84a 100644 --- a/.github/policies/OpenAPI.NET.OData-branch-protection.yml +++ b/.github/policies/OpenAPI.NET.OData-branch-protection.yml @@ -49,6 +49,42 @@ configuration: # This branch pattern applies to the following branches as of 06/09/2024 20:45:44: # support/v1 + # Specifies whether this branch can be deleted. boolean + allowsDeletions: false + # Specifies whether forced pushes are allowed on this branch. boolean + allowsForcePushes: false + # Specifies whether new commits pushed to the matching branches dismiss pull request review approvals. boolean + dismissStaleReviews: true + # Specifies whether admins can overwrite branch protection. boolean + isAdminEnforced: false + # Indicates whether "Require a pull request before merging" is enabled. boolean + requiresPullRequestBeforeMerging: true + # Specifies the number of pull request reviews before merging. int (0-6). Should be null/empty if PRs are not required + requiredApprovingReviewsCount: 1 + # Require review from Code Owners. Requires requiredApprovingReviewsCount. boolean + requireCodeOwnersReview: true + # Are commits required to be signed. boolean. TODO: all contributors must have commit signing on local machines. + requiresCommitSignatures: false + # Are conversations required to be resolved before merging? boolean + requiresConversationResolution: true + # Are merge commits prohibited from being pushed to this branch. boolean + requiresLinearHistory: false + # Required status checks to pass before merging. Values can be any string, but if the value does not correspond to any existing status check, the status check will be stuck on pending for status since nothing exists to push an actual status + requiredStatusChecks: + - license/cla + - Continuous Integration + - CodeQL + # Require branches to be up to date before merging. This should be false since the repo contains autogenerated files. boolean + requiresStrictStatusChecks: false + # Indicates whether there are restrictions on who can push. boolean. Should be set with whoCanPush. + restrictsPushes: false + # Restrict who can dismiss pull request reviews. boolean + restrictsReviewDismissals: false + + - branchNamePattern: support/v2 + # This branch pattern applies to the following branches as of 06/09/2024 20:45:44: + # support/v1 + # Specifies whether this branch can be deleted. boolean allowsDeletions: false # Specifies whether forced pushes are allowed on this branch. boolean diff --git a/.github/release-please.yml b/.github/release-please.yml index c821fc16..ce23f6ec 100644 --- a/.github/release-please.yml +++ b/.github/release-please.yml @@ -3,5 +3,8 @@ primaryBranch: main handleGHRelease: true branches: - branch: support/v1 + manifest: true + handleGHRelease: true + - branch: support/v2 manifest: true handleGHRelease: true \ No newline at end of file diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 625fd765..660e7b22 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -17,7 +17,7 @@ jobs: GITHUB_RUN_NUMBER: ${{ github.run_number }} steps: - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: 8.0.x @@ -44,7 +44,7 @@ jobs: - name: Checkout repository id: checkout_repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 56409ee7..aaa85d12 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,10 +13,10 @@ name: "CodeQL" on: push: - branches: [ main, support/v1 ] + branches: [ main, support/v1, support/v2 ] pull_request: # The branches below must be a subset of the branches above - branches: [ main, support/v1 ] + branches: [ main, support/v1, support/v2 ] schedule: - cron: '32 2 * * 6' workflow_dispatch: @@ -39,16 +39,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: 8.0.x # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -76,4 +76,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/release-please-gha.yml b/.github/workflows/release-please-gha.yml new file mode 100644 index 00000000..e54172da --- /dev/null +++ b/.github/workflows/release-please-gha.yml @@ -0,0 +1,43 @@ +## ----------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See LICENSE.txt in the project root for license information. +## ----------------------------------------------------------------------------- +# +# Summary: +# This GitHub Actions workflow automates the release process using Release Please. +# It triggers on pushes to the main branch, generates a GitHub App token using organization +# variables and secrets, and then runs the release-please-action to manage versioning and changelogs. + +name: Release Please + +on: + push: + branches: + - main + - support/v1 + - support/v2 + +permissions: + contents: read + +jobs: + release-please-master: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.RELEASE_PLEASE_TOKEN_PROVIDER_APP_ID }} + private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }} + + - name: Release Please + uses: googleapis/release-please-action@v4 + with: + token: ${{ steps.app-token.outputs.token }} + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + target-branch: ${{ github.ref_name }} diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 567536c5..d18fbb41 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -5,6 +5,7 @@ on: branches: - main - support/v1 + - support/v2 paths-ignore: ['.vscode/**'] pull_request: types: [opened, synchronize, reopened] @@ -35,19 +36,19 @@ jobs: runs-on: windows-latest steps: - name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'adopt' java-version: 17 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v5 with: dotnet-version: 8.0.x - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Cache SonarCloud packages - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar diff --git a/.github/workflows/validate-descriptions.yml b/.github/workflows/validate-descriptions.yml index a9a0d36d..5027d45a 100644 --- a/.github/workflows/validate-descriptions.yml +++ b/.github/workflows/validate-descriptions.yml @@ -2,9 +2,9 @@ name: OpenAPI Parser Validation for latest OpenAPI docs on: push: - branches: [ main, support/v1 ] + branches: [ main, support/v1, support/v2 ] pull_request: - branches: [ main, support/v1 ] + branches: [ main, support/v1, support/v2 ] jobs: @@ -13,7 +13,7 @@ jobs: outputs: matrix: ${{ steps.set-descriptions.outputs.matrix }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - id: set-descriptions run: echo "::set-output name=matrix::$(ls test/**/Resources/*.{json,yaml} | sed 's/.*\///' | jq -R -s -c 'split("\n")[:-1]')" @@ -26,11 +26,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: recursive - name: Validate description with redocly uses: fluximus-prime/redocly-cli-github-action@v1 with: - args: 'lint test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/${{ matrix.descriptions }} --skip-rule operation-4xx-response --skip-rule no-server-trailing-slash --skip-rule no-unused-components --skip-rule security-defined --skip-rule info-license-url --skip-rule info-license --skip-rule no-empty-servers --skip-rule operation-summary --skip-rule tag-description --max-problems 1000' \ No newline at end of file + args: 'lint test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/${{ matrix.descriptions }} --max-problems 1000 --config redocly.yaml' \ No newline at end of file From ca117079107f2e372674fef3356b8daf72985799 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 6 Jan 2026 16:06:33 -0500 Subject: [PATCH 03/11] cd: syncs with main Signed-off-by: Vincent Biret --- .azure-pipelines/ci-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index cedb47a0..836c94d2 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -8,6 +8,7 @@ trigger: include: - main - support/v1 + - support/v2 tags: include: - 'v*' @@ -16,6 +17,7 @@ pr: include: - main - support/v1 + - support/v2 variables: buildPlatform: 'Any CPU' From 0a208694394f8ed88efbb4ae352f502a253da7b6 Mon Sep 17 00:00:00 2001 From: Gavin Barron Date: Fri, 16 Jan 2026 09:30:50 -0800 Subject: [PATCH 04/11] feat: allow optional body parameter (#773) makes body parameter optional if all fields in the body are optional Signed-off-by: Vincent Biret --- .../EdmModelOpenApiExtensions.cs | 160 ++++++ .../Generator/OpenApiRequestBodyGenerator.cs | 2 +- .../ComplexPropertyPostOperationHandler.cs | 6 +- .../ComplexPropertyUpdateOperationHandler.cs | 4 +- .../EntitySetPostOperationHandler.cs | 6 +- .../Operation/EntityUpdateOperationHandler.cs | 4 +- .../NavigationPropertyPostOperationHandler.cs | 4 +- ...avigationPropertyUpdateOperationHandler.cs | 6 +- .../SingletonPatchOperationHandler.cs | 6 +- .../PublicAPI.Unshipped.txt | 2 + .../EdmModelOpenApiExtensionsTests.cs | 489 ++++++++++++++++++ .../OpenApiRequestBodyGeneratorTests.cs | 3 +- .../Resources/Basic.OpenApi.V2.json | 2 - .../Resources/Basic.OpenApi.V2.yaml | 2 - .../Resources/Basic.OpenApi.V3.1.json | 8 +- .../Resources/Basic.OpenApi.V3.1.yaml | 4 +- .../Resources/Basic.OpenApi.json | 226 ++++---- .../Resources/Basic.OpenApi.yaml | 2 - .../Resources/Empty.OpenApi.V3.1.json | 2 +- .../Resources/Empty.OpenApi.V3.1.yaml | 2 +- .../Resources/Empty.OpenApi.json | 2 +- .../Resources/Multiple.Schema.OpenApi.V2.json | 6 - .../Resources/Multiple.Schema.OpenApi.V2.yaml | 6 - .../Multiple.Schema.OpenApi.V3.1.json | 18 +- .../Multiple.Schema.OpenApi.V3.1.yaml | 6 - .../Resources/Multiple.Schema.OpenApi.json | 18 +- .../Resources/Multiple.Schema.OpenApi.yaml | 6 - .../Resources/TripService.OpenApi.V2.json | 84 --- .../Resources/TripService.OpenApi.V2.yaml | 84 --- .../Resources/TripService.OpenApi.V3.1.json | 252 +++------ .../Resources/TripService.OpenApi.V3.1.yaml | 84 --- .../Resources/TripService.OpenApi.json | 252 +++------ .../Resources/TripService.OpenApi.yaml | 84 --- 33 files changed, 977 insertions(+), 865 deletions(-) create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTests.cs diff --git a/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs index 25fb080f..e5bf1f0a 100644 --- a/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs @@ -3,12 +3,15 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using System; using System.Collections.Generic; +using System.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Validation; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.OData.Generator; +using Microsoft.OpenApi.OData.Vocabulary.Core; namespace Microsoft.OpenApi.OData { @@ -54,5 +57,162 @@ public static OpenApiDocument ConvertToOpenApi(this IEdmModel model, OpenApiConv ODataContext context = new(model, settings); return context.CreateDocument(); } + + /// + /// Determines if a request body should be required for an OData action. + /// + /// The EDM action. + /// True if the request body should be required, false otherwise. + public static bool ShouldRequestBodyBeRequired(this IEdmAction action) + { + if (action == null) + { + return true; // Safe default + } + + // Get non-binding parameters + var parameters = action.IsBound + ? action.Parameters.Skip(1) + : action.Parameters; + + // If no parameters, body is already null (existing behavior handles this) + if (!parameters.Any()) + { + return true; // Won't matter since body will be null + } + + // Check if any parameter is non-nullable and not optional + return parameters.Any(p => !p.Type.IsNullable && p is not IEdmOptionalParameter); + } + + /// + /// Determines if a request body should be required for an entity or complex type. + /// + /// The EDM structured type. + /// Whether this is an update operation (excludes key properties). + /// The EDM model for additional context. + /// True if the request body should be required, false otherwise. + public static bool ShouldRequestBodyBeRequired( + this IEdmStructuredType structuredType, + bool isUpdateOperation, + IEdmModel? model = null) + { + if (structuredType == null) + { + return true; // Safe default + } + + return !AreAllPropertiesOptional(structuredType, isUpdateOperation, model); + } + + /// + /// Checks if all properties in a structured type are optional. + /// + /// The EDM structured type. + /// Whether to exclude key properties from analysis (for update operations). + /// The EDM model for additional context. + /// True if all properties are optional, false if any are required. + private static bool AreAllPropertiesOptional( + IEdmStructuredType structuredType, + bool excludeKeyProperties, + IEdmModel? model = null) + { + if (structuredType == null) + { + return false; + } + + // Collect all properties including inherited ones + var allProperties = new List(); + + // Get properties from current type and all base types + IEdmStructuredType currentType = structuredType; + while (currentType != null) + { + allProperties.AddRange(currentType.DeclaredStructuralProperties()); + allProperties.AddRange(currentType.DeclaredNavigationProperties()); + currentType = currentType.BaseType; + } + + // If no properties, consider optional (empty body) + if (allProperties.Count == 0) + { + return true; + } + + // Get key property names if we need to exclude them + HashSet? keyNames = null; + if (excludeKeyProperties && structuredType is IEdmEntityType entityType) + { + keyNames = new HashSet(entityType.Key().Select(static k => k.Name), StringComparer.Ordinal); + } + + // Check if ALL remaining properties are optional + foreach (var property in allProperties) + { + // Skip key properties if requested + if (keyNames != null && keyNames.Contains(property.Name)) + { + continue; + } + + // Skip computed properties (read-only) + if (model != null && property is IEdmStructuralProperty && + (model.GetBoolean(property, CoreConstants.Computed) ?? false)) + { + continue; + } + + // If this property is required, the body must be required + if (!property.IsPropertyOptional()) + { + return false; + } + } + + return true; + } + + /// + /// Checks if an individual property is optional. + /// + /// The EDM property. + /// True if the property is optional, false if required. + private static bool IsPropertyOptional(this IEdmProperty property) + { + if (property == null) + { + return false; + } + + // Structural properties (primitive, enum, complex) + if (property is IEdmStructuralProperty structuralProp) + { + // Has default value = optional + if (!string.IsNullOrEmpty(structuralProp.DefaultValueString)) + { + return true; + } + + // Type is nullable = optional + if (structuralProp.Type.IsNullable) + { + return true; + } + + // Otherwise required + return false; + } + + // Navigation properties + if (property is IEdmNavigationProperty navProp) + { + // Navigation properties are optional if nullable + return navProp.Type.IsNullable; + } + + // Unknown property type, treat as required (safe default) + return false; + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs index 9be25fe6..37bb6e2a 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs @@ -77,7 +77,7 @@ internal static class OpenApiRequestBodyGenerator OpenApiRequestBody requestBody = new OpenApiRequestBody { Description = "Action parameters", - Required = true, + Required = action.ShouldRequestBodyBeRequired(), Content = new Dictionary() }; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs index e213bff9..e53de605 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs @@ -84,10 +84,12 @@ protected override void SetParameters(OpenApiOperation operation) } /// protected override void SetRequestBody(OpenApiOperation operation) - { + { operation.RequestBody = new OpenApiRequestBody { - Required = true, + Required = ComplexPropertySegment?.ComplexType?.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + Context?.Model) ?? true, Description = "New property values", Content = new Dictionary { diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs index 2455530b..76f05ece 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs @@ -63,7 +63,9 @@ protected override void SetRequestBody(OpenApiOperation operation) { operation.RequestBody = new OpenApiRequestBody { - Required = true, + Required = ComplexPropertySegment?.ComplexType?.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + Context?.Model) ?? true, Description = "New property values", Content = new Dictionary { diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs index 9a4ac62f..c0205d54 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs @@ -69,10 +69,12 @@ protected override void SetBasicInfo(OpenApiOperation operation) protected override void SetRequestBody(OpenApiOperation operation) { // The requestBody field contains a Request Body Object for the request body - // that references the schema of the entity set’s entity type in the global schemas. + // that references the schema of the entity set's entity type in the global schemas. operation.RequestBody = new OpenApiRequestBody { - Required = true, + Required = EntitySet?.EntityType?.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + Context?.Model) ?? true, Description = "New entity", Content = GetContentDescription() }; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs index 7d17f30d..a9438944 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs @@ -77,7 +77,9 @@ protected override void SetRequestBody(OpenApiOperation operation) { operation.RequestBody = new OpenApiRequestBody { - Required = true, + Required = EntitySet?.EntityType?.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + Context?.Model) ?? true, Description = "New property values", Content = GetContent() }; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs index 9b596d45..4dcd337c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs @@ -67,7 +67,9 @@ protected override void SetRequestBody(OpenApiOperation operation) operation.RequestBody = new OpenApiRequestBody { - Required = true, + Required = NavigationProperty?.ToEntityType()?.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + Context?.Model) ?? true, Description = "New navigation property", Content = GetContent(schema, _insertRestriction?.RequestContentTypes) }; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs index 4c1a5e72..30ed21bf 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyUpdateOperationHandler.cs @@ -58,13 +58,15 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) { - var schema = Context is { Settings.EnableDerivedTypesReferencesForRequestBody: true } ? + var schema = Context is { Settings.EnableDerivedTypesReferencesForRequestBody: true } ? EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model, _document) : null; operation.RequestBody = new OpenApiRequestBody { - Required = true, + Required = NavigationProperty?.ToEntityType()?.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + Context?.Model) ?? true, Description = "New navigation property values", Content = GetContent(schema, _updateRestriction?.RequestContentTypes) }; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs index f086c040..2fe12cd0 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs @@ -67,10 +67,12 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) - { + { operation.RequestBody = new OpenApiRequestBody { - Required = true, + Required = Singleton?.EntityType?.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + Context?.Model) ?? true, Description = "New property values", Content = new Dictionary { diff --git a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt index e29f3677..b175f6a1 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt @@ -307,6 +307,8 @@ static Microsoft.OpenApi.OData.Edm.EdmTypeExtensions.ShouldPathParameterBeQuoted static Microsoft.OpenApi.OData.Edm.ODataRefSegment.Instance -> Microsoft.OpenApi.OData.Edm.ODataRefSegment! static Microsoft.OpenApi.OData.EdmModelOpenApiExtensions.ConvertToOpenApi(this Microsoft.OData.Edm.IEdmModel! model) -> Microsoft.OpenApi.OpenApiDocument! static Microsoft.OpenApi.OData.EdmModelOpenApiExtensions.ConvertToOpenApi(this Microsoft.OData.Edm.IEdmModel! model, Microsoft.OpenApi.OData.OpenApiConvertSettings! settings) -> Microsoft.OpenApi.OpenApiDocument! +static Microsoft.OpenApi.OData.EdmModelOpenApiExtensions.ShouldRequestBodyBeRequired(this Microsoft.OData.Edm.IEdmAction! action) -> bool +static Microsoft.OpenApi.OData.EdmModelOpenApiExtensions.ShouldRequestBodyBeRequired(this Microsoft.OData.Edm.IEdmStructuredType! structuredType, bool isUpdateOperation, Microsoft.OData.Edm.IEdmModel? model = null) -> bool virtual Microsoft.OpenApi.OData.Edm.ODataPath.Kind.get -> Microsoft.OpenApi.OData.Edm.ODataPathKind virtual Microsoft.OpenApi.OData.Edm.ODataPathProvider.CanFilter(Microsoft.OData.Edm.IEdmElement! element) -> bool virtual Microsoft.OpenApi.OData.Edm.ODataPathProvider.GetPaths(Microsoft.OData.Edm.IEdmModel! model, Microsoft.OpenApi.OData.OpenApiConvertSettings! settings) -> System.Collections.Generic.IEnumerable! diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTests.cs new file mode 100644 index 00000000..0fb11fe0 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTests.cs @@ -0,0 +1,489 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OData.Edm.Vocabularies.V1; +using Xunit; + +namespace Microsoft.OpenApi.OData.Tests +{ + /// + /// Tests for EdmModelOpenApiExtensions.ShouldRequestBodyBeRequired extension methods. + /// + public class EdmModelOpenApiExtensionsTests + { + #region Action Tests + + [Fact] + public void ActionWithAllNullableParameters_ReturnsOptional() + { + // Arrange + var action = CreateAction("TestAction", isNullable: true); + + // Act + var result = action.ShouldRequestBodyBeRequired(); + + // Assert + Assert.False(result); + } + + [Fact] + public void ActionWithAllRequiredParameters_ReturnsRequired() + { + // Arrange + var action = CreateAction("TestAction", isNullable: false); + + // Act + var result = action.ShouldRequestBodyBeRequired(); + + // Assert + Assert.True(result); + } + + [Fact] + public void ActionWithMixedNullableAndRequiredParameters_ReturnsRequired() + { + // Arrange + var model = new EdmModel(); + var action = new EdmAction("NS", "TestAction", null); + action.AddParameter("nullableParam", EdmCoreModel.Instance.GetString(true)); + action.AddParameter("requiredParam", EdmCoreModel.Instance.GetString(false)); + model.AddElement(action); + + // Act + var result = action.ShouldRequestBodyBeRequired(); + + // Assert + Assert.True(result); + } + + [Fact] + public void ActionWithOptionalParameter_ReturnsOptional() + { + // Arrange + var model = new EdmModel(); + var action = new EdmAction("NS", "TestAction", null); + action.AddOptionalParameter("optionalParam", EdmCoreModel.Instance.GetString(false)); + model.AddElement(action); + + // Act + var result = action.ShouldRequestBodyBeRequired(); + + // Assert + Assert.False(result); + } + + [Fact] + public void BoundActionWithNullableParameter_ExcludesBindingParameter() + { + // Arrange + var model = new EdmModel(); + var entityType = new EdmEntityType("NS", "Entity"); + var action = new EdmAction("NS", "TestAction", null, true, null); + action.AddParameter("bindingParam", new EdmEntityTypeReference(entityType, false)); + action.AddParameter("nullableParam", EdmCoreModel.Instance.GetString(true)); + model.AddElement(entityType); + model.AddElement(action); + + // Act + var result = action.ShouldRequestBodyBeRequired(); + + // Assert + Assert.False(result); // Only non-binding parameter is nullable + } + + [Fact] + public void ActionWithNoParameters_ReturnsRequired() + { + // Arrange + var model = new EdmModel(); + var action = new EdmAction("NS", "TestAction", null); + model.AddElement(action); + + // Act + var result = action.ShouldRequestBodyBeRequired(); + + // Assert + Assert.True(result); // No parameters means no request body needed, but returns true (existing behavior) + } + + [Fact] + public void NullAction_ReturnsRequired() + { + // Act + var result = ((IEdmAction)null).ShouldRequestBodyBeRequired(); + + // Assert + Assert.True(result); // Safe default + } + + #endregion + + #region Entity Type Tests - Create Operations + + [Fact] + public void EntityTypeWithAllNullableProperties_CreateOperation_ReturnsOptional() + { + // Arrange + var entityType = CreateEntityType("Customer", hasRequiredProperties: false); + + // Act + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + model: null); + + // Assert + Assert.False(result); + } + + [Fact] + public void EntityTypeWithRequiredProperty_CreateOperation_ReturnsRequired() + { + // Arrange + var entityType = CreateEntityType("Customer", hasRequiredProperties: true); + + // Act + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + model: null); + + // Assert + Assert.True(result); + } + + [Fact] + public void EntityTypeWithOnlyKeyProperty_CreateOperation_ReturnsRequired() + { + // Arrange + var entityType = new EdmEntityType("NS", "Entity"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + // Act - Create operation includes key properties + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + model: null); + + // Assert + Assert.True(result); // Key is not nullable, so body is required + } + + #endregion + + #region Entity Type Tests - Update Operations + + [Fact] + public void EntityTypeWithOnlyKeyProperty_UpdateOperation_ReturnsOptional() + { + // Arrange + var entityType = new EdmEntityType("NS", "Entity"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + // Act - Update operation excludes key properties + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: null); + + // Assert + Assert.False(result); // No non-key properties, so body is optional + } + + [Fact] + public void EntityTypeWithRequiredNonKeyProperty_UpdateOperation_ReturnsRequired() + { + // Arrange + var entityType = new EdmEntityType("NS", "Entity"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + entityType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, false); // Required + + // Act + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: null); + + // Assert + Assert.True(result); // Has required non-key property + } + + [Fact] + public void EntityTypeWithNullableNonKeyProperties_UpdateOperation_ReturnsOptional() + { + // Arrange + var entityType = new EdmEntityType("NS", "Entity"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + entityType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, true); // Nullable + entityType.AddStructuralProperty("Email", EdmPrimitiveTypeKind.String, true); // Nullable + + // Act + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: null); + + // Assert + Assert.False(result); // All non-key properties are nullable + } + + #endregion + + #region Inheritance Tests + + [Fact] + public void EntityTypeWithRequiredInheritedProperty_ReturnsRequired() + { + // Arrange + var baseType = new EdmEntityType("NS", "BaseEntity"); + baseType.AddKeys(baseType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + baseType.AddStructuralProperty("BaseProperty", EdmPrimitiveTypeKind.String, false); // Required + + var derivedType = new EdmEntityType("NS", "DerivedEntity", baseType); + derivedType.AddStructuralProperty("DerivedProperty", EdmPrimitiveTypeKind.String, true); // Nullable + + // Act - Update operation + var result = derivedType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: null); + + // Assert + Assert.True(result); // Base type has required property + } + + [Fact] + public void EntityTypeWithAllNullableInheritedProperties_ReturnsOptional() + { + // Arrange + var baseType = new EdmEntityType("NS", "BaseEntity"); + baseType.AddKeys(baseType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + baseType.AddStructuralProperty("BaseProperty", EdmPrimitiveTypeKind.String, true); // Nullable + + var derivedType = new EdmEntityType("NS", "DerivedEntity", baseType); + derivedType.AddStructuralProperty("DerivedProperty", EdmPrimitiveTypeKind.String, true); // Nullable + + // Act - Update operation + var result = derivedType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: null); + + // Assert + Assert.False(result); // All non-key properties are nullable + } + + #endregion + + #region Property with Default Value Tests + + [Fact] + public void PropertyWithDefaultValue_TreatedAsOptional() + { + // Arrange + var entityType = new EdmEntityType("NS", "Entity"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + // Create property with default value + var nameProperty = new EdmStructuralProperty( + entityType, + "Name", + EdmCoreModel.Instance.GetString(false), + "DefaultName"); // Default value + entityType.AddProperty(nameProperty); + + // Act - Update operation + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: null); + + // Assert + Assert.False(result); // Has default value, so optional + } + + #endregion + + #region Computed Property Tests + + [Fact] + public void ComputedProperty_ExcludedFromAnalysis() + { + // Arrange + var model = new EdmModel(); + var entityType = new EdmEntityType("NS", "Entity"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + var computedProp = entityType.AddStructuralProperty("ComputedProp", EdmPrimitiveTypeKind.String, false); + model.AddElement(entityType); + + // Add Computed annotation + var term = CoreVocabularyModel.ComputedTerm; + var annotation = new EdmVocabularyAnnotation(computedProp, term, new EdmBooleanConstant(true)); + model.SetVocabularyAnnotation(annotation); + + // Act - Update operation + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: model); + + // Assert + Assert.False(result); // Computed property excluded, no other properties + } + + #endregion + + #region Complex Type Tests + + [Fact] + public void ComplexTypeWithAllNullableProperties_ReturnsOptional() + { + // Arrange + var complexType = new EdmComplexType("NS", "Address"); + complexType.AddStructuralProperty("Street", EdmPrimitiveTypeKind.String, true); + complexType.AddStructuralProperty("City", EdmPrimitiveTypeKind.String, true); + + // Act + var result = complexType.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + model: null); + + // Assert + Assert.False(result); + } + + [Fact] + public void ComplexTypeWithRequiredProperty_ReturnsRequired() + { + // Arrange + var complexType = new EdmComplexType("NS", "Address"); + complexType.AddStructuralProperty("Street", EdmPrimitiveTypeKind.String, false); // Required + complexType.AddStructuralProperty("City", EdmPrimitiveTypeKind.String, true); + + // Act + var result = complexType.ShouldRequestBodyBeRequired( + isUpdateOperation: false, + model: null); + + // Assert + Assert.True(result); + } + + #endregion + + #region Navigation Property Tests + + [Fact] + public void EntityTypeWithNullableNavigationProperty_ReturnsOptional() + { + // Arrange + var model = new EdmModel(); + var entityType = new EdmEntityType("NS", "Order"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + var customerType = new EdmEntityType("NS", "Customer"); + customerType.AddKeys(customerType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + var navProperty = entityType.AddUnidirectionalNavigation( + new EdmNavigationPropertyInfo + { + Name = "Customer", + Target = customerType, + TargetMultiplicity = EdmMultiplicity.ZeroOrOne + }); + + model.AddElement(entityType); + model.AddElement(customerType); + + // Act - Update operation (excludes key) + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: model); + + // Assert + Assert.False(result); // Navigation property is nullable + } + + [Fact] + public void EntityTypeWithRequiredNavigationProperty_ReturnsRequired() + { + // Arrange + var model = new EdmModel(); + var entityType = new EdmEntityType("NS", "Order"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + var customerType = new EdmEntityType("NS", "Customer"); + customerType.AddKeys(customerType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + var navProperty = entityType.AddUnidirectionalNavigation( + new EdmNavigationPropertyInfo + { + Name = "Customer", + Target = customerType, + TargetMultiplicity = EdmMultiplicity.One // Required + }); + + model.AddElement(entityType); + model.AddElement(customerType); + + // Act - Update operation (excludes key) + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: model); + + // Assert + Assert.True(result); // Navigation property is required + } + + #endregion + + #region Edge Cases + + [Fact] + public void EmptyEntityType_ReturnsOptional() + { + // Arrange - Entity with only key, update operation excludes key + var entityType = new EdmEntityType("NS", "Empty"); + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false)); + + // Act + var result = entityType.ShouldRequestBodyBeRequired( + isUpdateOperation: true, + model: null); + + // Assert + Assert.False(result); // No properties after excluding key + } + + [Fact] + public void NullStructuredType_ReturnsRequired() + { + // Act + var result = ((IEdmStructuredType)null).ShouldRequestBodyBeRequired( + isUpdateOperation: false, + model: null); + + // Assert + Assert.True(result); // Safe default + } + + #endregion + + #region Helper Methods + + private IEdmAction CreateAction(string name, bool isNullable) + { + var model = new EdmModel(); + var action = new EdmAction("NS", name, null); + action.AddParameter("param", EdmCoreModel.Instance.GetString(isNullable)); + model.AddElement(action); + return action; + } + + private IEdmEntityType CreateEntityType(string name, bool hasRequiredProperties) + { + var entityType = new EdmEntityType("NS", name); + // Key is always nullable for this helper (to allow testing all-nullable scenarios) + entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, true)); + entityType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, !hasRequiredProperties); + return entityType; + } + + #endregion + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs index 3e2555aa..ffa17aad 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs @@ -120,8 +120,7 @@ public async Task CanSerializeAsJsonFromTheCreatedRequestBody() } } } - }, - ""required"": true + } }"; var actualJsonNode = JsonNode.Parse(json); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.json index 2a2e75db..9cfa2d0a 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.json @@ -203,7 +203,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/DefaultNs.City" } @@ -479,7 +478,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/DefaultNs.CountryOrRegion" } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.yaml index 39aac121..c4bf24aa 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V2.yaml @@ -134,7 +134,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/DefaultNs.City' responses: @@ -313,7 +312,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/DefaultNs.CountryOrRegion' responses: diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.json index fdb7e7be..94ac5194 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.json @@ -224,8 +224,7 @@ "$ref": "#/components/schemas/DefaultNs.City" } } - }, - "required": true + } }, "responses": { "204": { @@ -513,8 +512,7 @@ "$ref": "#/components/schemas/DefaultNs.CountryOrRegion" } } - }, - "required": true + } }, "responses": { "204": { @@ -1458,4 +1456,4 @@ "x-ms-docs-toc-type": "page" } ] -} +} \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.yaml index c0c61165..619e617e 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.V3.1.yaml @@ -146,7 +146,6 @@ paths: application/json: schema: $ref: '#/components/schemas/DefaultNs.City' - required: true responses: '204': description: Success @@ -332,7 +331,6 @@ paths: application/json: schema: $ref: '#/components/schemas/DefaultNs.CountryOrRegion' - required: true responses: '204': description: Success @@ -947,4 +945,4 @@ tags: - name: Me.Person x-ms-docs-toc-type: page - name: People.Person - x-ms-docs-toc-type: page + x-ms-docs-toc-type: page \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.json index b7a79edc..efade297 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.json @@ -224,8 +224,7 @@ "$ref": "#/components/schemas/DefaultNs.City" } } - }, - "required": true + } }, "responses": { "204": { @@ -513,8 +512,7 @@ "$ref": "#/components/schemas/DefaultNs.CountryOrRegion" } } - }, - "required": true + } }, "responses": { "204": { @@ -984,6 +982,105 @@ }, "components": { "schemas": { + "DefaultNs.ODataErrors.ODataError": { + "required": [ + "error" + ], + "type": "object", + "properties": { + "error": { + "$ref": "#/components/schemas/DefaultNs.ODataErrors.MainError" + } + } + }, + "DefaultNs.ODataErrors.MainError": { + "required": [ + "code", + "message" + ], + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string", + "x-ms-primary-error-message": true + }, + "target": { + "type": "string", + "nullable": true + }, + "details": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DefaultNs.ODataErrors.ErrorDetails" + } + }, + "innerError": { + "$ref": "#/components/schemas/DefaultNs.ODataErrors.InnerError" + } + } + }, + "DefaultNs.ODataErrors.ErrorDetails": { + "required": [ + "code", + "message" + ], + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "target": { + "type": "string", + "nullable": true + } + } + }, + "DefaultNs.ODataErrors.InnerError": { + "type": "object", + "description": "The structure of this object is service-specific" + }, + "ODataCountResponse": { + "type": "number", + "format": "int64" + }, + "ReferenceUpdate": { + "type": "object", + "properties": { + "@odata.id": { + "type": "string" + }, + "@odata.type": { + "type": "string", + "nullable": true + } + } + }, + "ReferenceCreate": { + "type": "object", + "properties": { + "@odata.id": { + "type": "string" + } + }, + "additionalProperties": { + "type": "object" + } + }, + "ReferenceNumeric": { + "enum": [ + "-INF", + "INF", + "NaN" + ], + "type": "string", + "nullable": true + }, "DefaultNs.Color": { "title": "Color", "enum": [ @@ -1098,73 +1195,6 @@ } } }, - "DefaultNs.ODataErrors.ODataError": { - "required": [ - "error" - ], - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/DefaultNs.ODataErrors.MainError" - } - } - }, - "DefaultNs.ODataErrors.MainError": { - "required": [ - "code", - "message" - ], - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "message": { - "type": "string", - "x-ms-primary-error-message": true - }, - "target": { - "type": "string", - "nullable": true - }, - "details": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DefaultNs.ODataErrors.ErrorDetails" - } - }, - "innerError": { - "$ref": "#/components/schemas/DefaultNs.ODataErrors.InnerError" - } - } - }, - "DefaultNs.ODataErrors.ErrorDetails": { - "required": [ - "code", - "message" - ], - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "message": { - "type": "string" - }, - "target": { - "type": "string", - "nullable": true - } - } - }, - "DefaultNs.ODataErrors.InnerError": { - "type": "object", - "description": "The structure of this object is service-specific" - }, - "ODataCountResponse": { - "type": "number", - "format": "int64" - }, "DefaultNs.PersonCollectionResponse": { "title": "Collection of Person", "type": "object", @@ -1212,38 +1242,6 @@ } } } - }, - "ReferenceUpdate": { - "type": "object", - "properties": { - "@odata.id": { - "type": "string" - }, - "@odata.type": { - "type": "string", - "nullable": true - } - } - }, - "ReferenceCreate": { - "type": "object", - "properties": { - "@odata.id": { - "type": "string" - } - }, - "additionalProperties": { - "type": "object" - } - }, - "ReferenceNumeric": { - "enum": [ - "-INF", - "INF", - "NaN" - ], - "type": "string", - "nullable": true } }, "responses": { @@ -1363,18 +1361,18 @@ "examples": { "DefaultNs.Person": { "value": { - "Addresses": [ - { - "@odata.type": "DefaultNs.Address" - } - ], + "UserName": "string (identifier)", "HomeAddress": { "@odata.type": "DefaultNs.Address" }, - "UserName": "string (identifier)", "WorkAddress": { "@odata.type": "DefaultNs.Address" - } + }, + "Addresses": [ + { + "@odata.type": "DefaultNs.Address" + } + ] } }, "DefaultNs.City": { @@ -1389,21 +1387,21 @@ }, "DefaultNs.Address": { "value": { + "Id": 0, "City": { "@odata.type": "DefaultNs.City" - }, - "Id": 0 + } } }, "DefaultNs.WorkAddress": { "value": { + "Id": 0, "City": { "@odata.type": "DefaultNs.City" }, "CountryOrRegion": { "@odata.type": "DefaultNs.CountryOrRegion" - }, - "Id": 0 + } } } }, diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.yaml index 7f9acd1c..bea2123e 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Basic.OpenApi.yaml @@ -146,7 +146,6 @@ paths: application/json: schema: $ref: '#/components/schemas/DefaultNs.City' - required: true responses: '204': description: Success @@ -332,7 +331,6 @@ paths: application/json: schema: $ref: '#/components/schemas/DefaultNs.CountryOrRegion' - required: true responses: '204': description: Success diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.json index 2fd7686d..23dfd332 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.json @@ -220,4 +220,4 @@ } } } -} +} \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.yaml index 3c6fb003..7bbfe3fc 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.V3.1.yaml @@ -148,4 +148,4 @@ components: application/json: schema: $ref: '#/components/schemas/ReferenceUpdate' - required: true + required: true \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.json index 892884da..5e5109ba 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Empty.OpenApi.json @@ -144,7 +144,7 @@ "schema": { "minimum": 0, "type": "number", - "format": "int64" + "format": "int64" }, "example": 50 }, diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json index 995e3e06..93b12af5 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json @@ -1165,7 +1165,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -1222,7 +1221,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -1929,7 +1927,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -1997,7 +1994,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -4240,7 +4236,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -4297,7 +4292,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml index e8d9a89c..981a2e20 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml @@ -824,7 +824,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -863,7 +862,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -1363,7 +1361,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -1411,7 +1408,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -3007,7 +3003,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -3046,7 +3041,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.json index fe23ad38..eb55e62f 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.json @@ -1237,8 +1237,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -1289,8 +1288,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2044,8 +2042,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2109,8 +2106,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4477,8 +4473,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4529,8 +4524,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.yaml index ea0aec89..1ed7dd37 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V3.1.yaml @@ -865,7 +865,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -900,7 +899,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -1428,7 +1426,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -1473,7 +1470,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -3139,7 +3135,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -3174,7 +3169,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json index b99bebf5..f2476ce6 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json @@ -1237,8 +1237,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -1289,8 +1288,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2044,8 +2042,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2109,8 +2106,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4477,8 +4473,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4529,8 +4524,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml index 15f72b15..969f839b 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml @@ -865,7 +865,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -900,7 +899,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -1428,7 +1426,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -1473,7 +1470,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -3139,7 +3135,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success @@ -3174,7 +3169,6 @@ paths: type: array items: $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentTagRelDto' - required: true responses: '204': description: Success 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 83d8ce19..3e321918 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 @@ -188,7 +188,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline" } @@ -448,7 +447,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airport" } @@ -576,7 +574,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation" } @@ -848,7 +845,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -902,7 +898,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -1103,7 +1098,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -1541,7 +1535,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -1594,7 +1587,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -2009,7 +2001,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -2062,7 +2053,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -2256,7 +2246,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -2756,7 +2745,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -2817,7 +2805,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -3053,7 +3040,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -3915,7 +3901,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -4107,7 +4092,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -4160,7 +4144,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -4575,7 +4558,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -4628,7 +4610,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -4822,7 +4803,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -5271,7 +5251,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -5332,7 +5311,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -5568,7 +5546,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -6226,7 +6203,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -6501,7 +6477,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -6562,7 +6537,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -6798,7 +6772,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -8272,7 +8245,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -8325,7 +8297,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -8740,7 +8711,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -8793,7 +8763,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -8987,7 +8956,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -9419,7 +9387,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -9480,7 +9447,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -9716,7 +9682,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -10317,7 +10282,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -10378,7 +10342,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -10614,7 +10577,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -11272,7 +11234,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -11345,7 +11306,6 @@ "in": "body", "name": "body", "description": "Action parameters", - "required": true, "schema": { "type": "object", "properties": { @@ -13537,7 +13497,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -13591,7 +13550,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -14058,7 +14016,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -14119,7 +14076,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -14355,7 +14311,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -14914,7 +14869,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -14976,7 +14930,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -15217,7 +15170,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -16095,7 +16047,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -16330,7 +16281,6 @@ "in": "body", "name": "body", "description": "Action parameters", - "required": true, "schema": { "type": "object", "properties": { @@ -17788,7 +17738,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -17849,7 +17798,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -18348,7 +18296,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -18409,7 +18356,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -18645,7 +18591,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -19243,7 +19188,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -19312,7 +19256,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -19588,7 +19531,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -20593,7 +20535,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -20831,7 +20772,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -20892,7 +20832,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -21391,7 +21330,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -21452,7 +21390,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -21688,7 +21625,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -22213,7 +22149,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -22282,7 +22217,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -22558,7 +22492,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -23320,7 +23253,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -23637,7 +23569,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -23706,7 +23637,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -23982,7 +23912,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -25686,7 +25615,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -25747,7 +25675,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -26246,7 +26173,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -26307,7 +26233,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -26543,7 +26468,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -27051,7 +26975,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -27120,7 +27043,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -27396,7 +27318,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -28093,7 +28014,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "object", "properties": { @@ -28162,7 +28082,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "type": "array", "items": { @@ -28438,7 +28357,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -29200,7 +29118,6 @@ "in": "body", "name": "body", "description": "New property values", - "required": true, "schema": { "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } @@ -29291,7 +29208,6 @@ "in": "body", "name": "body", "description": "Action parameters", - "required": true, "schema": { "type": "object", "properties": { 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 a6639290..72516a2a 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 @@ -124,7 +124,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline' responses: @@ -292,7 +291,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airport' responses: @@ -379,7 +377,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation' responses: @@ -558,7 +555,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -594,7 +590,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -726,7 +721,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -1018,7 +1012,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -1054,7 +1047,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -1335,7 +1327,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -1371,7 +1362,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -1502,7 +1492,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -1840,7 +1829,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -1882,7 +1870,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -2044,7 +2031,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -2620,7 +2606,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -2747,7 +2732,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -2783,7 +2767,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -3064,7 +3047,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -3100,7 +3082,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -3231,7 +3212,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -3534,7 +3514,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -3576,7 +3555,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -3738,7 +3716,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -4181,7 +4158,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -4362,7 +4338,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -4404,7 +4379,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -4566,7 +4540,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -5566,7 +5539,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -5602,7 +5574,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -5883,7 +5854,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -5919,7 +5889,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -6050,7 +6019,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -6341,7 +6309,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -6383,7 +6350,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -6545,7 +6511,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -6948,7 +6913,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -6990,7 +6954,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -7152,7 +7115,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -7595,7 +7557,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -7646,7 +7607,6 @@ paths: - in: body name: body description: Action parameters - required: true schema: type: object properties: @@ -9139,7 +9099,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -9175,7 +9134,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -9491,7 +9449,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -9533,7 +9490,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -9695,7 +9651,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -10074,7 +10029,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -10116,7 +10070,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -10278,7 +10231,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -10854,7 +10806,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -11009,7 +10960,6 @@ paths: - in: body name: body description: Action parameters - required: true schema: type: object properties: @@ -11988,7 +11938,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -12030,7 +11979,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -12373,7 +12321,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -12415,7 +12362,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -12577,7 +12523,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -12988,7 +12933,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -13036,7 +12980,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -13228,7 +13171,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -13912,7 +13854,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -14072,7 +14013,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -14114,7 +14054,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -14457,7 +14396,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -14499,7 +14437,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -14661,7 +14598,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -15020,7 +14956,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -15068,7 +15003,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -15260,7 +15194,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -15781,7 +15714,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -15993,7 +15925,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -16041,7 +15972,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -16233,7 +16163,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -17404,7 +17333,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -17446,7 +17374,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -17789,7 +17716,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -17831,7 +17757,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -17993,7 +17918,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -18340,7 +18264,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -18388,7 +18311,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -18580,7 +18502,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -19055,7 +18976,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: object properties: @@ -19103,7 +19023,6 @@ paths: - in: body name: body description: New property values - required: true schema: type: array items: @@ -19295,7 +19214,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -19816,7 +19734,6 @@ paths: - in: body name: body description: New property values - required: true schema: $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' responses: @@ -19880,7 +19797,6 @@ paths: - in: body name: body description: Action parameters - required: true schema: type: object properties: diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.json index 0d24d9d0..0a9ff9e1 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.json @@ -208,8 +208,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline" } } - }, - "required": true + } }, "responses": { "204": { @@ -481,8 +480,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airport" } } - }, - "required": true + } }, "responses": { "204": { @@ -618,8 +616,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation" } } - }, - "required": true + } }, "responses": { "204": { @@ -918,8 +915,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -967,8 +963,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -1173,8 +1168,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -1677,8 +1671,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -1723,8 +1716,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2134,8 +2126,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2180,8 +2171,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2367,8 +2357,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -2908,8 +2897,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2964,8 +2952,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -3205,8 +3192,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -4112,8 +4098,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -4325,8 +4310,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4371,8 +4355,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4782,8 +4765,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4828,8 +4810,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -5015,8 +4996,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -5496,8 +5476,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -5552,8 +5531,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -5793,8 +5771,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -6474,8 +6451,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -6777,8 +6753,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -6833,8 +6808,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -7074,8 +7048,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -8609,8 +8582,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -8655,8 +8627,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9066,8 +9037,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9112,8 +9082,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9299,8 +9268,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -9761,8 +9729,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9817,8 +9784,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -10058,8 +10024,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -10682,8 +10647,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -10738,8 +10702,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -10979,8 +10942,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -11660,8 +11622,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -11741,8 +11702,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14039,8 +13999,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14088,8 +14047,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14577,8 +14535,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14633,8 +14590,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14874,8 +14830,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -15496,8 +15451,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -15555,8 +15509,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -15811,8 +15764,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -16770,8 +16722,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -17027,8 +16978,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -18586,8 +18536,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -18642,8 +18591,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -19163,8 +19111,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -19219,8 +19166,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -19460,8 +19406,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -20121,8 +20066,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -20187,8 +20131,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -20478,8 +20421,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -21564,8 +21506,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -21835,8 +21776,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -21891,8 +21831,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -22412,8 +22351,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -22468,8 +22406,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -22709,8 +22646,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -23286,8 +23222,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -23352,8 +23287,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -23643,8 +23577,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -24458,8 +24391,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -24813,8 +24745,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -24879,8 +24810,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -25170,8 +25100,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -26999,8 +26928,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27055,8 +26983,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27576,8 +27503,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27632,8 +27558,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27873,8 +27798,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -28431,8 +28355,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -28497,8 +28420,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -28788,8 +28710,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -29534,8 +29455,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -29600,8 +29520,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -29891,8 +29810,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -30706,8 +30624,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -30811,8 +30728,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.yaml index 2d5b53a6..0f062dc1 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V3.1.yaml @@ -135,7 +135,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline' - required: true responses: '204': description: Success @@ -310,7 +309,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airport' - required: true responses: '204': description: Success @@ -401,7 +399,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation' - required: true responses: '204': description: Success @@ -597,7 +594,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -629,7 +625,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -761,7 +756,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1079,7 +1073,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1110,7 +1103,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1388,7 +1380,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1419,7 +1410,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1544,7 +1534,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1907,7 +1896,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1945,7 +1933,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2107,7 +2094,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2708,7 +2694,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2849,7 +2834,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2880,7 +2864,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3158,7 +3141,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3189,7 +3171,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3314,7 +3295,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3636,7 +3616,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3674,7 +3653,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3836,7 +3814,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4290,7 +4267,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4489,7 +4465,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4527,7 +4502,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4689,7 +4663,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -5726,7 +5699,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -5757,7 +5729,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6035,7 +6006,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6066,7 +6036,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6191,7 +6160,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6500,7 +6468,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6538,7 +6505,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6700,7 +6666,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7115,7 +7080,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7153,7 +7117,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7315,7 +7278,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7769,7 +7731,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7822,7 +7783,6 @@ paths: anyOf: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - type: 'null' - required: true responses: '204': description: Success @@ -9377,7 +9337,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9409,7 +9368,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9735,7 +9693,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9773,7 +9730,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9935,7 +9891,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -10350,7 +10305,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -10389,7 +10343,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -10556,7 +10509,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -11175,7 +11127,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -11341,7 +11292,6 @@ paths: anyOf: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - type: 'null' - required: true responses: '204': description: Success @@ -12374,7 +12324,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12412,7 +12361,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12765,7 +12713,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12803,7 +12750,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12965,7 +12911,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -13412,7 +13357,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -13457,7 +13401,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -13654,7 +13597,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14381,7 +14323,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14561,7 +14502,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14599,7 +14539,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14952,7 +14891,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14990,7 +14928,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15152,7 +15089,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15540,7 +15476,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15585,7 +15520,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15782,7 +15716,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16329,7 +16262,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16564,7 +16496,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16609,7 +16540,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16806,7 +16736,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18046,7 +17975,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18084,7 +18012,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18437,7 +18364,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18475,7 +18401,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18637,7 +18562,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19012,7 +18936,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19057,7 +18980,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19254,7 +19176,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19754,7 +19675,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19799,7 +19719,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19996,7 +19915,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -20543,7 +20461,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -20612,7 +20529,6 @@ paths: anyOf: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - type: 'null' - required: true responses: '204': description: Success 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 9f930ed6..3cf1de2b 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json @@ -208,8 +208,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline" } } - }, - "required": true + } }, "responses": { "204": { @@ -481,8 +480,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airport" } } - }, - "required": true + } }, "responses": { "204": { @@ -618,8 +616,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation" } } - }, - "required": true + } }, "responses": { "204": { @@ -918,8 +915,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -967,8 +963,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -1173,8 +1168,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -1669,8 +1663,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -1715,8 +1708,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2126,8 +2118,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2172,8 +2163,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2359,8 +2349,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -2900,8 +2889,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -2956,8 +2944,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -3197,8 +3184,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -4104,8 +4090,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -4317,8 +4302,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4363,8 +4347,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4774,8 +4757,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -4820,8 +4802,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -5007,8 +4988,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -5488,8 +5468,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -5544,8 +5523,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -5785,8 +5763,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -6466,8 +6443,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -6769,8 +6745,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -6825,8 +6800,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -7066,8 +7040,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -8601,8 +8574,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -8647,8 +8619,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9058,8 +9029,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9104,8 +9074,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9291,8 +9260,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -9753,8 +9721,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -9809,8 +9776,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -10050,8 +10016,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -10674,8 +10639,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -10730,8 +10694,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -10971,8 +10934,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -11652,8 +11614,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -11733,8 +11694,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14031,8 +13991,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14080,8 +14039,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14569,8 +14527,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14625,8 +14582,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -14866,8 +14822,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -15488,8 +15443,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -15547,8 +15501,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -15803,8 +15756,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -16762,8 +16714,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -17019,8 +16970,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -18578,8 +18528,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -18634,8 +18583,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -19155,8 +19103,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -19211,8 +19158,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -19452,8 +19398,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -20113,8 +20058,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -20179,8 +20123,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -20470,8 +20413,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -21556,8 +21498,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -21827,8 +21768,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -21883,8 +21823,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -22404,8 +22343,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -22460,8 +22398,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -22701,8 +22638,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -23278,8 +23214,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -23344,8 +23279,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -23635,8 +23569,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -24450,8 +24383,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -24805,8 +24737,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -24871,8 +24802,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -25162,8 +25092,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -26991,8 +26920,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27047,8 +26975,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27568,8 +27495,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27624,8 +27550,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -27865,8 +27790,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -28423,8 +28347,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -28489,8 +28412,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -28780,8 +28702,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -29526,8 +29447,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -29592,8 +29512,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { @@ -29883,8 +29802,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -30698,8 +30616,7 @@ "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location" } } - }, - "required": true + } }, "responses": { "204": { @@ -30803,8 +30720,7 @@ } } } - }, - "required": true + } }, "responses": { "204": { 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 a37ce4a4..330379ec 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml @@ -135,7 +135,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline' - required: true responses: '204': description: Success @@ -310,7 +309,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airport' - required: true responses: '204': description: Success @@ -401,7 +399,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation' - required: true responses: '204': description: Success @@ -597,7 +594,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -629,7 +625,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -761,7 +756,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1075,7 +1069,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1106,7 +1099,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1384,7 +1376,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1415,7 +1406,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1540,7 +1530,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1903,7 +1892,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -1941,7 +1929,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2103,7 +2090,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2704,7 +2690,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2845,7 +2830,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -2876,7 +2860,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3154,7 +3137,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3185,7 +3167,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3310,7 +3291,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3632,7 +3612,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3670,7 +3649,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -3832,7 +3810,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4286,7 +4263,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4485,7 +4461,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4523,7 +4498,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -4685,7 +4659,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -5722,7 +5695,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -5753,7 +5725,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6031,7 +6002,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6062,7 +6032,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6187,7 +6156,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6496,7 +6464,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6534,7 +6501,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -6696,7 +6662,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7111,7 +7076,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7149,7 +7113,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7311,7 +7274,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7765,7 +7727,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -7818,7 +7779,6 @@ paths: anyOf: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - nullable: true - required: true responses: '204': description: Success @@ -9373,7 +9333,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9405,7 +9364,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9731,7 +9689,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9769,7 +9726,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -9931,7 +9887,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -10346,7 +10301,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -10385,7 +10339,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -10552,7 +10505,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -11171,7 +11123,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -11337,7 +11288,6 @@ paths: anyOf: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - nullable: true - required: true responses: '204': description: Success @@ -12370,7 +12320,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12408,7 +12357,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12761,7 +12709,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12799,7 +12746,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -12961,7 +12907,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -13408,7 +13353,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -13453,7 +13397,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -13650,7 +13593,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14377,7 +14319,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14557,7 +14498,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14595,7 +14535,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14948,7 +14887,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -14986,7 +14924,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15148,7 +15085,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15536,7 +15472,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15581,7 +15516,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -15778,7 +15712,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16325,7 +16258,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16560,7 +16492,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16605,7 +16536,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -16802,7 +16732,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18042,7 +17971,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18080,7 +18008,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18433,7 +18360,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18471,7 +18397,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -18633,7 +18558,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19008,7 +18932,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19053,7 +18976,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19250,7 +19172,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19750,7 +19671,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19795,7 +19715,6 @@ paths: type: array items: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -19992,7 +19911,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -20539,7 +20457,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Location' - required: true responses: '204': description: Success @@ -20608,7 +20525,6 @@ paths: anyOf: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - nullable: true - required: true responses: '204': description: Success From 20bbbffdb411da8787ee47e6d37e5736ea993465 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 16 Jan 2026 13:04:04 -0500 Subject: [PATCH 05/11] ci: aligns with main branch --- .github/workflows/auto-merge-dependabot.yml | 2 +- redocly.yaml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 redocly.yaml diff --git a/.github/workflows/auto-merge-dependabot.yml b/.github/workflows/auto-merge-dependabot.yml index d454cd18..ba2243c9 100644 --- a/.github/workflows/auto-merge-dependabot.yml +++ b/.github/workflows/auto-merge-dependabot.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v2.4.0 + uses: dependabot/fetch-metadata@v2.5.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/redocly.yaml b/redocly.yaml new file mode 100644 index 00000000..423d5aeb --- /dev/null +++ b/redocly.yaml @@ -0,0 +1,15 @@ +extends: + - recommended + +rules: + operation-4xx-response: off + nullable-type-sibling: off + no-server-example.com: off + no-server-trailing-slash: off + no-unused-components: off + security-defined: off + info-license-url: off + info-license: off + no-empty-servers: off + operation-summary: off + tag-description: off \ No newline at end of file From 0db79f382f8dd19fcc91f575e58436dc4adbd27d Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 18:20:54 +0000 Subject: [PATCH 06/11] chore(support/v2): release 2.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ Directory.Build.props | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 65f558e7..656a2ef1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.0.0" + ".": "2.1.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a38c6fc2..ffe31aa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.1.0](https://github.com/microsoft/OpenAPI.NET.OData/compare/v2.0.0...v2.1.0) (2026-01-16) + + +### Features + +* allow optional body parameter ([#773](https://github.com/microsoft/OpenAPI.NET.OData/issues/773)) ([caca191](https://github.com/microsoft/OpenAPI.NET.OData/commit/caca1913e3ae47bfc33049a026c65a689b777a85)) +* allow optional body parameter ([#773](https://github.com/microsoft/OpenAPI.NET.OData/issues/773)) ([0a20869](https://github.com/microsoft/OpenAPI.NET.OData/commit/0a208694394f8ed88efbb4ae352f502a253da7b6)) + ## [2.0.0](https://github.com/microsoft/OpenAPI.NET.OData/compare/v2.0.0-preview.18...v2.0.0) (2025-07-10) diff --git a/Directory.Build.props b/Directory.Build.props index 727f6782..eb0aa211 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ https://github.com/Microsoft/OpenAPI.NET.OData © Microsoft Corporation. All rights reserved. Microsoft OpenApi OData EDM - 2.0.0 + 2.1.0 From 1054b7f7a3acf6a201fa2463d3e753f3f3413daa Mon Sep 17 00:00:00 2001 From: Gavin Barron Date: Wed, 18 Mar 2026 09:32:53 -0700 Subject: [PATCH 07/11] feat: add int32 format configuration for pagination parameters and count responses (#793) Add two new boolean settings to OpenApiConvertSettings: - UseInt32ForPaginationParameters: when true, generates $top and $skip parameters with int32 format instead of the default int64 - UseInt32ForCountResponses: when true, generates $count response schema and @odata.count properties with int32 format instead of int64 Both settings default to false, preserving existing behavior. They are configured via the HIDI settings config file under OpenApiConvertSettings. Closes #792 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Generator/OpenApiParameterGenerator.cs | 12 ++++---- .../Generator/OpenApiResponseGenerator.cs | 3 +- .../Generator/OpenApiSchemaGenerator.cs | 14 ++++++--- .../OData/ODataConstants.cs | 14 +++++++++ .../OpenApiConvertSettings.cs | 14 ++++++++- .../PublicAPI.Unshipped.txt | 4 +++ .../OpenApiParameterGeneratorTests.cs | 30 +++++++++++++++++++ .../Generator/OpenApiSchemaGeneratorTests.cs | 25 ++++++++++++++++ 8 files changed, 104 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs index 06087925..4e93f645 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs @@ -34,8 +34,8 @@ public static void AddParametersToDocument(this ODataContext context, OpenApiDoc // It allows defining query options and headers that can be reused across operations of the service. // The value of parameters is a map of Parameter Objects. - document.AddComponent("top", CreateTop(context.Settings.TopExample)); - document.AddComponent("skip", CreateSkip()); + document.AddComponent("top", CreateTop(context.Settings.TopExample, context.Settings.UseInt32ForPaginationParameters)); + document.AddComponent("skip", CreateSkip(context.Settings.UseInt32ForPaginationParameters)); document.AddComponent("count", CreateCount()); document.AddComponent("filter", CreateFilter()); document.AddComponent("search", CreateSearch()); @@ -886,7 +886,7 @@ public static void AppendParameter(this IList parameters, IOp } // #top - private static OpenApiParameter CreateTop(int topExample) + private static OpenApiParameter CreateTop(int topExample, bool useInt32Format = false) { return new OpenApiParameter { @@ -896,7 +896,7 @@ private static OpenApiParameter CreateTop(int topExample) Schema = new OpenApiSchema { Type = JsonSchemaType.Number, - Format = "int64", + Format = useInt32Format ? "int32" : "int64", Minimum = "0", }, Example = topExample, @@ -906,7 +906,7 @@ private static OpenApiParameter CreateTop(int topExample) } // $skip - private static OpenApiParameter CreateSkip() + private static OpenApiParameter CreateSkip(bool useInt32Format = false) { return new OpenApiParameter { @@ -916,7 +916,7 @@ private static OpenApiParameter CreateSkip() Schema = new OpenApiSchema { Type = JsonSchemaType.Number, - Format = "int64", + Format = useInt32Format ? "int32" : "int64", Minimum = "0", }, Style = ParameterStyle.Form, diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs index 2c5f193c..83b306c1 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs @@ -195,7 +195,8 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp } if (context.Settings.EnableCount) { - baseSchema.Properties.Add(ODataConstants.OdataCount.Key, ODataConstants.OdataCount.Value); + var odataCount = ODataConstants.CreateOdataCount(context.Settings.UseInt32ForCountResponses); + baseSchema.Properties.Add(odataCount.Key, odataCount.Value); } schema = baseSchema; } diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs index df83013b..0fbd9541 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs @@ -48,7 +48,7 @@ public static void AddSchemasToDocument(this ODataContext context, OpenApiDocume if(context.Settings.EnableDollarCountPath) document.AddComponent(Constants.DollarCountSchemaName, new OpenApiSchema { Type = JsonSchemaType.Number, - Format = "int64" + Format = context.Settings.UseInt32ForCountResponses ? "int32" : "int64" }); if(context.HasAnyNonContainedCollections()) @@ -101,7 +101,10 @@ public static void AddSchemasToDocument(this ODataContext context, OpenApiDocume responseSchema.Properties ??= new Dictionary(); if (context.Settings.EnableCount) - responseSchema.Properties.Add(ODataConstants.OdataCount.Key, ODataConstants.OdataCount.Value); + { + var odataCount = ODataConstants.CreateOdataCount(context.Settings.UseInt32ForCountResponses); + responseSchema.Properties.Add(odataCount.Key, odataCount.Value); + } if (context.Settings.EnablePagination) responseSchema.Properties.Add(ODataConstants.OdataNextLink.Key, ODataConstants.OdataNextLink.Value); } @@ -261,10 +264,13 @@ private static OpenApiSchema CreateCollectionSchema(ODataContext context, IOpenA baseSchema.Properties.Add(ODataConstants.OdataNextLink.Key, ODataConstants.OdataNextLink.Value); if (context.Settings.EnableCount) - baseSchema.Properties.Add(ODataConstants.OdataCount.Key, ODataConstants.OdataCount.Value); + { + var odataCount = ODataConstants.CreateOdataCount(context.Settings.UseInt32ForCountResponses); + baseSchema.Properties.Add(odataCount.Key, odataCount.Value); + } collectionSchema = baseSchema; - } + } } else { diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs index d8aec5fb..090f55f4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs @@ -3,6 +3,7 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using System; using System.Collections.Generic; namespace Microsoft.OpenApi.OData @@ -27,8 +28,21 @@ internal static class ODataConstants /// /// @odata.count KeyValue pair /// + [Obsolete("Use CreateOdataCount instead to specify the format of the count value.")] public readonly static KeyValuePair OdataCount = new("@odata.count", new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "int64"}); + /// + /// Creates an @odata.count KeyValue pair with the specified format. + /// + public static KeyValuePair CreateOdataCount(bool useInt32Format) + { + return new("@odata.count", new OpenApiSchema + { + Type = JsonSchemaType.Number | JsonSchemaType.Null, + Format = useInt32Format ? "int32" : "int64" + }); + } + /// /// @odata.deltaLink KeyValue pair /// diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs index a7021c44..7effbc0c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs @@ -337,6 +337,16 @@ public string? PathPrefix /// public int ComposableFunctionsExpansionDepth { get; set; } = 1; + /// + /// Gets/Sets a value indicating whether common OData number parameters ($top, $skip) should use int32 format instead of int64. + /// + public bool UseInt32ForPaginationParameters { get; set; } = false; + + /// + /// Gets/Sets a value indicating whether the $count response schema should use int32 format instead of int64. + /// + public bool UseInt32ForCountResponses { get; set; } = false; + internal OpenApiConvertSettings Clone() { var newSettings = new OpenApiConvertSettings @@ -392,7 +402,9 @@ internal OpenApiConvertSettings Clone() SemVerVersion = this.SemVerVersion, EnableAliasForOperationSegments = this.EnableAliasForOperationSegments, UseStringArrayForQueryOptionsSchema = this.UseStringArrayForQueryOptionsSchema, - ComposableFunctionsExpansionDepth = this.ComposableFunctionsExpansionDepth + ComposableFunctionsExpansionDepth = this.ComposableFunctionsExpansionDepth, + UseInt32ForPaginationParameters = this.UseInt32ForPaginationParameters, + UseInt32ForCountResponses = this.UseInt32ForCountResponses }; return newSettings; diff --git a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt index b175f6a1..01b1978b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt @@ -201,6 +201,10 @@ Microsoft.OpenApi.OData.OpenApiConvertSettings.RoutePathPrefixProvider.get -> Mi Microsoft.OpenApi.OData.OpenApiConvertSettings.RoutePathPrefixProvider.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.SemVerVersion.get -> string! Microsoft.OpenApi.OData.OpenApiConvertSettings.SemVerVersion.set -> void +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseInt32ForPaginationParameters.get -> bool +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseInt32ForPaginationParameters.set -> void +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseInt32ForCountResponses.get -> bool +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseInt32ForCountResponses.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.ServiceRoot.get -> System.Uri! Microsoft.OpenApi.OData.OpenApiConvertSettings.ServiceRoot.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.ShowExternalDocs.get -> bool diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs index ba60bbd8..5e3f86bc 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs @@ -655,5 +655,35 @@ public static IEdmModel GetEdmModel() Assert.True(result); return model; } + + [Theory] + [InlineData(true, "int32")] + [InlineData(false, "int64")] + public async Task CreateParametersRespectsUseInt32ForPaginationParameters(bool useInt32, string expectedFormat) + { + // Arrange + IEdmModel model = EdmCoreModel.Instance; + OpenApiConvertSettings settings = new() + { + UseInt32ForPaginationParameters = useInt32 + }; + ODataContext context = new ODataContext(model, settings); + OpenApiDocument openApiDocument = new(); + + // Act + context.AddParametersToDocument(openApiDocument); + var parameters = openApiDocument.Components.Parameters; + + // Assert + Assert.NotNull(parameters); + var topParam = parameters.First(p => p.Key == "top").Value; + var skipParam = parameters.First(p => p.Key == "skip").Value; + + var topJson = JsonNode.Parse(await topParam.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0)); + var skipJson = JsonNode.Parse(await skipParam.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0)); + + Assert.Equal(expectedFormat, topJson["schema"]["format"]?.GetValue()); + Assert.Equal(expectedFormat, skipJson["schema"]["format"]?.GetValue()); + } } } \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs index b9698650..8c1e550f 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs @@ -1167,5 +1167,30 @@ public async Task NonNullableUntypedPropertyWorks() Assert.Equal("{ }", json); } + + [Theory] + [InlineData(true, "int32")] + [InlineData(false, "int64")] + public void DollarCountSchemaRespectsUseInt32ForCountResponses(bool useInt32, string expectedFormat) + { + // Arrange + IEdmModel model = EdmModelHelper.TripServiceModel; + OpenApiDocument openApiDocument = new(); + OpenApiConvertSettings settings = new() + { + EnableDollarCountPath = true, + UseInt32ForCountResponses = useInt32 + }; + ODataContext context = new(model, settings); + + // Act + context.AddSchemasToDocument(openApiDocument); + + // Assert + Assert.True(openApiDocument.Components.Schemas.TryGetValue(Constants.DollarCountSchemaName, out var countSchema)); + Assert.NotNull(countSchema); + Assert.Equal(JsonSchemaType.Number, countSchema.Type); + Assert.Equal(expectedFormat, countSchema.Format); + } } } From 2da64a7535377369c963a75592b6e158e3d1f7fb Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Mar 2026 11:18:04 -0400 Subject: [PATCH 08/11] Merge pull request #770 from microsoft/feat/use-put-for-update feat: add switch to use put as default update verb --- .../OpenApiConvertSettings.cs | 10 ++ .../PathItem/ComplexPropertyItemHandler.cs | 11 +- .../PathItem/EntityPathItemHandler.cs | 11 +- .../NavigationPropertyPathItemHandler.cs | 11 +- .../PublicAPI.Unshipped.txt | 2 + src/OoasUtil/ComLineProcessor.cs | 32 +++++ src/OoasUtil/Program.cs | 1 + .../ComplexPropertyPathItemHandlerTests.cs | 97 ++++++++++++++ .../PathItem/EntityPathItemHandlerTests.cs | 61 +++++++++ .../NavigationPropertyPathItemHandlerTests.cs | 122 ++++++++++++++++++ 10 files changed, 355 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs index 7effbc0c..93e56e9b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs @@ -337,6 +337,15 @@ public string? PathPrefix /// public int ComposableFunctionsExpansionDepth { get; set; } = 1; + /// + /// Gets/sets a value indicating whether to use HTTP PUT method for update operations by default + /// instead of PATCH when no UpdateRestrictions annotation is present in the CSDL. + /// If false (default), PATCH will be used for updates. + /// If true, PUT will be used for updates. + /// This setting is ignored when UpdateRestrictions annotations are present in the CSDL. + /// + public bool UseHttpPutForUpdate { get; set; } = false; + /// /// Gets/Sets a value indicating whether common OData number parameters ($top, $skip) should use int32 format instead of int64. /// @@ -403,6 +412,7 @@ internal OpenApiConvertSettings Clone() EnableAliasForOperationSegments = this.EnableAliasForOperationSegments, UseStringArrayForQueryOptionsSchema = this.UseStringArrayForQueryOptionsSchema, ComposableFunctionsExpansionDepth = this.ComposableFunctionsExpansionDepth, + UseHttpPutForUpdate = this.UseHttpPutForUpdate, UseInt32ForPaginationParameters = this.UseInt32ForPaginationParameters, UseInt32ForCountResponses = this.UseInt32ForCountResponses }; diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs index 6596750e..1e4e7a83 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/ComplexPropertyItemHandler.cs @@ -99,7 +99,16 @@ public void AddUpdateOperation(OpenApiPathItem item) } else { - AddOperation(item, HttpMethod.Patch); + // When no explicit update method is specified in UpdateRestrictions, + // use the UseHttpPutForUpdate setting to determine the default method + if (Context?.Settings?.UseHttpPutForUpdate == true) + { + AddOperation(item, HttpMethod.Put); + } + else + { + AddOperation(item, HttpMethod.Patch); + } } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs index 0487f787..0d4dbdbd 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs @@ -67,7 +67,16 @@ protected override void SetOperations(OpenApiPathItem item) } else { - AddOperation(item, HttpMethod.Patch); + // When no explicit update method is specified in UpdateRestrictions, + // use the UseHttpPutForUpdate setting to determine the default method + if (Context?.Settings?.UseHttpPutForUpdate == true) + { + AddOperation(item, HttpMethod.Put); + } + else + { + AddOperation(item, HttpMethod.Patch); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs index a1c33b15..a86fc5da 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs @@ -279,7 +279,16 @@ private void AddUpdateOperation(OpenApiPathItem item, UpdateRestrictionsType? up } else { - AddOperation(item, HttpMethod.Patch); + // When no explicit update method is specified in UpdateRestrictions, + // use the UseHttpPutForUpdate setting to determine the default method + if (Context?.Settings?.UseHttpPutForUpdate == true) + { + AddOperation(item, HttpMethod.Put); + } + else + { + AddOperation(item, HttpMethod.Patch); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt index 01b1978b..0952d827 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt @@ -225,6 +225,8 @@ Microsoft.OpenApi.OData.OpenApiConvertSettings.UseStringArrayForQueryOptionsSche Microsoft.OpenApi.OData.OpenApiConvertSettings.UseStringArrayForQueryOptionsSchema.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.UseSuccessStatusCodeRange.get -> bool Microsoft.OpenApi.OData.OpenApiConvertSettings.UseSuccessStatusCodeRange.set -> void +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseHttpPutForUpdate.get -> bool +Microsoft.OpenApi.OData.OpenApiConvertSettings.UseHttpPutForUpdate.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.VerifyEdmModel.get -> bool Microsoft.OpenApi.OData.OpenApiConvertSettings.VerifyEdmModel.set -> void Microsoft.OpenApi.OData.Vocabulary.Core.LinkRelKey diff --git a/src/OoasUtil/ComLineProcessor.cs b/src/OoasUtil/ComLineProcessor.cs index 84cb58c3..b8169d50 100644 --- a/src/OoasUtil/ComLineProcessor.cs +++ b/src/OoasUtil/ComLineProcessor.cs @@ -99,6 +99,11 @@ public ComLineProcessor(string[] args) /// public bool? RequireDerivedTypesConstraint { get; private set; } + /// + /// Use HTTP PUT method for update operations by default instead of PATCH. + /// + public bool? UseHttpPutForUpdate { get; private set; } + /// /// Process the arguments. /// @@ -227,6 +232,14 @@ public bool Process() } break; + case "--useputforupdate": + case "-put": + if (!ProcessUseHttpPutForUpdate(true)) + { + return false; + } + break; + default: PrintUsage(); return false; @@ -285,6 +298,11 @@ public bool Process() DisableSchemaExamples = false; } + if (UseHttpPutForUpdate == null) + { + UseHttpPutForUpdate = false; + } + _continue = ValidateArguments(); return _continue; } @@ -419,6 +437,19 @@ private bool ProcessDisableSchemaExamples(bool disableSchemaExamples) return true; } + private bool ProcessUseHttpPutForUpdate(bool useHttpPutForUpdate) + { + if (UseHttpPutForUpdate != null) + { + Console.WriteLine("[Error:] Multiple [--useputforupdate|-put] are not allowed.\n"); + PrintUsage(); + return false; + } + + UseHttpPutForUpdate = useHttpPutForUpdate; + return true; + } + private bool ProcessTarget(int version) { if (Version != null) @@ -484,6 +515,7 @@ public static void PrintUsage() sb.Append(" --enablepagination|-p\t\t\tSet the output to expose pagination for collections.\n"); sb.Append(" --enableunqualifiedcall|-u\t\t\tSet the output to use unqualified calls for bound operations.\n"); sb.Append(" --disableschemaexamples|-x\t\t\tDisable examples in the schema.\n"); + sb.Append(" --useputforupdate|-put\t\t\tUse HTTP PUT method for update operations instead of PATCH by default.\n"); sb.Append(" --json|-j\t\t\tSet the output format as JSON.\n"); sb.Append(" --yaml|-y\t\t\tSet the output format as YAML.\n"); sb.Append(" --specversion|-s IntVersion\tSet the OpenApi Specification version of the output. Only 2 or 3 are supported.\n"); diff --git a/src/OoasUtil/Program.cs b/src/OoasUtil/Program.cs index 211dc0f5..937abdde 100644 --- a/src/OoasUtil/Program.cs +++ b/src/OoasUtil/Program.cs @@ -42,6 +42,7 @@ static async System.Threading.Tasks.Task Main(string[] args) EnableUnqualifiedCall = processor.EnableUnqualifiedCall.Value, ShowSchemaExamples = !processor.DisableSchemaExamples.Value, OpenApiSpecVersion = processor.Version.Value, + UseHttpPutForUpdate = processor.UseHttpPutForUpdate.Value, }; if (processor.IsLocalFile) diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/ComplexPropertyPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/ComplexPropertyPathItemHandlerTests.cs index 0a413cd1..28345303 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/ComplexPropertyPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/ComplexPropertyPathItemHandlerTests.cs @@ -263,4 +263,101 @@ public void CreatesComplexPropertyPathsBasedOnTargetPathAnnotations(string reada Assert.True(pathItem.Operations.ContainsKey(HttpMethod.Get)); } } + + [Theory] + [InlineData(false, 2)] + [InlineData(true, 2)] + public void CreatesComplexPropertyPathItemUsesHttpPutForUpdateWhenSettingIsEnabled(bool useHttpPutForUpdate, int operationCount) + { + // Arrange + var annotation = @" + + + + + + + + + +"; + var target = @"""NS.Customer/BillingAddress"""; + var model = EntitySetPathItemHandlerTests.GetEdmModel(annotation: annotation, target: target); + var convertSettings = new OpenApiConvertSettings + { + UseHttpPutForUpdate = useHttpPutForUpdate + }; + var context = new ODataContext(model, convertSettings); + var entitySet = model.EntityContainer.FindEntitySet("Customers"); + Assert.NotNull(entitySet); // guard + var entityType = entitySet.EntityType; + var property = entityType.FindProperty("BillingAddress"); + Assert.NotNull(property); // guard + var path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataComplexPropertySegment(property as IEdmStructuralProperty)); + Assert.Equal(ODataPathKind.ComplexProperty, path.Kind); // guard + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + Assert.Equal(operationCount, pathItem.Operations?.Count ?? 0); + + Assert.True(pathItem.Operations.ContainsKey(HttpMethod.Get)); + if (useHttpPutForUpdate) + { + Assert.True(pathItem.Operations.ContainsKey(HttpMethod.Put)); + Assert.False(pathItem.Operations.ContainsKey(HttpMethod.Patch)); + } + else + { + Assert.True(pathItem.Operations.ContainsKey(HttpMethod.Patch)); + Assert.False(pathItem.Operations.ContainsKey(HttpMethod.Put)); + } + } + + [Fact] + public void CreateComplexPropertyPathItemPrefersUpdateMethodAnnotationOverUseHttpPutForUpdateSetting() + { + // Arrange - annotation specifies PUT explicitly, setting is disabled (default PATCH) + var annotation = @" + + + + Org.OData.Capabilities.V1.HttpMethod/PUT + + + + + + + + +"; + var target = @"""NS.Customer/BillingAddress"""; + var model = EntitySetPathItemHandlerTests.GetEdmModel(annotation: annotation, target: target); + var convertSettings = new OpenApiConvertSettings + { + UseHttpPutForUpdate = false // Setting says use PATCH (default) + }; + var context = new ODataContext(model, convertSettings); + var entitySet = model.EntityContainer.FindEntitySet("Customers"); + Assert.NotNull(entitySet); // guard + var entityType = entitySet.EntityType; + var property = entityType.FindProperty("BillingAddress"); + Assert.NotNull(property); // guard + var path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataComplexPropertySegment(property as IEdmStructuralProperty)); + Assert.Equal(ODataPathKind.ComplexProperty, path.Kind); // guard + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + Assert.Equal(2, pathItem.Operations?.Count ?? 0); + Assert.True(pathItem.Operations.ContainsKey(HttpMethod.Get)); + // Should use PUT from annotation, not PATCH from setting + Assert.True(pathItem.Operations.ContainsKey(HttpMethod.Put)); + Assert.False(pathItem.Operations.ContainsKey(HttpMethod.Patch)); + } } \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs index 7d6c6c61..92885c16 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs @@ -232,6 +232,67 @@ public void CreateEntityPathItemWorksForUpdateMethodRestrictionsCapabilities(boo VerifyPathItemOperations(annotation, expected); } + [Theory] + [InlineData(false, new string[] { "get", "patch", "delete" })] + [InlineData(true, new string[] { "get", "put", "delete" })] + public void CreateEntityPathItemUsesHttpPutForUpdateWhenSettingIsEnabled(bool useHttpPutForUpdate, string[] expected) + { + // Arrange + IEdmModel model = EntitySetPathItemHandlerTests.GetEdmModel(annotation: ""); + OpenApiConvertSettings settings = new OpenApiConvertSettings + { + UseHttpPutForUpdate = useHttpPutForUpdate + }; + ODataContext context = new ODataContext(model, settings); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); + Assert.NotNull(entitySet); // guard + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType)); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + Assert.Equal(expected, pathItem.Operations.Select(e => e.Key.ToString().ToLowerInvariant())); + } + + [Fact] + public void CreateEntityPathItemPrefersUpdateMethodAnnotationOverUseHttpPutForUpdateSetting() + { + // Arrange - annotation specifies PUT explicitly, setting is disabled (default PATCH) + string annotation = @" + + + + Org.OData.Capabilities.V1.HttpMethod/PUT + + +"; + + IEdmModel model = EntitySetPathItemHandlerTests.GetEdmModel(annotation); + OpenApiConvertSettings settings = new OpenApiConvertSettings + { + UseHttpPutForUpdate = false // Setting says use PATCH (default) + }; + ODataContext context = new ODataContext(model, settings); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); + Assert.NotNull(entitySet); // guard + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType)); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + // Should use PUT from annotation, not PATCH from setting + Assert.Equal(new string[] { "get", "put", "delete" }, pathItem.Operations.Select(e => e.Key.ToString().ToLowerInvariant())); + } + private void VerifyPathItemOperations(string annotation, string[] expected) { // Arrange diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs index 32c456d7..76b43541 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs @@ -602,6 +602,128 @@ public void CreateNavigationPropertyPathItemAddsCustomAttributeValuesToPathExten Assert.Equal("true", isHiddenValue); } + [Theory] + [InlineData(false, new string[] { "get", "patch", "delete" })] + [InlineData(true, new string[] { "get", "put", "delete" })] + public void CreateSingleNavigationPropertyPathItemUsesHttpPutForUpdateWhenSettingIsEnabled(bool useHttpPutForUpdate, string[] expected) + { + // Arrange + IEdmModel model = GetEdmModel(""); + OpenApiConvertSettings settings = new OpenApiConvertSettings + { + UseHttpPutForUpdate = useHttpPutForUpdate + }; + ODataContext context = new ODataContext(model, settings); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); + Assert.NotNull(entitySet); // guard + IEdmEntityType entityType = entitySet.EntityType; + + IEdmNavigationProperty property = entityType.DeclaredNavigationProperties() + .FirstOrDefault(c => c.ContainsTarget == true && c.TargetMultiplicity() != EdmMultiplicity.Many); + Assert.NotNull(property); + + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), + new ODataKeySegment(entityType), + new ODataNavigationPropertySegment(property)); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + Assert.Equal(expected, pathItem.Operations.Select(o => o.Key.ToString().ToLowerInvariant())); + } + + [Theory] + [InlineData(false, new string[] { "get", "patch", "delete" })] + [InlineData(true, new string[] { "get", "put", "delete" })] + public void CreateCollectionNavigationPropertyPathItemUsesHttpPutForUpdateWhenSettingIsEnabled(bool useHttpPutForUpdate, string[] expected) + { + // Arrange + IEdmModel model = GetEdmModel(""); + OpenApiConvertSettings settings = new OpenApiConvertSettings + { + UseHttpPutForUpdate = useHttpPutForUpdate + }; + ODataContext context = new ODataContext(model, settings); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); + Assert.NotNull(entitySet); // guard + IEdmEntityType entityType = entitySet.EntityType; + + IEdmNavigationProperty property = entityType.DeclaredNavigationProperties() + .FirstOrDefault(c => c.ContainsTarget == true && c.TargetMultiplicity() == EdmMultiplicity.Many); + Assert.NotNull(property); + + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), + new ODataKeySegment(entityType), + new ODataNavigationPropertySegment(property), + new ODataKeySegment(property.ToEntityType())); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + Assert.Equal(expected, pathItem.Operations.Select(o => o.Key.ToString().ToLowerInvariant())); + } + + [Fact] + public void CreateNavigationPropertyPathItemPrefersUpdateMethodAnnotationOverUseHttpPutForUpdateSetting() + { + // Arrange - annotation specifies PUT explicitly, setting is disabled (default PATCH) + string annotation = @" + + + + + + + + + + Org.OData.Capabilities.V1.HttpMethod/PUT + + + + + + + +"; + + IEdmModel model = GetEdmModel(annotation); + OpenApiConvertSettings settings = new OpenApiConvertSettings + { + UseHttpPutForUpdate = false // Setting says use PATCH (default) + }; + ODataContext context = new ODataContext(model, settings); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); + Assert.NotNull(entitySet); // guard + IEdmEntityType entityType = entitySet.EntityType; + + IEdmNavigationProperty property = entityType.DeclaredNavigationProperties() + .FirstOrDefault(c => c.ContainsTarget == true && c.Name == "ContainedMyOrder"); + Assert.NotNull(property); + + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), + new ODataKeySegment(entityType), + new ODataNavigationPropertySegment(property)); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + // Should use PUT from annotation, not PATCH from setting + Assert.Equal(new string[] { "get", "put", "delete" }, pathItem.Operations.Select(o => o.Key.ToString().ToLowerInvariant())); + } + public static IEdmModel GetEdmModel(string annotation, string annotation2 = "") { const string template = @" From d24d3c80c5b6050935857638e658952f652aa777 Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 23:05:28 +0000 Subject: [PATCH 09/11] chore(support/v2): release 2.2.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 10 ++++++++++ Directory.Build.props | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 656a2ef1..bfc26f9c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.1.0" + ".": "2.2.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe31aa0..20c81911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.2.0](https://github.com/microsoft/OpenAPI.NET.OData/compare/v2.1.0...v2.2.0) (2026-03-19) + + +### Features + +* add int32 format configuration for pagination parameters and count responses ([#793](https://github.com/microsoft/OpenAPI.NET.OData/issues/793)) ([305eacc](https://github.com/microsoft/OpenAPI.NET.OData/commit/305eacccc2a359a9c9da23a5d86a436bfe22cfd7)) +* add int32 format configuration for pagination parameters and count responses ([#793](https://github.com/microsoft/OpenAPI.NET.OData/issues/793)) ([1054b7f](https://github.com/microsoft/OpenAPI.NET.OData/commit/1054b7f7a3acf6a201fa2463d3e753f3f3413daa)), closes [#792](https://github.com/microsoft/OpenAPI.NET.OData/issues/792) +* add switch to use put as default update verb ([2da64a7](https://github.com/microsoft/OpenAPI.NET.OData/commit/2da64a7535377369c963a75592b6e158e3d1f7fb)) +* adds settings to map the update verb to put ([bef4c96](https://github.com/microsoft/OpenAPI.NET.OData/commit/bef4c969539ef6455963920b51838c1f71a3d811)) + ## [2.1.0](https://github.com/microsoft/OpenAPI.NET.OData/compare/v2.0.0...v2.1.0) (2026-01-16) diff --git a/Directory.Build.props b/Directory.Build.props index eb0aa211..b5d03221 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ https://github.com/Microsoft/OpenAPI.NET.OData © Microsoft Corporation. All rights reserved. Microsoft OpenApi OData EDM - 2.1.0 + 2.2.0 From ff9ab41d7e7c9a42797ee77213c8442e20c52e3a Mon Sep 17 00:00:00 2001 From: "Gavin Barron (from Dev Box)" Date: Mon, 13 Apr 2026 17:57:14 -0700 Subject: [PATCH 10/11] fix: TryAddPath exact-match check for duplicate bound operation paths When a duplicate path is detected in TryAddPath, the existing heuristic checks if the new operation's binding type has derived types and, if so, keeps the first entry assuming it was more specific. This is incorrect when the first entry came from a base type (e.g., directoryObject) and the new entry is the exact match for the entity set (e.g., servicePrincipal). Add an exact-match check: if the operation's binding type matches the entity set type, always replace the existing entry regardless of derived types. This ensures paths like /servicePrincipals/delta() return the correct type (servicePrincipal) instead of the base type (directoryObject). Fixes #806 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Common/Utils.cs | 7 ++ .../Edm/ODataPathProviderTests.cs | 80 +++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs index 9c037889..c2f3c312 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs @@ -345,6 +345,13 @@ internal static bool TryAddPath(this IDictionary pathI if (derivedTypes?.Any() ?? false) { + if (boundEntityType != null && boundEntityType == operationEntityType) + { + // The operation's binding type exactly matches the entity set's type, + // so this is a more specific overload than whatever was added first. + pathItems[pathName] = pathItem; + return true; + } if (boundEntityType != null && !derivedTypes.Contains(boundEntityType)) { Debug.WriteLine($"Duplicate paths present but entity type of binding parameter '{operationEntityType}' " + diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs index a450bc04..630af975 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs @@ -7,11 +7,14 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; using Microsoft.OData.Edm.Validation; +using Microsoft.OpenApi; using Microsoft.OpenApi.OData.Tests; using Xunit; @@ -921,6 +924,83 @@ private static IEdmModel GetNavPropModel(string annotation) return GetEdmModel(template); } + [Fact] + public async Task GetPathsForDerivedTypeDeltaFunctionUsesCorrectReturnType() + { + // Arrange – mirrors the Graph scenario: + // directoryObject (base) has delta with RequiresExplicitBinding + // servicePrincipal (derived) has its own delta + // agentIdentity (derived from servicePrincipal) causes servicePrincipal to have derived types + // Bug: TryAddPath kept the base-type delta for /servicePrincipals/delta() because + // servicePrincipal has derived types. + string csdl = @" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NS.delta + + + + + +"; + + bool result = CsdlReader.TryParse(XElement.Parse(csdl).CreateReader(), out IEdmModel model, out _); + Assert.True(result); + + var settings = new OpenApiConvertSettings(); + var doc = model.ConvertToOpenApi(settings); + + // Serialize to YAML and verify the response type + using var stream = new MemoryStream(); + await doc.SerializeAsync(stream, OpenApiSpecVersion.OpenApi3_1, "yaml", CancellationToken.None); + stream.Position = 0; + string yaml = await new StreamReader(stream).ReadToEndAsync(); + + // The /servicePrincipals/NS.delta() path should reference servicePrincipal, not directoryObject + Assert.Contains("/servicePrincipals/NS.delta()", yaml); + + // Extract just the path section (up to 'components:' or next top-level key) + int pathIndex = yaml.IndexOf("/servicePrincipals/NS.delta():"); + Assert.True(pathIndex >= 0, "Path /servicePrincipals/NS.delta() not found in YAML output"); + + int componentsIndex = yaml.IndexOf("\ncomponents:", pathIndex); + string pathSection = componentsIndex > 0 + ? yaml.Substring(pathIndex, componentsIndex - pathIndex) + : yaml.Substring(pathIndex); + + // The response schema items $ref should reference servicePrincipal + Assert.Contains("'#/components/schemas/NS.servicePrincipal'", pathSection); + Assert.DoesNotContain("#/components/schemas/NS.directoryObject", pathSection); + } + private static IEdmModel GetEdmModel(string schema) { bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(schema)) }, out IEdmModel parsedModel, out IEnumerable errors); From 4ba74985b9295ca8ec7f20e570a22162e66c6549 Mon Sep 17 00:00:00 2001 From: "release-please-token-provider[bot]" <225477224+release-please-token-provider[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:16:14 +0000 Subject: [PATCH 11/11] chore(support/v2): release 2.2.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ Directory.Build.props | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bfc26f9c..89d8ff81 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.2.0" + ".": "2.2.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c81911..ed2261a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.2.1](https://github.com/microsoft/OpenAPI.NET.OData/compare/v2.2.0...v2.2.1) (2026-04-14) + + +### Bug Fixes + +* TryAddPath exact-match check for duplicate bound operation paths ([ff9ab41](https://github.com/microsoft/OpenAPI.NET.OData/commit/ff9ab41d7e7c9a42797ee77213c8442e20c52e3a)), closes [#806](https://github.com/microsoft/OpenAPI.NET.OData/issues/806) +* TryAddPath exact-match check for duplicate bound operation paths (OpenAPI 3.1) ([c47009a](https://github.com/microsoft/OpenAPI.NET.OData/commit/c47009a5facb18aab18e4e60d180db7001d122e9)) + ## [2.2.0](https://github.com/microsoft/OpenAPI.NET.OData/compare/v2.1.0...v2.2.0) (2026-03-19) diff --git a/Directory.Build.props b/Directory.Build.props index b5d03221..6192a4ec 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ https://github.com/Microsoft/OpenAPI.NET.OData © Microsoft Corporation. All rights reserved. Microsoft OpenApi OData EDM - 2.2.0 + 2.2.1