Skip to content

Filtering

Shady Ashraf Abdelhameed edited this page Jan 31, 2025 · 1 revision

Filtering in TRWalks ASP.NET Core Web API

Filtering is an essential feature in the TRWalks project, enabling users to retrieve a subset of walks based on specific criteria. Below is an implementation guide tailored to the TRWalks application.

Example Scenario

Consider the following dataset of walks:

  • Tomsk Historical Walk
  • Siberian Forest Trail
  • New River Adventure
  • Ancient Tomsk Trek
  • South Siberia Expedition
  • South Mountain Climb

If a user queries for walks containing the keyword south, the filtered results would include:

  • South Siberia Expedition
  • South Mountain Climb

In addition to filtering by name, users can apply filters to other attributes such as difficulty, region, or description.


Step-by-Step Implementation

1. Adding Query Parameters in the Controller

In the TRWalks API, the filtering logic starts in the controller. Add query strings to the GetAllWalks method in the WalksController.

Query Parameters:

  • filterOn: Specifies the column to filter on (e.g., name).
  • filterQuery: The keyword to filter by.
[HttpGet]
public async Task<IActionResult> GetAllWalks(
    [FromQuery] string? filterOn = null,
    [FromQuery] string? filterQuery = null)
{
    var results = await _walkRepository.GetAllAsync(filterOn, filterQuery);
    return Ok(results);
}

The query string in the URL might look like this:

GET /api/walks?filterOn=name&filterQuery=south

2. Modifying the Repository Interface

Update the repository interface to include filtering parameters:

Task<IEnumerable<Walk>> GetAllAsync(string? filterOn = null, string? filterQuery = null);

3. Updating the Repository Implementation

Modify the GetAllAsync method in the repository to include filtering logic:

Convert to Queryable

Retrieve walks as a queryable object to support dynamic filtering:

public async Task<IEnumerable<Walk>> GetAllAsync(string? filterOn, string? filterQuery)
{
    var walks = _dbContext.Walks
        .Include(w => w.Difficulty)
        .Include(w => w.Region)
        .AsQueryable();

    if (!string.IsNullOrWhiteSpace(filterOn) && !string.IsNullOrWhiteSpace(filterQuery))
    {
        walks = filterOn.ToLower() switch
        {
            "name" => walks.Where(w => w.Name.Contains(filterQuery, StringComparison.OrdinalIgnoreCase)),
            "description" => walks.Where(w => w.Description.Contains(filterQuery, StringComparison.OrdinalIgnoreCase)),
            "region" => walks.Where(w => w.Region.Name.Contains(filterQuery, StringComparison.OrdinalIgnoreCase)),
            _ => walks
        };
    }

    return await walks.ToListAsync();
}

4. Testing with Swagger or Postman

After implementation, test the API using tools like Swagger or Postman by making requests with appropriate query strings:

Example Request

GET /api/walks?filterOn=name&filterQuery=tomsk

Expected Response

[
    {
        "id": 1,
        "name": "Tomsk Historical Walk",
        "description": "Explore the rich history of Tomsk.",
        "length": 3.5,
        "difficulty": "Easy",
        "region": "Urban"
    }
]

Key Notes

  1. Default Behavior: If filterOn or filterQuery is null, the API returns all walks.
  2. Case-Insensitive Search: Use StringComparison.OrdinalIgnoreCase for case-insensitive filtering.
  3. Scalability: This implementation is adaptable for additional features such as sorting and pagination.

By integrating filtering into the repository, the TRWalks API ensures efficient and scalable data retrieval, tailored to meet diverse user needs.

Clone this wiki locally