Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context url for expand #1286

Merged
merged 5 commits into from
Oct 22, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Microsoft.OData.Core/JsonLight/ODataJsonLightReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ private bool ReadAtStartImplementationSynchronously(
? null
: this.jsonLightResourceDeserializer.ContextUriParseResult.SelectQueryOption;

SelectedPropertiesNode selectedProperties = SelectedPropertiesNode.Create(selectQueryOption);
SelectedPropertiesNode selectedProperties = SelectedPropertiesNode.Create(selectQueryOption, this.CurrentResourceType, this.jsonLightInputContext.Model);

if (this.ReadingResourceSet)
{
Expand Down Expand Up @@ -1493,7 +1493,7 @@ private void ReadNextResourceSetItem()
break;
case JsonNodeType.StartArray:
// we are at the start of a nested resource set
this.ReadResourceSetStart(new ODataResourceSet(), SelectedPropertiesNode.EntireSubtree);
this.ReadResourceSetStart(new ODataResourceSet(), new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree));
break;
case JsonNodeType.EndArray:
// we are at the end of a resource set
Expand Down Expand Up @@ -1925,7 +1925,7 @@ private void ReadNextNestedResourceInfoContentItemInRequest()
if (nestedResourceInfo.NestedResourceInfo.IsCollection == true)
{
// because this is a request, there is no $select query option.
SelectedPropertiesNode selectedProperties = SelectedPropertiesNode.EntireSubtree;
SelectedPropertiesNode selectedProperties = new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree);
ODataDeltaResourceSet deltaResourceSet = nestedResourceInfo.NestedResourceSet as ODataDeltaResourceSet;
if (deltaResourceSet != null)
{
Expand Down
14 changes: 3 additions & 11 deletions src/Microsoft.OData.Core/ODataContextUrlInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,9 @@ private static string CreateSelectExpandContextUriSegment(SelectExpandClause sel
/// <returns>The generated expand string.</returns>
private static string ProcessSubExpand(string expandNode, string subExpand, ODataVersion version)
{
return string.IsNullOrEmpty(subExpand) && version <= ODataVersion.V4 ? null :
Copy link
Member

@xuzhg xuzhg Oct 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string.IsNullOrEmpty(subExpand) [](start = 19, length = 31)

Should we keep "string.IsNullOrEmpty(subExpand) " check and return "null"? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do need to include the case of null and return "()" for expanded entity.


In reply to: 224171315 [](ancestors = 224171315)

expandNode + ODataConstants.ContextUriProjectionStart + subExpand + ODataConstants.ContextUriProjectionEnd;

// TODO: cleanup the version parameter.
Copy link
Member

@mikepizzo mikepizzo Oct 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// TODO: cleanup the version parameter. [](start = 12, length = 39)

// TODO: cleanup the version parameter. [](start = 12, length = 39)

what work is left? not passing the version parameter to the method? do you have an issue filed for that? #Closed

Copy link
Contributor Author

@biaol-odata biaol-odata Oct 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is just potential cleanups from caller side, wherever applicable, after reviewing changes in this PR and confirming that the dependency on version (V4/V401) should be removed. The cleanup should be straight forward when this PR is finalized. #Closed

return expandNode + ODataConstants.ContextUriProjectionStart + subExpand + ODataConstants.ContextUriProjectionEnd;
}

/// <summary>Create combined result string using selected items list and expand items list.</summary>
Expand All @@ -417,15 +418,6 @@ private static string CombineSelectAndExpandResult(IList<string> selectList, ILi

if (selectList.Any())
{
// https://github.com/OData/odata.net/issues/1104
// If the user explicitly selects and expands a nav prop, we should include both forms in contextUrl
// We can't, though, because SelectExpandClauseFinisher.AddExplicitNavPropLinksWhereNecessary adds all of
// the expanded items to the select before it gets here, so we can't tell what is explicitly selected by the user.
foreach (var item in expandList)
{
string expandNode = item.Substring(0, item.IndexOf(ODataConstants.ContextUriProjectionStart));
selectList.Remove(expandNode);
}

currentExpandClause += String.Join(ODataConstants.ContextUriProjectionPropertySeparator, selectList.ToArray());
}
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.OData.Core/ODataMessageWriterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ internal SelectedPropertiesNode SelectedProperties
{
return this.SelectExpandClause != null
? SelectedPropertiesNode.Create(this.SelectExpandClause, this.Version ?? ODataVersion.V4)
: SelectedPropertiesNode.EntireSubtree;
: new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree);
}
}

Expand Down
297 changes: 263 additions & 34 deletions src/Microsoft.OData.Core/SelectedPropertiesNode.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ public static void AddExplicitNavPropLinksWhereNecessary(SelectExpandClause clau
IEnumerable<ODataSelectPath> selectedPaths = selectItems.OfType<PathSelectItem>().Select(item => item.SelectedPath);
foreach (ExpandedNavigationSelectItem navigationSelect in selectItems.Where(I => I.GetType() == typeof(ExpandedNavigationSelectItem)))
{
if (anyPathSelectItems && !selectedPaths.Any(x => x.Equals(navigationSelect.PathToNavigationProperty.ToSelectPath())))
{
clause.AddToSelectedItems(new PathSelectItem(navigationSelect.PathToNavigationProperty.ToSelectPath()));
}

AddExplicitNavPropLinksWhereNecessary(navigationSelect.SelectAndExpand);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,10 @@ internal static void Traverse<T>(this SelectExpandClause selectExpandClause, Fun
{
string currentExpandClause = String.Join("/", expandSelectItem.PathToNavigationProperty.WalkWith(PathSegmentToStringTranslator.Instance).ToArray());
T subResult = default(T);
Copy link
Member

@mikepizzo mikepizzo Oct 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

= default(T) [](start = 27, length = 13)

Since you are no longer conditionally calling Traverse, do you still need to initialize subResult? #Closed

if (expandSelectItem.SelectAndExpand.SelectedItems.Any())
Copy link
Member

@mikepizzo mikepizzo Oct 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expandSelectItem.SelectAndExpand.SelectedItems.Any()) [](start = 20, length = 53)

expandSelectItem.SelectAndExpand.SelectedItems.Any()) [](start = 20, length = 53)

why are you removing this check? won't traverse always return an empty subresult if there are no items in SelectedItems? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restored. Same outcome.


In reply to: 224144946 [](ancestors = 224144946)

{
Traverse(expandSelectItem.SelectAndExpand, processSubResult, combineSelectAndExpand, version, out subResult);
}
Traverse(expandSelectItem.SelectAndExpand, processSubResult, combineSelectAndExpand, version, out subResult);

var expandItem = processSubResult(currentExpandClause, subResult, version);

if (expandItem != null)
{
expandList.Add(expandItem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ public void ExpandEntryQuery()
var queryResults = contextWrapper.Execute<Customer>(new Uri(this.ServiceUri.OriginalString + "/Customer(-9)?$expand=Info")).ToArray();
}

[TestMethod]
public void ExpandEntryQueryWithNestedSelect()
{
var contextWrapper = this.CreateContext();
var queryResults = contextWrapper.Execute<Customer>(new Uri(this.ServiceUri.OriginalString + "/Customer(-9)?$expand=Info($select=Information)")).ToArray();
}

[TestMethod]
public void DerivedTypeExpandWithProjectionFeedQuery()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,9 +697,16 @@ public void QueryEntityAndExpandContainedEntity()
{
Dictionary<string, int[]> testCases = new Dictionary<string, int[]>()
{
{ "Accounts(101)?$expand=MyGiftCard", new int[] {2, 4} },
{ "Accounts(101)?$expand=MyPaymentInstruments", new int[] {4, 15} },
{ "Accounts(101)?$select=AccountID&$expand=MyGiftCard($select=GiftCardID)", new int[] {2, 1} }
{ "Accounts(101)?$select=AccountInfo/FirstName, AccountInfo/LastName", new int[] {1, 0, 0} },
{ "Accounts(101)?$select=AccountID&$expand=MyPaymentInstruments($select=PaymentInstrumentID;$expand=TheStoredPI)", new int[]{7,4,4} },
Copy link
Member

@mikepizzo mikepizzo Oct 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

           { "Accounts(101)?$select=AccountID&$expand=MyPaymentInstruments($select=PaymentInstrumentID;$expand=TheStoredPI) [](start = 0, length = 128)
           { "Accounts(101)?$select=AccountID&$expand=MyPaymentInstruments($select=PaymentInstrumentID;$expand=TheStoredPI) [](start = 0, length = 128)

Do we have any test cases that test multiple nested levels of expand? i.e., $select=AccountID&$expand=MyPaymentInstruments($select=PaymentInstrumentID;$expand=TheStoredPI($select=someproponstoredpi))? #Closed

{ "Accounts(101)?$expand=MyPaymentInstruments($select=PaymentInstrumentID,FriendlyName)", new int[]{4, 15, 4} },

{ "Accounts(101)?$expand=MyGiftCard($select=GiftCardID)", new int[] {2, 4, 4} },

{ "Accounts(101)?$expand=MyGiftCard", new int[] {2, 4, 4} },
{ "Accounts(101)?$expand=MyPaymentInstruments", new int[] {4, 15, 15} },
{ "Accounts(101)?$select=AccountID&$expand=MyGiftCard($select=GiftCardID)", new int[] {2, 1, 1} },
{ "Accounts(101)?$select=AccountID,MyGiftCard&$expand=MyGiftCard($select=GiftCardID)", new int[] {2, 1, 1} },
};

ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings() { BaseUri = ServiceBaseUri };
Expand Down Expand Up @@ -782,7 +789,11 @@ public void QueryEntityAndExpandContainedEntity()

Assert.AreEqual(ODataReaderState.Completed, reader.State);
Assert.AreEqual(testCase.Value[0], entries.Count);
Assert.AreEqual(testCase.Value[1], navigationLinks.Count);

int expectedLinksCount = mimeType.Contains(MimeTypes.ODataParameterFullMetadata)
? testCase.Value[1]
: testCase.Value[2];
Assert.AreEqual(expectedLinksCount, navigationLinks.Count);
Copy link
Member

@mikepizzo mikepizzo Oct 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss. I wouldn't expect expectedLinksCount to vary depending on the full versus minimal metadata. #Closed

Copy link
Contributor Author

@biaol-odata biaol-odata Oct 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the case of "Accounts(101)?$expand=MyPaymentInstruments($select=PaymentInstrumentID,FriendlyName)", full metadata response contains nav links for entities contained by PaymentInstruments, which are not supposed to be materialized in the minimal metadata response.

Edit:
I have made an update to SelectedPropertiesNode.Create(SelectExpandClause) to return entire tree only when AllSelected are true for current level and expanded entities.
Thanks for the catch! #Closed

Copy link
Member

@mikepizzo mikepizzo Oct 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


In reply to: 224632181 [](ancestors = 224632181)

}
}
}
Expand Down Expand Up @@ -1197,9 +1208,9 @@ public void InvokeActionFromODataClientWhichReturnsContainedEntity()
[TestMethod]
public void CreateContainedEntityFromODataClientUsingAddRelatedObject()
{

TestClientContext.Format.UseJson(Model);

// create an an account entity and a contained PI entity
Account newAccount = new Account()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void ODataUriBuilderWithEntitySet()
IEnumerable<PathSelectItem> pathSelectItem = selectItems.Where(I => I.GetType() == typeof(PathSelectItem)).OfType<PathSelectItem>();
Assert.AreEqual(expandedNavigationSelectItem.Count(), 1);
Assert.AreEqual(expandedReferenceSelectItem.Count(), 1);
Assert.AreEqual(pathSelectItem.Count(), 3);
Assert.AreEqual(pathSelectItem.Count(), 2);
NavigationPropertySegment navigationProperty = (NavigationPropertySegment)expandedNavigationSelectItem.First().PathToNavigationProperty.FirstSegment;
Assert.AreEqual(navigationProperty.NavigationProperty.Name, "MyDog");
navigationProperty = (NavigationPropertySegment)expandedReferenceSelectItem.First().PathToNavigationProperty.FirstSegment;
Expand All @@ -93,10 +93,10 @@ public void ODataUriBuilderWithEntitySet()
Assert.AreEqual(searchTermNode.Text, "FA");

Uri actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses);
Assert.AreEqual(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyDog%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);
Assert.AreEqual(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);

actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Slash);
Assert.AreEqual(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyDog%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);
Assert.AreEqual(new Uri("http://www.example.com/People?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);
}

[TestMethod]
Expand Down Expand Up @@ -138,7 +138,7 @@ public void TestODataUriBuilderWithKeySegment()
IEnumerable<PathSelectItem> pathSelectItem = selectItems.Where(I => I.GetType() == typeof(PathSelectItem)).OfType<PathSelectItem>();
Assert.AreEqual(expandedNavigationSelectItem.Count(), 1);
Assert.AreEqual(expandedReferenceSelectItem.Count(), 1);
Assert.AreEqual(pathSelectItem.Count(), 3);
Assert.AreEqual(pathSelectItem.Count(), 2);
NavigationPropertySegment navigationProperty = (NavigationPropertySegment)expandedNavigationSelectItem.First().PathToNavigationProperty.FirstSegment;
Assert.AreEqual(navigationProperty.NavigationProperty.Name, "MyDog");
navigationProperty = (NavigationPropertySegment)expandedReferenceSelectItem.First().PathToNavigationProperty.FirstSegment;
Expand All @@ -161,7 +161,7 @@ public void TestODataUriBuilderWithKeySegment()
SearchTermNode searchTermNode = (SearchTermNode)odataUri.Search.Expression;
Assert.AreEqual(searchTermNode.Text, "FA");
Uri actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses);
Assert.AreEqual(new Uri("http://www.example.com/People(1)?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyDog%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);
Assert.AreEqual(new Uri("http://www.example.com/People(1)?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$orderby=ID&$top=1&$skip=2&$count=true&$search=FA"), actualUri);
}

[TestMethod]
Expand Down Expand Up @@ -203,7 +203,7 @@ public void ODataUriBuilderWithKeyAsSegment()
IEnumerable<PathSelectItem> pathSelectItem = selectItems.Where(I => I.GetType() == typeof(PathSelectItem)).OfType<PathSelectItem>();
Assert.AreEqual(expandedNavigationSelectItem.Count(), 1);
Assert.AreEqual(expandedReferenceSelectItem.Count(), 1);
Assert.AreEqual(pathSelectItem.Count(), 3);
Assert.AreEqual(pathSelectItem.Count(), 2);
NavigationPropertySegment navigationProperty = (NavigationPropertySegment)expandedNavigationSelectItem.First().PathToNavigationProperty.FirstSegment;
Assert.AreEqual(navigationProperty.NavigationProperty.Name, "MyDog");
navigationProperty = (NavigationPropertySegment)expandedReferenceSelectItem.First().PathToNavigationProperty.FirstSegment;
Expand All @@ -219,7 +219,7 @@ public void ODataUriBuilderWithKeyAsSegment()
Assert.AreEqual(odataUri.QueryCount, false);

Uri actualUri = odataUri.BuildUri(ODataUrlKeyDelimiter.Slash);
Assert.AreEqual(new Uri("http://www.example.com/People/1?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyDog%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$top=1&$skip=2&$count=false"), actualUri);
Assert.AreEqual(new Uri("http://www.example.com/People/1?$filter=MyDog%2FColor%20eq%20%27Brown%27&$select=ID%2CMyCat&$expand=MyDog%2CMyCat%2F%24ref&$top=1&$skip=2&$count=false"), actualUri);
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,21 @@ public ODataEntryMetadataContextTest()
{
this.entry = new ODataResource {TypeName = ActualEntityType.FullName()};
this.typeContext = new TestFeedAndEntryTypeContext();
this.entryMetadataContextWithoutModel = ODataResourceMetadataContext.Create(this.entry, this.typeContext, new ODataResourceSerializationInfo(), /*actualEntityType*/null, new TestMetadataContext(), SelectedPropertiesNode.EntireSubtree);
this.entryMetadataContextWithModel = ODataResourceMetadataContext.Create(this.entry, this.typeContext, /*serializationInfo*/null, ActualEntityType, new TestMetadataContext(), SelectedPropertiesNode.EntireSubtree);
this.entryMetadataContextWithoutModel = ODataResourceMetadataContext.Create(this.entry, this.typeContext, new ODataResourceSerializationInfo(), /*actualEntityType*/null, new TestMetadataContext(), new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree));
this.entryMetadataContextWithModel = ODataResourceMetadataContext.Create(this.entry, this.typeContext, /*serializationInfo*/null, ActualEntityType, new TestMetadataContext(), new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree));
}

[Fact]
public void CreateShouldReturnMetadataContextWithoutModel()
{
var entryMetadataContext = ODataResourceMetadataContext.Create(this.entry, this.typeContext, new ODataResourceSerializationInfo(), ActualEntityType, new TestMetadataContext(), SelectedPropertiesNode.EntireSubtree);
var entryMetadataContext = ODataResourceMetadataContext.Create(this.entry, this.typeContext, new ODataResourceSerializationInfo(), ActualEntityType, new TestMetadataContext(), new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree));
entryMetadataContext.GetType().FullName.EndsWith("WithoutModel").Should().BeTrue();
}

[Fact]
public void CreateShouldReturnMetadataContextWithModel()
{
var entryMetadataContext = ODataResourceMetadataContext.Create(this.entry, this.typeContext, /*serializationInfo*/null, ActualEntityType, new TestMetadataContext(), SelectedPropertiesNode.EntireSubtree);
var entryMetadataContext = ODataResourceMetadataContext.Create(this.entry, this.typeContext, /*serializationInfo*/null, ActualEntityType, new TestMetadataContext(), new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree));
entryMetadataContext.GetType().FullName.EndsWith("WithModel").Should().BeTrue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void GetEntityMetadataBuilderShouldThrowWhenMetadataDocumentUriIsNull()
null /*requestUri*/);
IEdmEntitySet set = this.edmModel.EntityContainer.FindEntitySet("Products");
ODataResource entry = TestUtils.CreateODataEntry(set, new EdmStructuredValue(new EdmEntityTypeReference(set.EntityType(), true), new IEdmPropertyValue[0]), set.EntityType());
Action action = () => context.GetResourceMetadataBuilderForReader(new TestJsonLightReaderEntryState { Resource = entry, SelectedProperties = SelectedPropertiesNode.EntireSubtree, NavigationSource = set }, false);
Action action = () => context.GetResourceMetadataBuilderForReader(new TestJsonLightReaderEntryState { Resource = entry, SelectedProperties = new SelectedPropertiesNode(SelectedPropertiesNode.SelectionType.EntireSubtree), NavigationSource = set }, false);
action.ShouldThrow<ODataException>().WithMessage(Strings.ODataJsonLightResourceMetadataContext_MetadataAnnotationMustBeInPayload("odata.context"));
}

Expand All @@ -51,7 +51,7 @@ public void GetEntityMetadataBuilderShouldNotThrowWhenMetadataDocumentUriIsNonNu
null /*requestUri*/);
IEdmEntitySet set = this.edmModel.EntityContainer.FindEntitySet("Products");
ODataResource entry = TestUtils.CreateODataEntry(set, new EdmStructuredValue(new EdmEntityTypeReference(set.EntityType(), true), new IEdmPropertyValue[0]), set.EntityType());
Action action = () => context.GetResourceMetadataBuilderForReader(new TestJsonLightReaderEntryState { Resource = entry, SelectedProperties = new SelectedPropertiesNode("*"), NavigationSource = set }, false);
Action action = () => context.GetResourceMetadataBuilderForReader(new TestJsonLightReaderEntryState { Resource = entry, SelectedProperties = new SelectedPropertiesNode("*", null, null), NavigationSource = set }, false);
action.ShouldNotThrow();
}

Expand Down
Loading