QueryX 1.1.0
See the version list below for details.
dotnet add package QueryX --version 1.1.0
NuGet\Install-Package QueryX -Version 1.1.0
<PackageReference Include="QueryX" Version="1.1.0" />
paket add QueryX --version 1.1.0
#r "nuget: QueryX, 1.1.0"
// Install QueryX as a Cake Addin #addin nuget:?package=QueryX&version=1.1.0 // Install QueryX as a Cake Tool #tool nuget:?package=QueryX&version=1.1.0
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.
- QueryModel, this class is used for capturing queries from URL query strings, it provides
Filter
,OrderBy
,Offset
andLimit
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" (|
) logical operators:
id>1 & title=-'test' | priority|=1,2
For facilitating writing queries in URL, ;
(semicolon) character can be used instead for representing the and logical operator:
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
Category | Description |
---|---|
Numbers | integer, float, real, etc. |
String, Char | should be wrapped in single quotes |
DateTime, Timespan | should be wrapped in single quotes |
Enums | should be wrapped in single quotes |
Constants | true, false, null |
Operators
Operator | Description | Comment |
---|---|---|
== | Equals operator | |
!= | Not equals | |
< | Less than | |
⇐ | Less than or equals | |
> | Greater than | |
>= | Greater than or equals | |
-=- | Contains | String type only |
=- | Starts with | String type only |
-= | Ends with | String type only |
|= | In | Allows multiple values |
Multiple values are specified this way: 0,1,2
or 'val1','val2','val3'
if the values are strings
Case insensitive operator
All operators can be combined with the case insensitive operator (*
) for ignoring case when comparing strings:
title ==* 'TeSt VaLuE'
This operator is intended to work only with string properties
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 stringIsSortable
determines if this property is sortable or not, true by defaultParamsPropertyName
is used for mapping filter names from query string. In this case, in query string will be a filter namedEstimatedPts
that will be mapped to theEstimatedPoints
propertyModelPropertyName
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 theEstimation
property in the entity model because theIQueryable
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:
[CustomFilter]
public int Priority { get; set; }
Properties marked with this attribute 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.TryGetFilter(m => m.Priority, out var filter))
{
var filterValue = filter.Values.First();
queryable = queryable.Where(m => m.Priority == filterValue);
}
var result = queryable.ApplyQuery(query).ToList();
return Ok(result);
}
Query exceptions
By default invalid properties will be ignored for filtering and ordering but it is possible to change this behavior by setting ThrowQueryExceptions
to true when registering QueryX:
builder.Services.AddQueryX(o => o.ThrowQueryExceptions = true);
These exceptions will be thrown as appropriate:
InvalidFilterPropertyException
for filtering errorsInvalidOrderingPropertyException
for ordering errors
Product | Versions 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. |
-
.NETStandard 2.1
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 6.0.0)
- Superpower (>= 3.0.0)
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,682 | 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 |