QueryX 1.0.0-beta-0006

This is a prerelease version of QueryX.
There is a newer version of this package available.
See the version list below for details.
dotnet add package QueryX --version 1.0.0-beta-0006                
NuGet\Install-Package QueryX -Version 1.0.0-beta-0006                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="QueryX" Version="1.0.0-beta-0006" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add QueryX --version 1.0.0-beta-0006                
#r "nuget: QueryX, 1.0.0-beta-0006"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install QueryX as a Cake Addin
#addin nuget:?package=QueryX&version=1.0.0-beta-0006&prerelease

// Install QueryX as a Cake Tool
#tool nuget:?package=QueryX&version=1.0.0-beta-0006&prerelease                

QueryX

QueryX allows performing filtering, paging and sorting to IQueryable ends using URL query strings.

Installation

Install with nuget:

Install-Package QueryX

Usage

Initially it is necessary to add QueryX to the registered services. In Program.cs:

builder.Services.AddQueryX();

A filter model is needed to define the properties that will be used for filtering, this model could be an specific filter class, a Dto or a Domain model object.

public class Card
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public int Priority { get; set; }
    public float EstimatedPoints { get; set; }
    public List<User> Owners { get; set; }
}

By default all properties can be used for filtering and sorting, this could be customized using attributes.

Two classes from QueryX are required for creating filters for the Card example object:

  • QueryBuilder, this class should be injected in controllers or where the queries needs to be created.
  • QuerModel, this class is used for capturing queries from URL query strings, it provides Filter, OrderBy, Offset and Limit properties for this purpose.

Additionally, an entity framework context is required for applying the queries:

[HttpGet]
public IActionResult List([FromQuery] QueryModel queryModel)
{
    var query = _queryBuilder.CreateQuery<Card>(queryModel);
    var result = _context.Set<Card>().ApplyQuery(query).ToList();
    return Ok(result);
}

Filtering

Filtering is made using operators, so a filter is defined this way: propertyName operator value.

It is possible to combine multiple filters using "and" (&) and "or" (|) connectors:

id>1 & title=-'test' | priority|=1,2

For facilitating writing queries in URL, ; (semicolon) character can be used instead for representing the and connector:

id>1 ; title=-'test' | priority|=1,2

Filter grouping

Filters can be also grouped using parentheses to determine how they should be evaluated:

id>1 ; (title=-'test' | priority|=1,2)

Collection filters

It is possible to specify filters for collection properties with the following syntax:

propertyName(childPropertyName operator value)

The above code will use the Enumerable.Any method for applying the conditions.

For using the Enumerable.All method:

propertyName*(childPropertyName operator value)

An example using the Card object would be:

owners(id==1 | name=='user2')

Supported value types

  • Number, integer, float, real, etc.
  • String, this values should be wrapped in single quotes. Datetime and enum values needs to be specified as strings.
  • Booleans, true and false keywords.
  • Null, according the property type, null could be a valid value.

Operators

Operator Description Comment
== Equals operator
==* Case insensitive equals String type only
!= Not equals
!=* Case insensitive not equals String type only
< Less than
Less than or equals
> Greater than
>= Greater than or equals
-=- Contains String type only
-=-* Case insensitive contains String type only
=- Starts with String type only
=-* Case insensitive starts with String type only
-= Ends with String type only
-=* Case insensitive ends with String type only
|= In Allows multiple values
|=* Case insensitive in String type only. Allows multiple values

Multiple values are specified this way: val1,val2,val3

Not Operator

The not operator (!) can be applied to any filter, collection filter or group:

!id>1 ; !title=-'test' | !priority|=1,2
id>1 ; !(title=-'test' | priority|=1,2)
!owners(id==1 | name=='user2')

Customize filter model

By default all properties from a filter model can be used for filtering and ordering, but there are some attributes that allows to have control on this

Properties marked wth the QueryIgnoreAttribute attribute will be ignored for filtering and ordering:

[QueryIgnore]
public float EstimatedPoints { get; set; }

Also, with QueryOptionsAttribute attribute some other options could be specified:

[QueryOptions(Operator = OperatorType.Equals, IsSortable = false, ParamsPropertyName = "EstimatedPts", ModelPropertyName = "Estimation")]
public float EstimatedPoints { get; set; }
  • Operator will set the default operator for this property, ignoring the one sent in the query string
  • IsSortable determines if this property is sortable or not, true by default
  • ParamsPropertyName is used for mapping filter names from query string. In this case, in query string will be a filter named EstimatedPts that will be mapped to the EstimatedPoints property
  • ModelPropertyName can be used when the filter model is different than the entity in DbContext and the filter model and the entity model have different property names, especifically, this allows mapping this property to a different one in the entity model. In this example, the value for this property will be used in the Estimation property in the entity model because the IQueryable filter needs to be created using the entity model properties

Sorting and Paging

The OrderBy property in QueryModel object allows specifying ordering.

For ascending order base on property Title:

title

For descending order:

-title

It is possible to combine multiple orderings:

id,-priority,title

Custom filters can not be used for ordering

Custom filters

The CustomFilterAttribute attribute allows changing the default behavior of filters, it can be done in different ways:

Decorating a property without a filter type

[CustomFilter]
public int Priority { get; set; }

By default this property will be excluded as part of the filter, custom code needs to be written for doing something with the filter value, after the Query object is created:

[HttpGet]
public IActionResult List([FromQuery] QueryModel queryModel)
{
    var query = _queryBuilder.CreateQuery<Card>(queryModel);
    var queryable = _context.Set<Card>();

    // Applying custom filter
    if (query.TryGetFilters(m => m.Priority, out var filters))
    {
        var filterValue = filters.First().Values.First();
        queryable = queryable.Where(m => m.Priority == filterValue);
    }

    var result = queryable.ApplyQuery(query).ToList();
    return Ok(result);
}

Decorating a property specifying a filter type

WIP

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.1.1 1,684 3/25/2024
2.1.0 561 12/7/2023
2.0.0 808 11/11/2023
2.0.0-beta.4 76 11/11/2023
2.0.0-beta.3 147 11/5/2023
2.0.0-beta.2 180 10/28/2023
2.0.0-beta.1 79 10/26/2023
2.0.0-alpha-02 81 10/22/2023
2.0.0-alpha-01 88 10/22/2023
1.2.0 233 9/16/2023
1.1.0 265 9/8/2023
1.0.2 628 5/3/2023
1.0.1 143 4/26/2023
1.0.0 403 10/6/2022
1.0.0-beta-0007 106 10/4/2022
1.0.0-beta-0006 163 9/28/2022
1.0.0-beta-0005 143 9/17/2022
1.0.0-beta-0004 189 9/14/2022
1.0.0-beta-0003 116 9/13/2022
1.0.0-beta-0001 110 9/10/2022
1.0.0-alpha-0002 110 9/9/2022
1.0.0-alpha-0001 108 9/8/2022