diff --git a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
index c9dfa666..f5033171 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
+++ b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
@@ -26,6 +26,7 @@
- Adds a delete operation and a required @id query parameter to collection-valued navigation property paths with $ref #453
- Fixes inconsistency of nullability of schemas of properties that are a collection of structured types #467
- Generates $expand query parameter for operations whose return type is a collection #481
+- Adds delete operation for non-contained navigation properties only if explicitly allowed via annotation #483
Microsoft.OpenApi.OData.Reader
..\..\tool\Microsoft.OpenApi.OData.snk
diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
index 7445d5e2..47bc6d4b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
@@ -247,7 +247,7 @@ public string PathPrefix
///
/// Gets/Sets a value indicating whether or not to expand derived types to retrieve their declared navigation properties.
///
- [Obsolete("Use RetrieveDerivedTypesProperties to Get or Set the value.")]
+ [Obsolete("Use GenerateDerivedTypesProperties to Get or Set the value.")]
public bool ExpandDerivedTypesNavigationProperties
{
get => GenerateDerivedTypesProperties;
@@ -299,7 +299,7 @@ public bool ExpandDerivedTypesNavigationProperties
public bool RequireRestrictionAnnotationsToGenerateComplexPropertyPaths { get; set; } = true;
///
- /// Gets/sets a dictionary containing a mapping of custom atttribute names and extension names.
+ /// Gets/sets a dictionary containing a mapping of custom attribute names and extension names.
///
public Dictionary CustomXMLAttributesMapping { get; set; } = new();
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs
index a95743e1..37084b61 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs
@@ -1,4 +1,4 @@
-// ------------------------------------------------------------
+// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
@@ -197,31 +197,26 @@ private void AddDeleteOperation(OpenApiPathItem item, NavigationPropertyRestrict
Debug.Assert(!LastSegmentIsRefSegment);
DeleteRestrictionsType navPropDeleteRestriction = restriction?.DeleteRestrictions ??
- Context.Model.GetRecord(NavigationProperty);
-
- if (NavigationProperty.ContainsTarget)
- {
- DeleteRestrictionsType entityDeleteRestriction = Context.Model.GetRecord(_navPropEntityType);
- bool isDeletableDefault = navPropDeleteRestriction == null && entityDeleteRestriction == null;
-
- if (isDeletableDefault ||
- ((entityDeleteRestriction?.IsDeletable ?? true) &&
- (navPropDeleteRestriction?.IsDeletable ?? true)))
- {
- if (NavigationProperty.TargetMultiplicity() != EdmMultiplicity.Many || LastSegmentIsKeySegment)
- {
- AddOperation(item, OperationType.Delete);
- }
- }
+ Context.Model.GetRecord(NavigationProperty);
+
+ if (!(NavigationProperty.TargetMultiplicity() != EdmMultiplicity.Many || LastSegmentIsKeySegment))
+ return;
+
+ DeleteRestrictionsType entityDeleteRestriction = Context.Model.GetRecord(_navPropEntityType);
+ bool isDeletable =
+ (navPropDeleteRestriction == null && entityDeleteRestriction == null) ||
+ ((entityDeleteRestriction?.IsDeletable ?? true) &&
+ (navPropDeleteRestriction?.IsDeletable ?? true));
+
+ if (NavigationProperty.ContainsTarget && isDeletable)
+ {
+ AddOperation(item, OperationType.Delete);
}
- else
- {
- if ((navPropDeleteRestriction?.IsDeletable ?? false) &&
- (NavigationProperty.TargetMultiplicity() != EdmMultiplicity.Many ||
- LastSegmentIsKeySegment))
- {
- AddOperation(item, OperationType.Delete);
- }
+ else if (navPropDeleteRestriction?.Deletable ?? false)
+ {
+ // Add delete operation for non-contained nav. props only if explicitly set to true via annotation
+ // Note: Use Deletable and NOT IsDeletable
+ AddOperation(item, OperationType.Delete);
}
return;
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs
index e06ce16d..66aedac9 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs
@@ -61,12 +61,22 @@ public void CreatePathItemThrowsForNonNavigationPropertyPath()
[Theory]
[InlineData(true, true, new OperationType[] { OperationType.Get, OperationType.Patch, OperationType.Delete })]
[InlineData(true, false, new OperationType[] { OperationType.Get, OperationType.Post })]
- [InlineData(false, true, new OperationType[] { OperationType.Get })]
+ [InlineData(false, true, new OperationType[] { OperationType.Get, OperationType.Delete })] // Deletablity explicitly set via annotation
[InlineData(false, false, new OperationType[] { OperationType.Get})]
public void CreateCollectionNavigationPropertyPathItemReturnsCorrectPathItem(bool containment, bool keySegment, OperationType[] expected)
{
+ string annotation =
+ containment ?
+ "" :
+ @"
+
+
+
+
+";
+
// Arrange
- IEdmModel model = GetEdmModel("");
+ IEdmModel model = GetEdmModel(annotation: "", annotation2: annotation);
ODataContext context = new ODataContext(model);
IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers");
Assert.NotNull(entitySet); // guard
@@ -591,7 +601,7 @@ public void CreateNavigationPropertyPathItemAddsCustomAttributeValuesToPathExten
Assert.Equal("true", isHiddenValue);
}
- public static IEdmModel GetEdmModel(string annotation)
+ public static IEdmModel GetEdmModel(string annotation, string annotation2 = "")
{
const string template = @"
@@ -629,11 +639,14 @@ public static IEdmModel GetEdmModel(string annotation)
{0}
+
+ {1}
+
";
- string modelText = string.Format(template, annotation);
+ string modelText = string.Format(template, annotation, annotation2);
IEdmModel model;
IEnumerable errors;