liveBook · Manning

Filtering

As explained in Building Web APIs with ASP.NET Core

Filtering behavior is the rule that determines which data items are included in a returned result based on a condition applied to their values.

Filtering determines which records appear in a returned result by applying a condition to their values. In a board-game API, it prevents clients from receiving an unwieldy list when they need only matching games. section 5.4 section 5.4.3

Implement database-driven filtering in the GET endpoint as follows:

  • Accept a nullable filterQuery parameter from the client. section 5.4.3
  • Start with an IQueryable query and conditionally add Where when filterQuery is not null or empty. section 5.4.3
  • Count the filtered query before applying sorting, Skip, and Take so pagination reflects the filter. section 5.4.3

Testing name filters

Requesting /BoardGames?filterQuery=diplomacy returns five matching games within the sorted result, while /BoardGames?filterQuery=war retrieves the first matching page. section 5.4.3

Listing 5.8 BoardGameController.Get() method (with paging, sorting, and filtering)
[HttpGet(Name = "GetBoardGames")]
[ResponseCache(Location = ResponseCacheLocation.Any, Duration = 60)]
public async Task<RestDTO<BoardGame[]>> Get(
    int pageIndex = 0,
    int pageSize = 10,
    string? sortColumn = "Name",
    string? sortOrder = "ASC",
string? filterQuery = null)                                 #1
{
    var query = _context.BoardGames.AsQueryable();              #2
if (!string.IsNullOrEmpty(filterQuery))                  #3
query = query.Where(b => b.Name.Contains(filterQuery));
var recordCount = await query.CountAsync();             #4
    query = query
            .OrderBy($"{sortColumn} {sortOrder}")
            .Skip(pageIndex * pageSize)
            .Take(pageSize);
    return new RestDTO<BoardGame[]>()
    {
        Data = await query.ToArrayAsync(),
        PageIndex = pageIndex,
        PageSize = pageSize,
        RecordCount = recordCount,
        Links = new List<LinkDTO> {
            new LinkDTO(
                Url.Action(
                    null,
                    "BoardGames",
                    new { pageIndex, pageSize },
                    Request.Scheme)!,
                "self",
                "GET"),
        }
    };
}

Inspect the complete GET method to see filterQuery, conditional Where, record counting, sorting, and paging composed together. section 5.4.3

How Building Web APIs with ASP.NET Core covers it

How deep it goes
Defines conditional database filtering, explains query composition and count timing, and stops at matching the Name field with Contains.
Examples
Uses filterQuery=diplomacy and filterQuery=war requests to verify matching board-game results.
What it assumes
Assumes basic DML knowledge, while requiring no specific SQL knowledge because LINQ handles the database tasks.
What you can do after
Apply it via EF Core by adding filterQuery, conditionally chaining Where, and testing matching results.
How it connects
Connects filtering with paging, sorting, EF Core, LINQ, IQueryable, and database-backed GET requests.

Also explained in

Compare how 33 books explain filtering →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Building Web APIs with ASP.NET Core. The section links point to the parts of the book it draws on.