Skip to content

GridifyQuery ​

GridifyQuery is a simple class for configuring Filtering, Ordering and Paging.

csharp
var gq = new GridifyQuery()
{
    Filter = "FirstName=John",
    Page = 1,
    PageSize = 20,
    OrderBy = "Age"
};

// Apply Filter, Sort and Paging
Paging<Person> result = personsRepo.Gridify(gq);

Here’s an updated version of the IsValid section you can drop into the docs.

IsValid ​

This extension method checks if a GridifyQuery (Filter, OrderBy) is valid for use with a custom mapper or the auto-generated mapper. It returns true if valid, false otherwise.

The validation checks:

  • Field names (mapped or actual properties)
  • Filter syntax
  • Value type compatibility (integers, DateTime, enums, bool, Guid, etc.)

Basic usage ​

csharp
var gq = new GridifyQuery { Filter = "name=John", OrderBy = "Age" };
// true
bool isValid = gq.IsValid<Person>();
csharp
var gq = new GridifyQuery { Filter = "NonExist=John", OrderBy = "Age" };
// false (NonExist is not a property of Person)
bool isValid = gq.IsValid<Person>();
csharp
var gq = new GridifyQuery { Filter = "@name=!", OrderBy = "Age" };
// false (invalid filter syntax)
bool isValid = gq.IsValid<Person>();
csharp
var gq = new GridifyQuery { Filter = "Age=abc" };
// false (Age is an int, "abc" cannot be converted)
bool isValid = gq.IsValid<Person>();

Using a custom mapper ​

Optionally you can pass a custom mapper to check if the GridifyQuery is valid for that mapper:

csharp
var mapper = new GridifyMapper<Person>()
    .AddMap("name", q => q.Name);

var gq = new GridifyQuery { Filter = "name=John", OrderBy = "Age" };

// false (Age is not mapped on this mapper)
bool isValid = gq.IsValid(mapper);

Maps with a custom convertor ​

When a map has a convertor, IsValid runs it before checking the value type, the same way the query builder does. Validating the raw text instead would reject values that only the convertor understands:

csharp
var mapper = new GridifyMapper<Person>()
    .AddMap("createdOn", q => q.CreatedOn, value => ParseRelativeDate(value)); // understands "d-2"

var gq = new GridifyQuery { Filter = "createdOn>d-2" };

// true, because the convertor turns "d-2" into a DateTime
bool isValid = gq.IsValid(mapper);

The convertor's result is then judged the way the query builder uses it:

convertor resultvalidation
throwsinvalid, the message includes the convertor's own error
a stringchecked against the mapped property type, as usual
any other typemust be usable as the mapped property type
nullvalid when the mapped property can hold null

Two things to keep in mind:

  • IsValid invokes the convertor. If yours is expensive or has side effects, it now runs during validation as well as during filtering.
  • "Usable as the mapped property type" is decided by asking the query builder's own value machinery, so it follows whichever path is in effect. Plain LINQ needs the exact type; with the Entity Framework compatibility layer the value is assigned through reflection, which widens some types (int into a long property, for instance) and accepts null for a non-nullable property by storing its default.

Getting validation error messages ​

If you need detailed feedback (for example, to return validation errors to a client), use the overload with out List<string> validationErrors:

csharp
var gq = new GridifyQuery { Filter = "Age=abc" };

var isValid = gq.IsValid<Person>(out var errors);

// isValid == false
// errors might contain something like:
// ["Cannot convert value 'abc' to type 'Int32' for field 'Age': Invalid format"]

You can combine this with a custom mapper as well:

csharp
var mapper = new GridifyMapper<Person>()
    .AddMap("name", q => q.Name);

var gq = new GridifyQuery { Filter = "name=John; Age=abc" };

var isValid = gq.IsValid(out var errors, mapper);

// isValid == false
// errors could include:
// - "Field 'Age' is not mapped" (if Age isn't mapped)
//   or, if it is mapped but the value is wrong:
// - "Cannot convert value 'abc' to type 'Int32' for field 'Age': Invalid format"

OrderBy is validated too, and its errors come back in the same list:

csharp
var mapper = new GridifyMapper<Person>()
    .AddMap("Name", q => q.Name)
    .AddMap("Age", q => q.Age);

var gq = new GridifyQuery(1, 100, "Name=Ivan", "ageee");

var isValid = gq.IsValid(out var errors, mapper);

// isValid == false
// errors == ["Field 'ageee' is not mapped"]

There are overloads for each part on its own, should you only have one of them:

csharp
// filtering only
((IGridifyFiltering)gq).IsValid(out var filterErrors, mapper);

// ordering only
((IGridifyOrdering)gq).IsValid(out var orderErrors, mapper);

The validation also catches a few things that only fail once the query is built:

csharp
// '?' and '!' order by the member's null state, so the member has to be nullable
new GridifyQuery { OrderBy = "Age?" }.IsValid<Person>(out var errors);
// false, ["Field 'Age' is not a nullable type, so it cannot be ordered by its null state"]

Notes:

  • Empty or null Filter and OrderBy values are considered valid and return true.
  • The “old” overloads (IsValid<T>() and IsValid(mapper)) remain and now also benefit from the improved value-type validation; they just don’t expose the error details.
  • Whether the null keyword is accepted follows the mapper's AllowNullSearch, which is what the query builder uses, rather than the global configuration.
  • Calling the error collecting overload on a GridifyQuery, or on anything typed as IGridifyQuery, validates both Filter and OrderBy and reports every error from both, rather than stopping at the first part that fails.

GetFilteringExpression ​

This extension method, creates a lambda expression using the GridifyQuery.Filter property that you can use it in the LINQ Where method to filter the data.

csharp
var gq = new GridifyQuery() { Filter = "name=John" };
Expression<Func<T, bool>> expression = gq.GetFilteringExpression<Person>();
var result = personsRepo.Where(expression);