Использование параметров запроса для привязки модели. Фильтрация результатов (передача массивов)

Фильтрация данных, наряду с постраничным выводом результатов, позволяет ускорить работу приложения. Однако, прежде чем мы перейдем к реализации фильтрации в нашем приложении, стоит рассмотреть вопрос: чем отличается фильтрация от поиска?

Чем отличается фильтрация от поиска?

Обычно, под поиском подразумевается выбор всех данных, подходящих под заданный критерий. Визуально поиск в приложении реализуется в виде обычного поля ввода. Например, если пользователь вводит в строку поиска слово «проект», то приложение должно выбрать из всего массива проектов только те, название которых содержит искомое слово.

В свою очередь, фильтрация – это более гибкий механизм выбора данных. При фильтрации мы можем задействовать все свойства объекта. Например, фильтровать список проектов по дате создания, текущему статусу и так далее. Кроме этого, мы можем создавать сложные фильтры, позволяя пользователю фильтровать данные по нескольким полям сразу. Фильтры также можно использовать в процессе поиска, например, позволив пользователю указать, где именно искать введенную им строку – в начале названия, в конце, в любом месте, учитывать или не учитывать регистр символов и так далее. Попробуем реализовать фильтрацию данных в приложении, которое мы разработали в предыдущей части.

Подготовка шаблонного проекта 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.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии