Pandatech.GridifyExtensions
4.3.0
dotnet add package Pandatech.GridifyExtensions --version 4.3.0
NuGet\Install-Package Pandatech.GridifyExtensions -Version 4.3.0
<PackageReference Include="Pandatech.GridifyExtensions" Version="4.3.0" />
<PackageVersion Include="Pandatech.GridifyExtensions" Version="4.3.0" />
<PackageReference Include="Pandatech.GridifyExtensions" />
paket add Pandatech.GridifyExtensions --version 4.3.0
#r "nuget: Pandatech.GridifyExtensions, 4.3.0"
#:package Pandatech.GridifyExtensions@4.3.0
#addin nuget:?package=Pandatech.GridifyExtensions&version=4.3.0
#tool nuget:?package=Pandatech.GridifyExtensions&version=4.3.0
Pandatech.GridifyExtensions
Extensions for Gridify providing streamlined filtering, ordering, pagination, and aggregation for .NET 8+ with Entity Framework Core.
Installation
dotnet add package Pandatech.GridifyExtensions
Setup
Register Gridify with custom mapper discovery:
builder.AddGridify(); // Scans calling assembly
// or
builder.AddGridify(typeof(Program).Assembly, typeof(Domain).Assembly);
Quick Start
1. Define Entity Mapper
public class Book
{
public Guid Id { get; set; }
public string Title { get; set; }
public DateTime PublishedDate { get; set; }
public decimal Price { get; set; }
}
public class BookMapper : FilterMapper<Book>
{
public BookMapper()
{
GenerateMappings(); // Auto-map all properties
// Custom mappings
AddMap("book-id", x => x.Id);
AddMap("title", x => x.Title.ToLower(), x => x.ToLower());
AddMap("published", x => x.PublishedDate, x => x.ToUtcDateTime());
// Default sort order
AddDefaultOrderByDescending("published");
}
}
2. Query with Filtering & Pagination
// Paged response
var result = await dbContext.Books
.FilterOrderAndGetPagedAsync(
new GridifyQueryModel {
Page = 1,
PageSize = 20,
Filter = "title=*potter*",
OrderBy = "published desc"
},
cancellationToken
);
// With projection
var dtos = await dbContext.Books
.FilterOrderAndGetPagedAsync(
new GridifyQueryModel { Page = 1, PageSize = 20 },
x => new BookDto { Title = x.Title, Price = x.Price },
cancellationToken
);
3. Cursor-Based Pagination
var result = await dbContext.Books
.FilterOrderAndGetCursoredAsync(
new GridifyCursoredQueryModel {
PageSize = 50,
Filter = "price>10"
},
cancellationToken
);
Core Features
Filtering & Ordering
// Apply filter only
var filtered = query.ApplyFilter("title=*science*");
// Apply filter from model
var filtered = query.ApplyFilter(new GridifyQueryModel { Filter = "price<20" });
// Apply ordering
var ordered = query.ApplyOrder(new GridifyQueryModel { OrderBy = "title" });
Pagination
// Traditional paging
var paged = await query.GetPagedAsync(
new GridifyQueryModel { Page = 2, PageSize = 10 },
cancellationToken
);
// Cursor-based (more efficient for large datasets)
var cursored = await query.FilterOrderAndGetCursoredAsync(
new GridifyCursoredQueryModel { PageSize = 50 },
cancellationToken
);
Column Distinct Values
// Get distinct values for a column (with cursor pagination)
var distinctTitles = await dbContext.Books
.ColumnDistinctValuesAsync(
new ColumnDistinctValueCursoredQueryModel {
PropertyName = "title",
PageSize = 50,
Filter = "title>A"
},
cancellationToken
);
// For encrypted columns, provide decryptor
var decrypted = await query.ColumnDistinctValuesAsync(
model,
decryptor: bytes => Decrypt(bytes),
cancellationToken
);
When the filter has a =* (contains) term on the requested string column, the values are ranked for autocomplete:
exact match, then values starting with the term, then values with a word starting with the term, then the remaining
matches. Within a rank, plain columns order by length and value; columns with a natural sort key
(AddMapForNaturalSortKey) order by that key.
Aggregations
var total = await dbContext.Books
.AggregateAsync(
new AggregateQueryModel {
AggregateType = AggregateType.Sum,
PropertyName = "price"
},
cancellationToken
);
Supported aggregations:
UniqueCount- Count of distinct valuesSum- Sum of valuesAverage- Average valueMin- Minimum valueMax- Maximum value
Advanced Features
Custom Converters
public class DeviceMapper : FilterMapper<Device>
{
public DeviceMapper()
{
GenerateMappings();
// Case-insensitive string matching
AddMap("name", x => x.Name.ToLower(), x => x.ToLower());
// DateTime with UTC conversion
AddMap("created", x => x.CreatedAt, x => x.ToUtcDateTime());
AddDefaultOrderByDescending("created");
}
}
Encrypted Columns
public class UserMapper : FilterMapper<User>
{
public UserMapper()
{
// Mark column as encrypted
AddMap("email", x => x.EncryptedEmail, isEncrypted: true);
}
}
// Query with decryption
var users = await dbContext.Users
.ColumnDistinctValuesAsync(
new ColumnDistinctValueCursoredQueryModel { PropertyName = "email" },
decryptor: encryptedBytes => AesDecrypt(encryptedBytes),
cancellationToken
);
Complex Mappings
// Navigation properties
AddMap("author-name", x => x.Author.Name);
// Collections
AddMap("tags", x => x.Tags.Select(t => t.Name));
// Nested properties
AddMap("publisher-country", x => x.Publisher.Address.Country);
Page Size Limits
By default, GridifyQueryModel limits PageSize to 500:
// Remove limit via constructor
var model = new GridifyQueryModel(validatePageSize: false) {
PageSize = 1000,
Page = 1
};
// Or set to maximum
model.SetMaxPageSize(); // Sets PageSize to int.MaxValue
Custom Flag Operator
Built-in support for bitwise flag checking:
// Filter by enum flags
var query = "permissions#hasFlag16"; // checks if bit 16 is set
Gridify Query Syntax
Standard Gridify filtering syntax is supported:
// Operators: =, !=, <, >, <=, >=, =*, *=, =*=
Filter = "title=*potter*, price<20, published>2020-01-01"
// Logical: , (AND), | (OR), () (grouping)
Filter = "(title=*fantasy*|title=*scifi*), price<30"
// Custom operators
Filter = "flags#hasFlag4" // bitwise flag check
API Reference
Extension Methods
| Method | Description |
|---|---|
ApplyFilter(model/filter) |
Apply filtering |
ApplyOrder(model) |
Apply ordering |
GetPagedAsync(model) |
Get paged results |
FilterOrderAndGetPagedAsync(model) |
Filter + order + page |
FilterOrderAndGetCursoredAsync(model) |
Cursor-based pagination |
ColumnDistinctValuesAsync(model) |
Get distinct column values |
AggregateAsync(model) |
Perform aggregation |
Model Types
GridifyQueryModel- Traditional pagination with page numberGridifyCursoredQueryModel- Cursor-based paginationColumnDistinctValueCursoredQueryModel- Distinct values with cursorAggregateQueryModel- Aggregation configuration
Response Types
PagedResponse<T>-(Data, Page, PageSize, TotalCount)CursoredResponse<T>-(Data, PageSize)
License
MIT
| Product | Versions 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. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Gridify.EntityFramework (>= 2.19.1)
-
net8.0
- Gridify.EntityFramework (>= 2.19.1)
-
net9.0
- Gridify.EntityFramework (>= 2.19.1)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Pandatech.GridifyExtensions:
| Package | Downloads |
|---|---|
|
Pandatech.ResponseCrafter
Exception-based error handling for ASP.NET Core 8+ with RFC 9457 ProblemDetails, structured logging, typed exceptions, automatic EF Core/Gridify/FluentImporter exception mapping, SignalR support, and flexible naming conventions. Alternative to Result pattern libraries. |
|
|
Pandatech.SharedKernel.Postgres
PostgreSQL integration helpers for ASP.NET Core 10: DbContext registration with or without pooling and audit trail, migrations, health checks, snake_case naming, query locks, exception mapping, and bulk extensions. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.3.0 | 198 | 9/10/2026 |
| 4.2.0 | 131 | 9/2/2026 |
| 4.1.3 | 338 | 7/6/2026 |
| 4.1.2 | 127 | 6/30/2026 |
| 4.1.1 | 207 | 6/10/2026 |
| 4.1.0 | 139 | 4/13/2026 |
| 4.0.2 | 389 | 3/19/2026 |
| 4.0.1 | 142 | 3/18/2026 |
| 4.0.0 | 242 | 2/28/2026 |
| 3.0.1 | 208 | 1/26/2026 |
| 3.0.0 | 176 | 12/28/2025 |
| 2.1.6 | 263 | 12/14/2025 |
| 2.1.5 | 271 | 12/5/2025 |
| 2.1.4 | 341 | 10/13/2025 |
| 2.1.3 | 246 | 10/13/2025 |
| 2.1.2 | 217 | 9/26/2025 |
| 2.1.1 | 301 | 9/21/2025 |
| 2.1.0 | 264 | 9/11/2025 |
| 2.0.14 | 356 | 8/15/2025 |
| 2.0.13 | 243 | 8/14/2025 |
ColumnDistinctValuesAsync ranks the hits of a =* (contains) search on a string column: exact match, then values starting with the term, then values with a word starting with the term, then the remaining matches. Plain columns then order by length and value, keyed columns by their natural sort key. Applies to the cursored and the paged overloads.