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 = @"