Содержание
Фильтрация данных, наряду с постраничным выводом результатов, позволяет ускорить работу приложения. Однако, прежде чем мы перейдем к реализации фильтрации в нашем приложении, стоит рассмотреть вопрос: чем отличается фильтрация от поиска?
Чем отличается фильтрация от поиска?
Обычно, под поиском подразумевается выбор всех данных, подходящих под заданный критерий. Визуально поиск в приложении реализуется в виде обычного поля ввода. Например, если пользователь вводит в строку поиска слово «проект», то приложение должно выбрать из всего массива проектов только те, название которых содержит искомое слово.
В свою очередь, фильтрация – это более гибкий механизм выбора данных. При фильтрации мы можем задействовать все свойства объекта. Например, фильтровать список проектов по дате создания, текущему статусу и так далее. Кроме этого, мы можем создавать сложные фильтры, позволяя пользователю фильтровать данные по нескольким полям сразу. Фильтры также можно использовать в процессе поиска, например, позволив пользователю указать, где именно искать введенную им строку – в начале названия, в конце, в любом месте, учитывать или не учитывать регистр символов и так далее. Попробуем реализовать фильтрацию данных в приложении, которое мы разработали в предыдущей части.
Подготовка шаблонного проекта ASP.NET Core Web API
Снова немного изменим класс WeatherForecast:
public enum ForecastSummary {Freezing, Bracing, Chilly, Cool, Mild, Warm, Balmy, Hot, Sweltering, Scorching }; public class WeatherForecast { public int Id { get; set; } public DateOnly Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public ForecastSummary Summary { get; set; } }
Здесь мы заменили тип свойства Summary
на перечисление ForecastSummary
, чтобы в дальнейшем нам было удобнее использовать фильтрацию результатов. Соответственно, необходимо немного изменить и метод Get() контроллера:
[HttpGet] public ActionResult<PagedList<WeatherForecast>> Get([FromQuery] ForecastParameters parameters) { var data = Enumerable.Range(1, 500).Select(index => new WeatherForecast { Id = index, Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), TemperatureC = Random.Shared.Next(-20, 55), Summary = (ForecastSummary)Random.Shared.Next(0, 10) }); var result = PagedList<WeatherForecast>.ToPagedList(data, parameters.PageNumber, parameters.PageSize); if (result.Data.Count > 0) { return result; } else return NoContent(); }
Протестируем работу приложения, выполнив запрос из http-файла на получение страницы с результатами. Вот как теперь будет выглядеть ответ сервера:
Чтобы снова видеть в поле summary строку (имя элемента перечисления), изменим немного файл Program.cs:
builder.Services.AddControllers() //эта строка уже есть в проекте .AddJsonOptions(opt => //настраиваем параметры сериализации в JSON { opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); });
Теперь ответ сервера будет более информативный:
Теперь можно приступать к реализации функций фильтрации данных.
Фильтрация результатов (передача массивов)
Разрешим пользователю фильтровать результаты по свойству Summary
, причем дадим пользователю возможность указывать в фильтре несколько вариантов значения этого свойства. Например, пользователь сможет задать запрос следующего содержания: получить все объекты, у которых свойство Summary равно Freezing или Chilly. Для этого нам потребуется, во-первых, внести следующее изменение в класс ForecastParameters, который мы создали в прошлой части:
public class ForecastParameters: RequestParameters { public ForecastSummary[]? Summaries { get; set; } }
Так как фильтр может и не использоваться, то свойство Summaries
объявлено, как допускающее null
.
А, во-вторых, научиться передавать в строке параметров запроса массивы значений. Но, вначале, применим новое свойство в методе Get() контроллера. Здесь нам снова придёт на помощь LINQ:
[HttpGet] public ActionResult<PagedList<WeatherForecast>> Get([FromQuery] ForecastParameters parameters) { var data = Enumerable.Range(1, 500).Select(index => new WeatherForecast { Id = index, Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), TemperatureC = Random.Shared.Next(-20, 55), Summary = (ForecastSummary)Random.Shared.Next(0, 10) }); //выбираем только те объекты, значение свойства Summary которых содержится в фильтре if (parameters.Summaries != null) { data = data.Where(d => parameters.Summaries.Contains(d.Summary)); } var result = PagedList<WeatherForecast>.ToPagedList(data, parameters.PageNumber, parameters.PageSize); if (result.Data.Count > 0) { return result; } else return NoContent(); }
Здесь, прежде, чем выдать очередную страницу результатов, мы проводим фильтрацию данных:
//выбираем только те объекты, значение свойства Summary которых содержится в фильтре if (parameters.Summaries != null) { data = data.Where(d => parameters.Summaries.Contains(d.Summary)); }
Теперь попробуем передать в параметрах запроса массив. Для этого изменим запрос в http-файле проекта следующим образом:
GET {{WebApplication5_HostAddress}}/weatherforecast?pageSize=5&pageNumber=5&Summaries=Freezing&Summaries=Chilly Accept: application/json
Теперь сервер должен будет вернуть пяту страницу результатов, состоящую из пяти элементов у которых свойство Summary
равно Freezing
или Chilly
. Запустим приложение и выполним запрос:
Итого
В этой части мы на практике использовали передачу массивов через параметры запроса. Аналогичным образом вы можете самостоятельно потренироваться передавать через запросы другие типы данных. Мы же перейдем к следующей части, касающейся работы с моделями в приложениях ASP.NET Core Web API.