Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -351,86 +351,14 @@ private static string GetRootElementName(ODataPath path)
return null;
}

// This function is used to determine whether an OData path includes operation (import) path segments.
// We use this function to make sure the value of ODataUri.Path in ODataMessageWriterSettings is null
// when any path segment is an operation. ODL will try to calculate the context URL if the ODataUri.Path
// equals to null.
private static bool IsOperationPath(ODataPath path)
{
if (path == null)
{
return false;
}

foreach (ODataPathSegment segment in path.Segments)
{
if (segment is OperationSegment ||
segment is OperationImportSegment)
{
return true;
}
}

return false;
}

private static Microsoft.OData.UriParser.ODataPath ConvertPath(ODataPath path)
{
if (path == null)
{
return null;
}

if (IsOperationPath(path))
{
var lastSegment = path.Segments.Last();
OperationSegment operation = lastSegment as OperationSegment;
if (operation != null && operation.EntitySet != null)
{
return GeneratePath(operation.EntitySet);
}

OperationImportSegment operationImport = lastSegment as OperationImportSegment;
if (operationImport != null && operationImport.EntitySet != null)
{
return GeneratePath(operationImport.EntitySet);
}

return null;
}

return path.Path;
}

private static Microsoft.OData.UriParser.ODataPath GeneratePath(IEdmNavigationSource navigationSource)
{
Contract.Assert(navigationSource != null);

switch (navigationSource.NavigationSourceKind())
{
case EdmNavigationSourceKind.EntitySet:
return new Microsoft.OData.UriParser.ODataPath(new EntitySetSegment((IEdmEntitySet)navigationSource));

case EdmNavigationSourceKind.Singleton:
return new Microsoft.OData.UriParser.ODataPath(new SingletonSegment((IEdmSingleton)navigationSource));

case EdmNavigationSourceKind.ContainedEntitySet:
IEdmContainedEntitySet containedEntitySet = (IEdmContainedEntitySet)navigationSource;
Microsoft.OData.UriParser.ODataPath path = GeneratePath(containedEntitySet.ParentNavigationSource);
IList<ODataPathSegment> segments = new List<ODataPathSegment>();
foreach (var item in path)
{
segments.Add(item);
}

segments.Add(new NavigationPropertySegment(containedEntitySet.NavigationProperty, containedEntitySet.ParentNavigationSource));
return new Microsoft.OData.UriParser.ODataPath(segments);

case EdmNavigationSourceKind.None:
case EdmNavigationSourceKind.UnknownEntitySet:
default:
return null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,56 @@ public async Task ActionImportFollowedByQueryOption()
Assert.DoesNotContain("Street 11", responseString);
}

[Fact]
public async Task FunctionImportWithExpand()
{
// Arrange
const int CustomerId = 407;
ConventionCustomer expectCustomer = new ConventionCustomersController().GetConventionCustomerById(CustomerId);
Assert.NotNull(expectCustomer);
Assert.NotNull(expectCustomer.Orders);
Assert.NotEmpty(expectCustomer.Orders);

// Act - Expand Orders navigation property from function import result
var requestUri = this.BaseAddress + "/odata/GetConventionCustomerByIdImport(CustomerId=" + CustomerId + ")?$expand=Orders";
var response = await Client.GetAsync(requestUri);
var responseString = await response.Content.ReadAsStringAsync();

// Assert
Assert.True(response.IsSuccessStatusCode, $"Request failed with status {response.StatusCode}. Response: {responseString}");
Assert.Contains("/$metadata#ConventionCustomers/$entity", responseString);

// Verify customer data is present
string expect = "\"ID\":" + expectCustomer.ID;
Assert.Contains(expect, responseString);
expect = "\"Name\":\"" + expectCustomer.Name + "\"";
Assert.Contains(expect, responseString);

// Verify expanded Orders are present
Assert.Contains("\"Orders\":", responseString);
foreach (var order in expectCustomer.Orders)
{
Assert.Contains("\"OrderName\":\"" + order.OrderName + "\"", responseString);
}
}

[Fact]
public async Task FunctionImportReturningCollectionWithExpand()
{
// Act - Expand Orders navigation property from function import returning collection
var requestUri = this.BaseAddress + "/odata/GetAllConventionCustomersImport()?$expand=Orders";
var response = await Client.GetAsync(requestUri);
var responseString = await response.Content.ReadAsStringAsync();

// Assert
Assert.True(response.IsSuccessStatusCode, $"Request failed with status {response.StatusCode}. Response: {responseString}");
Assert.Contains("/$metadata#ConventionCustomers", responseString);

// Verify that orders are expanded for at least one customer
Assert.Contains("\"Orders\":", responseString);
Assert.Contains("\"OrderName\":", responseString);
}

#endregion
}
}