. NET Core 2.1 OData v4 изменить фильтр $ на стороне сервера - PullRequest
0 голосов
/ 14 апреля 2020

Мне нужно изменить $filter на стороне сервера. NET core 2.1 API. Я посмотрел на них:

https://entityframework.net/knowledge-base/33660648/odata-v4-modify--filter-on-server-side

OData V4 изменить $ фильтр на стороне сервера

Лучший способ изменить WebAPI OData QueryOptions.Filter

(и несколько других)

Все они делают что-то вроде:

//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);

Проблема в том, что он появляется в. NET ядре нет RequestUri. Я могу получить запрос несколькими различными способами:

var query = originalRequest.QueryString.Value;
//or a foreach loop
var filter = Request.Query;
foreach (var x in filter)
//...

Однако оба QueryString.Value Request.Query выдают мне ошибку «Значение не имеет установщиков»

Также метод ApplyTo не входит. NET Core.

Как правильно сделать это в. NET Core? Есть какой-то пакет, который мне не хватает?

1 Ответ

1 голос
/ 15 апреля 2020

@ Xaphann Вы можете расширить EnableQueryAttribute следующим образом:

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);
    }
}

Затем вы можете приступить к применению этого расширенного атрибута к действию вашего контроллера. Я проверил его практически, и, похоже, он работал для такого выражения:

?$filter=ID eq 201&$orderby=Name&$select=Name

Если этот подход работает для вас, я бы посоветовал провести более подробное тестирование и, возможно, также написать несколько тестов для проверки поведения

...