Skip to content
Merged
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
1 change: 1 addition & 0 deletions AutoMapper.AspNetCore.OData.EFCore/ProjectionSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ namespace AutoMapper.AspNet.OData
public class ProjectionSettings
{
public object Parameters { get; set; }
public bool ApplyFilterAfterProjection { get; set; }
}
}
15 changes: 10 additions & 5 deletions AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,24 @@ private static IQueryable<TModel> GetQuery<TModel, TData>(this IQueryable<TData>
IEnumerable<Expression<Func<TModel, object>>> includeProperties = null,
ProjectionSettings projectionSettings = null)
{
Expression<Func<TData, bool>> f = mapper.MapExpression<Expression<Func<TData, bool>>>(filter);
Func<IQueryable<TData>, IQueryable<TData>> mappedQueryFunc = mapper.MapExpression<Expression<Func<IQueryable<TData>, IQueryable<TData>>>>(queryFunc)?.Compile();

if (filter != null)
query = query.Where(f);
if (filter != null && !FilterAfterProjection())
query = query.Where(mapper.MapExpression<Expression<Func<TData, bool>>>(filter));

return mappedQueryFunc != null
var projectedQuery = mappedQueryFunc != null
? mapper.ProjectTo(mappedQueryFunc(query), projectionSettings?.Parameters, GetIncludes())
: mapper.ProjectTo(query, projectionSettings?.Parameters, GetIncludes());

if (filter != null && FilterAfterProjection())
projectedQuery = projectedQuery.Where(filter);

return projectedQuery;

bool FilterAfterProjection() => projectionSettings?.ApplyFilterAfterProjection ?? false;
Expression<Func<TModel, object>>[] GetIncludes() => includeProperties?.ToArray() ?? new Expression<Func<TModel, object>>[] { };
}

private static void ApplyOptions<TModel, TData>(this IQueryable<TData> query, IMapper mapper, Expression<Func<TModel, bool>> filter, ODataQueryOptions<TModel> options, QuerySettings querySettings)
{
ApplyOptions(options, querySettings);
Expand Down
78 changes: 78 additions & 0 deletions AutoMapper.OData.EFCore.Tests/GetQueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,85 @@ void Test(ICollection<OpsTenant> collection)
Assert.Equal("Two", collection.First().Name);
}
}
[Fact]
public async Task FilterByDynamicParameterValueAfterProjectionReturnExpectedResults()
{
// Arrange
string buildingParameterValue = Guid.NewGuid().ToString();

var parameters = new { buildingParameter = buildingParameterValue };

var projectionSettings = new ProjectionSettings
{
Parameters = parameters,
//if false test will fail
ApplyFilterAfterProjection = true
};

var odataSettings = new ODataSettings
{
HandleNullPropagation = HandleNullPropagationOption.False
};

string query = $"/corebuilding?$filter=Parameter eq '{buildingParameterValue}'";

// Act
var result = await GetAsync<CoreBuilding, TBuilding>(
query,
null,
new QuerySettings
{
ProjectionSettings = projectionSettings,
ODataSettings = odataSettings
});

// Assert
if (result.Count == 0)
{
throw new Xunit.Sdk.XunitException(
"Expected at least one CoreBuilding with matching Parameter value, " +
"but none were returned. This replicates the case where a runtime parameter " +
"(like CurrentUserId) was not propagated during OData filter translation."
);
}

Assert.All(result, b => Assert.Equal(buildingParameterValue, b.Parameter));
}

[Fact]
public async Task FilterByDynamicParameterValueBeforeProjectionReturnZeroResults()
{
// Arrange
string buildingParameterValue = Guid.NewGuid().ToString();

var parameters = new { buildingParameter = buildingParameterValue };

var projectionSettings = new ProjectionSettings
{
Parameters = parameters,
ApplyFilterAfterProjection = false
};

var odataSettings = new ODataSettings
{
HandleNullPropagation = HandleNullPropagationOption.False
};

string query = $"/corebuilding?$filter=Parameter eq '{buildingParameterValue}'";

// Act
var result = await GetAsync<CoreBuilding, TBuilding>(
query,
null,
new QuerySettings
{
ProjectionSettings = projectionSettings,
ODataSettings = odataSettings
});

// Assert
Assert.Empty(result);
}
[Fact]
public async Task BuildingExpandBuilderTenantFilterEqAndOrderByWithParameter()
{
Expand Down