Programming

Conditionally Add Filters Only When a Value Is Supplied

If you are converting a series of optional filters in a UI into an IQueryable, you’ll find yourself writing a lot of if-statements to only add a filter if a value is supplied.

if (myNumber!= 0)
{
    query = query.Where(t => t.Number.Equals(myNumber));
}

if (myName!= 0)
{
    query = query.Where(t => t.Name.Equals(myName));
}

I have been using the following extension methods to clean up this act, it conditionally adds the filter only if a value has been supplied (note: in my case 0 always means nothing was selected…).

/// <summary>
/// Conditionally adds a Where expression IF the property has a non-zero value
/// </summary>
/// <param name="query">An existing IQueryable<Vehicle> query.</param>
/// <param name="property">The property to be checked.</param>
/// <param name="predicate">The predicate to be used within the .Where() method.</param>
/// <returns></returns>
public static IQueryable<T> AddFilterIfValue<T>(this IQueryable<T> query, int property, Expression<Func<T, bool>> predicate)
{
    if (property > 0)
    {
        return query.Where(predicate);
    }

    return query;
}

/// <summary>
/// Conditionally adds a Where expression IF the property has a non-empty value
/// </summary>
/// <param name="query">An existing IQueryable<Vehicle> query.</param>
/// <param name="property">The property to be checked.</param>
/// <param name="predicate">The predicate to be used within the .Where() method.</param>
/// <returns></returns>
public static IQueryable<T> AddFilterIfValue<T>(this IQueryable<T> query, string property, Expression<Func<T, bool>> predicate)
{
    if (!string.IsNullOrWhiteSpace(property))
    {
        return query.Where(predicate);
    }

    return query;
}

You call it like this…

query = query.AddFilterIfValue(myNumber, t => t.Number.Equals(myNumber));

And it can be chained, so you can do it like this…

query = query
    .AddFilterIfValue(myNumber, t => t.Number.Equals(myNumber))
    .AddFilterIfValue(myName, t => t.Name.Equals(myName));

Additional note: don’t forget to use the returned value, i.e. this won’t work because you forgot to assign the returned query to a variable…

query
    .AddFilterIfValue(myNumber, t => t.Number.Equals(myNumber))
    .AddFilterIfValue(myName, t => t.Name.Equals(myName));