romaklayt.DynamicFilter.Binder.Net 2.5.9

dotnet add package romaklayt.DynamicFilter.Binder.Net --version 2.5.9                
NuGet\Install-Package romaklayt.DynamicFilter.Binder.Net -Version 2.5.9                
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="romaklayt.DynamicFilter.Binder.Net" Version="2.5.9" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add romaklayt.DynamicFilter.Binder.Net --version 2.5.9                
#r "nuget: romaklayt.DynamicFilter.Binder.Net, 2.5.9"                
#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 romaklayt.DynamicFilter.Binder.Net as a Cake Addin
#addin nuget:?package=romaklayt.DynamicFilter.Binder.Net&version=2.5.9

// Install romaklayt.DynamicFilter.Binder.Net as a Cake Tool
#tool nuget:?package=romaklayt.DynamicFilter.Binder.Net&version=2.5.9                

romaklayt.DynamicFilter

Simple filter for .net WebApi that enables your endpoint to query your requests by url.

It provides ways to query, order and page your webapi and mvc.

.Net Core and .Net

First, download the packages into your project from nuget

nuget install romaklayt.DynamicFilter.Extensions.EntityFrameworkCore
nuget install romaklayt.DynamicFilter.Binder.Net

and, if you need, add to your ConfigureServices Startup.cs class for register value provider (JSON) for body JSON POST request support (providers for form-data, x-www-form-urlencoded work them by default)

services.AddControllers(options => options.ValueProviderFactories.Add(new JsonBodyValueProviderFactory()));

If you need to use DynamicFilter with IAsyncEnumerable or IAsyncQueryable use the package

nuget install romaklayt.DynamicFilter.Extensions.Async

After downloaded, go to your webapi and create an get or post endpoint receiving IDynamicComplex as parameter.

[HttpGet]
public Task<List<User>> Get([FromQuery] DynamicComplex filter)

Now you can query your endpoint with the DynamicFilter properties. Check "tests" folder on the Api projects for examples.

[HttpGet]
public Task<List<User>> Get([FromQuery] DynamicComplex filter)
{
    return users.Apply(filter).ToList();
}

DynamicFilter.Parser will transform your URI Queries into .Net Expressions. That way, you can use these expressions to filter your values into your database repository.

Simple Filter

You can use a DynamicComplexModel model for filtering. A DynamicFilterModel model without additional properties is also available.

public Task<List<User>> Get([FromQuery] DynamicComplex filter) #or DynamicFilterModel
{
    return users.Apply(filter).ToList(); #ApplyFilter for DynamicFilterModel
}

Example Uri:

GET http://url?filter=name==Bruno

Expression generated by Uri:

x => x.Name == "Bruno"

Filters are also supported for nested collections.

GET http://url?filter=roles.name==admin

Your request will be converted to:

users.Where(x => x.Roles.Any(y => y.Name == "admin"))

If the standard behavior for arrays and lists using the Any method does not suit you, you can add the '=' sign after the comparison operator, after which the system will use the All method for arrays:

GET http://url?filter=roles.name===admin

Your request will be converted to:

users.Where(x => x.Roles.All(y => y.Name == "admin"))

The parser supports the count property for the collection, you can use it as a regular collection property:

GET http://url?filter=roles.count==1

If you need to filter values by default for the value type, use \default:

GET http://url?filter=roles.name==\default

Complex Filter

Boolean operators &&(and) and ||(or) are supported.

Example Uri:

GET http://url?filter=name==Bruno&&lastname@=r&&age>=27

Since version 2.0 more complex filters are available. You can use brackets to create more complex expressions.

GET http://url?filter=(name==Bruno&&lastname@=r)||(age>=27)
GET http://url?filter=(name==Bruno&&lastname@=r)||(age>=27&&name==Bruno)

You can nest multiple parentheses to create complex expressions.

GET http://url?filter=((name==Bruno&&lastname@=r)||(age>=27))&&roles.name==Admin

Attention!

For correct parsing of the filter, when using brackets, enclose all logical elements in brackets, for example:

Not correct

GET http://url?filter=((name==Bruno&&lastname@=r)||age>=27)&&roles.name==Admin

Correct (age>=27 in brackets)

GET http://url?filter=((name==Bruno&&lastname@=r)||(age>=27))&&roles.name==Admin

Nested Filer

Example Uri:

GET http://url?filter=address.number==23

Expression generated by Uri:

x => x.Address.Number == 23

Ordering

You can also order your queries via DynamicFilter. You simply need to add an order parameter on your query, where you specify the property you'll use for order.

GET http://url?filter=name==Bruno&order=name

Default order type is Ascending. You can adding a - before the name switches to sorting descendingly..

GET http://url?filter=name==Bruno&order=name

GET http://url?filter=name==Bruno&order=-name

To sort by multiple properties:

GET http://url?filter=name==Bruno&order=name,firstname

GET http://url?filter=name==Bruno&order=-name,-firstname

If you do not specify the sort type, asc is used by default.

On your DynamicFilter object received on the endpoint, you'll get the orderType as an Enum, this way you can order by the type specified on enum.

public Task<List<User>> Get([FromQuery] DynamicComplex filter)
{
    return users.Apply(filter).ToList();
}

Pagging

GET http://url?filter=name@=*b&order=name&page=1&pagesize=10

In romaklayt.DynamicFilter.Extensions.* there is a method of expanding the ToPageModel which returns PageModel with info about page and your filtered data.

var page = users.ToPageModel(filterModel);

The PageModel is built on top of the List<T> so to add page information to the server response you need to add an AddPageInfoFilter which will write the page information to the headers.

services.AddControllers(options =>
        {
            options.Filters.Add(new PageInfoWriter());
        });

If you no need page info, you simply needs to add the parameters page and pagesize on your get request.

result = result.ApplyFilter(filter); #page mode without additional info

If you specify the page number and size in the filter model, pagination is disabled when using ApplyFilter. You can also disable pagination by forcibly calling:

result = result.ApplyFilter(filter, false); #only filtering without pagination

Example:

[HttpGet("page")]
public async Task<PageModel<User>> GetPage([FromQuery] DynamicComplex filterModel)
{
    return Data.Users.ToPageModel(filterModel);
}

Select

To select, you simply needs to add the parameter select with the properties you want to select from. It will render either an linq select and a plain string select.

GET http://url?select=name,age

If you select a nested property, from default, the properties from the root model will be ignored, to select all the root properties, use the word root.

GET http://url?select=address.zip,root #select Address.Zip and all root properties

If you need to select properties from only one model (the GetById method, for example), you can also use the method ** ApplyFilter**.

[HttpGet("{id}")]
public async Task<object> GetById([FromQuery] DynamicSelect dynamicSelectModel, Guid id)
{
    return await Data.Users.ApplySelect(dynamicSelectModel).DynamicFirstOfDefault("Id", id);
}

Filter operator support

Operator Meaning
== Equals
> Greater than
< Less than
>= Greater than or equal to
<= Less than or equal to
@= Contains
_= Starts with
_-= Ends with
@=* Case-insensitive string Contains
_=* Case-insensitive string Starts with
_-=* Case-insensitive string Ends with
==* Case-insensitive string Equals

All operators support negation, you need to put "!" before the operator (e.g. !== for Equals)

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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. 
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.5.9 250 9/24/2024
2.5.8 470 8/11/2024
2.5.7 694 4/27/2024
2.5.6 125 4/18/2024
2.5.5 111 4/10/2024
2.5.4 111 4/2/2024
2.5.3 117 4/1/2024
2.5.2 132 3/8/2024
2.5.1 119 3/3/2024
2.5.0 179 1/6/2024
2.4.5 187 8/14/2023
2.4.4 162 8/14/2023
2.4.3 197 6/18/2023
2.4.2 165 6/18/2023
2.4.1 179 6/7/2023
2.4.0 163 6/5/2023
2.3.5 164 6/2/2023
2.3.4 210 4/19/2023
2.3.3 188 4/18/2023
2.3.2 189 4/16/2023
2.3.1 205 4/9/2023
2.3.0 200 4/9/2023
2.2.1 203 4/8/2023
2.2.0 211 4/8/2023
2.2.0-tags-2-2-0-beta-1.1 79 4/8/2023
2.1.2 395 11/4/2022
2.1.1 371 11/4/2022
2.1.0 396 9/24/2022
2.1.0-beta.1 102 9/9/2022
2.0.0 432 9/2/2022
2.0.0-beta.3 123 7/28/2022
2.0.0-beta.2 104 7/26/2022
2.0.0-beta.1 113 7/19/2022
1.9.3 494 4/21/2022
1.9.2 467 4/10/2022
1.9.1 462 4/6/2022
1.9.0 449 4/5/2022
1.8.1 454 3/27/2022
1.8.0 450 3/7/2022
1.7.12 393 10/5/2022
1.7.11 524 2/8/2022
1.7.10 450 2/8/2022
1.7.9 469 1/11/2022
1.7.8 471 1/11/2022
1.7.7 458 1/11/2022
1.7.6 469 1/11/2022
1.7.5 460 1/10/2022
1.7.4 309 12/26/2021
1.7.3 320 12/17/2021
1.7.2 314 12/12/2021
1.7.1 333 12/3/2021
1.7.0 341 11/14/2021
1.6.5 406 11/6/2021
1.6.4 387 10/26/2021
1.6.3 352 10/12/2021
1.6.2 393 10/12/2021
1.6.1 355 10/12/2021
1.6.0 352 10/11/2021
1.5.5 350 10/6/2021
1.5.4 359 10/6/2021
1.5.3 383 9/27/2021
1.5.2 331 9/27/2021
1.5.1 361 9/27/2021
1.5.0 369 9/27/2021
1.4.1 365 9/24/2021
1.4.0 406 9/24/2021
1.3.1 402 9/22/2021
1.3.0 359 9/20/2021
1.2.0 376 9/17/2021
1.1.4 393 9/17/2021
1.1.3 383 9/17/2021
1.1.2 370 9/17/2021
1.1.1 354 9/16/2021
1.1.0 383 9/13/2021
1.0.2 436 9/10/2021
1.0.1 406 9/10/2021
1.0.0 393 9/10/2021