Search code examples
c#.netdesign-patternsarchitecture

Display list on a screen with three options


I am working with a database containing people, each having an isRetired parameter.

By default, I retrieve non-retired people, but I need to implement functionality on the screen to display people in three ways:

  • Active (non-retired people only),
  • Retired (retired people only), and
  • All (both retired and non-retired people).

How can I achieve this functionality in my application?

There is the problem, that i can retrieve data only by retired false or true. I thought by adding new parameter "ShowAll" and add if statement to service method(like is ShowAll=true then query without retired), but it seems confusing for me as when someone will debugging he could see like wow: ShowAll is true but Retired is false or true. What is going on and what data should be received? Does C# have any feature for this?

Here is my DTO I`m working with

public class PeopleDto
{
    public string Name { get; set; }
    public bool Retired { get; set; }
}

My Controller

[HttpGet]
public ActionResult<PaginatedResult<People>> GetAll([FromQuery] PeopleDto peopleDto) => Ok(_peopleService.GetAll(peopleDto));

Here is my Service method

public PaginatedResult<People> GetAll(PeopleDto peopleDto)
    {

        var peopleList = _dbContext.People
            .Where(people => String.IsNullOrEmpty(peopleDto.Name)
                                    || people.Name.Contains(peopleDto.Name))
            .IsRetired(peopleDto.Retired)
            .OrderBy(people => people.Id)
            .ToList();

        int totalItems = _dbContext.People
            .IsRetired(peopleDto.Retired)
            .Count(people => String.IsNullOrEmpty(peopleDto.Name)
                                    || people.Name.Contains(peopleDto.Name));
        
        var paginatedPeople = new PaginatedResult<People>
        {
            Items = peopleList,
            TotalCount = totalItems,
        };

        return paginatedPeople;
    }

public static class QueryableExtensions
{
    public static IQueryable<T> IsRetired<T>(this IQueryable<T> query, bool isRetired) where T : People =>
        query.Where(people => people.Retired == isRetired);
}

Solution

  • First, update your PeopleDto class to make Retired property nullable:

    public bool? Retired { get; set; }
    

    Then, create ApplyFilters method to handle the Retired property and handle other parameters, example like this:

    public static class QueryExtensions
    {
        public static IQueryable<T> ApplyFilters<T>(this IQueryable<T> query, BaseConfigurationFilterDto baseFilter) where T : DeviceConfiguration
        {
            if (!String.IsNullOrEmpty(baseFilter.Name))
            {
                query = query.Where(configuration => EF.Functions.ILike(configuration.Name, $"%{baseFilter.Name}%"));
            }
    
            if (baseFilter is ConfigurationFilterDto configurationFilter)
            {
                if (configurationFilter.Retired.HasValue)
                {
                    query = query.Where(configuration => configuration.Retired == configurationFilter.Retired.Value);
                }
            }
    
            return query;
        }
    }
    

    In your PeopleService class, update the GetAll method to use the ApplyFilters method:

    var query = _dbContext.People
            .Where(people => String.IsNullOrEmpty(peopleDto.Name) || people.Name.Contains(peopleDto.Name))
            .OrderBy(people => people.Id);
    
        query = query.ApplyFilters(peopleDto);
    
        var peopleList = query.ToList();