Reputation: 3677
I need to modify the $filter
on the server-side of .NET core 2.1 API. I have looked at these:
https://entityframework.net/knowledge-base/33660648/odata-v4-modify--filter-on-server-side
OData V4 modify $filter on server side
The best way to modify a WebAPI OData QueryOptions.Filter
(and a couple of others)
They all do something along the lines of:
//Get the URL
var url = queryOptions.Request.RequestUri.AbsoluteUri;
//Then modify the URL
url = url.Replace("$filter=ID%20eq%201", "$filter=ID%20eq%202");
//Apply the URL
return queryOptions.ApplyTo(queryable);
The problem being is that it appears in .NET core there is no RequestUri
. I am able to get the query multiple different ways:
var query = originalRequest.QueryString.Value;
//or a foreach loop
var filter = Request.Query;
foreach (var x in filter)
//...
However both QueryString.Value
Request.Query
gives me an error "Value has no setters"
Also the method ApplyTo
is not in .NET Core.
What is the correct way of doing this in .NET Core? Is there some package that I am missing?
Upvotes: 1
Views: 1923
Reputation: 4655
@Xaphann You could extend EnableQueryAttribute
in the manner below:
public class ExtendedEnableQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
{
// ... second check in the if statement might be overkill - abundance of caution?
if (queryOptions.Filter != null && queryOptions.Request.Query.ContainsKey("$filter"))
{
var stringValuesDict = new Dictionary<string, StringValues>();
foreach(var kvPair in queryOptions.Request.Query.Where(d => !d.Key.Equals("$filter")))
{
// This way the new StringValues instances are owned exclusively by substitute query collection
var values = new List<string>();
foreach(var value in kvPair.Value)
{
values.Add(value);
}
stringValuesDict.Add(kvPair.Key, new StringValues(values.ToArray()));
}
// Substitute the $filter option
stringValuesDict.Add("$filter", new StringValues("ID eq 202"));
// Substitute the request query collection
queryOptions.Request.Query = new QueryCollection(stringValuesDict);
queryOptions = new ODataQueryOptions(queryOptions.Context, queryOptions.Request);
}
return base.ApplyQuery(queryable, queryOptions);
}
}
You can then proceed to apply this extended attribute to your controller action. I tested it practically and it seemed to work for an expression like this:
?$filter=ID eq 201&$orderby=Name&$select=Name
If this approach works for you, my advise would be to test more extensively and maybe also write a few tests to validate the behaviour
Upvotes: 4