MikesSifter is a versatile and extensible library designed to provide powerful filtering, sorting and paging capabilities in .NET applications.
Minimum Requirements: .NET 8.0.x
NuGet\Install-Package MikesSifter -Version *version_number*
dotnet add package MikesSifter --version *version_number*
In this example, consider an app with a User
entity that can have many projects. We'll use MikesSifter to add sorting, filtering and pagination capabilities when retrieving all available users.
Inherit the base implementation MikesSifter
and override the Configure
method.
public class ApplicationSifter : MikesSifter
{
protected override void Configure(MikesSifterBuilder builder)
{
// Here apply your configurations.
}
}
public class UserSifterConfiguration : IMikesSifterEntityConfiguration<User>
{
public void Configure(MikesSifterEntityBuilder<User> builder)
{
builder
.Property(e => e.FullName)
.EnableFiltering()
.EnableSorting();
builder
.Property(e => e.Gender)
.EnableSorting()
.EnableFiltering();
builder
.Property(e => e.BirthDate)
.EnableFiltering()
.EnableSorting();
builder
.Property(e => e.Projects)
.EnableFiltering()
.HasCustomFilters(e =>
{
e.WithFilter(FilteringOperators.Contains, filterValue =>
{
ArgumentException.ThrowIfNullOrWhiteSpace(filterValue);
return u => u.Projects.Any(o => o.Id == Guid.Parse(filterValue));
});
});
builder
.Property(e => e.Passport.Number)
.EnableFiltering()
.EnableSorting()
.HasAlias("user_passportNumber");
}
}
Apply particular configuration by calling ApplyConfiguration<T>
:
protected override void Configure(MikesSifterBuilder builder)
{
builder.ApplyConfiguration<UserSifterConfiguration>();
}
Apply configurations from a particular assembly by calling ApplyConfigurationsFromAssembly
:
protected override void Configure(MikesSifterBuilder builder)
{
builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
protected override void Configure(MikesSifterBuilder builder)
{
builder.Entity<User>(e =>
{
e.Property(i => i.FullName)
.EnableFiltering()
.EnableSorting();
e.Property(i => i.Gender)
.EnableSorting()
.EnableFiltering();
e.Property(i => i.BirthDate)
.EnableFiltering()
.EnableSorting();
e.Property(e => e.Projects)
.EnableFiltering()
.HasCustomFilters(e =>
{
e.WithFilter(FilteringOperators.Contains, filterValue =>
{
ArgumentException.ThrowIfNullOrWhiteSpace(filterValue);
return u => u.Projects.Any(o => o.Id == Guid.Parse(filterValue));
});
});
e.Property(i => i.Passport.Number)
.EnableFiltering()
.EnableSorting()
.HasAlias("user_passportNumber");
});
}
In our example, we will use a custom model implementation as the POST body. However, you can implement your own using, for example, GET method with query parameters.
public sealed class ApplicationSifterModel : IMikesSifterModel
{
public FilteringOptions? FilteringOptions { get; init; }
public SortingOptions? SortingOptions { get; init; }
public PagingOptions? PagingOptions { get; init; }
public FilteringOptions? GetFilteringOptions() => FilteringOptions;
public SortingOptions? GetSortingOptions() => SortingOptions;
public PagingOptions? GetPagingOptions() => PagingOptions;
}
Add the application sifter to the services by calling the AddSifter
extension method.
builder.Services.AddSifter<ApplicationSifter>();
Inject IMikesSifter
into controller to use the sifter capabilities.
[HttpPost("full")]
public IActionResult Full(ApplicationSifterModel model)
{
var result = sifter.Apply(dbContext
.Users
.Include(e => e.Projects)
.Include(e => e.Passport), model);
return Ok(result.Select(e => e.ToViewModel()).ToList());
}
[HttpPost("filtering")]
public IActionResult OnlyFiltering(FilteringOptions filteringOptions)
{
var result = sifter.ApplyFiltering(dbContext
.Users
.Include(e => e.Projects)
.Include(e => e.Passport), filteringOptions);
return Ok(result.Select(e => e.ToViewModel()).ToList());
}
[HttpPost("sorting")]
public IActionResult OnlySorting(SortingOptions sortingOptions)
{
var result = sifter.ApplySorting(dbContext
.Users
.Include(e => e.Projects)
.Include(e => e.Passport), sortingOptions);
return Ok(result.Select(e => e.ToViewModel()).ToList());
}
[HttpPost("paging")]
public IActionResult OnlyPaging(PagingOptions pagingOptions)
{
var result = sifter.ApplyPaging(dbContext
.Users
.Include(e => e.Projects)
.Include(e => e.Passport), pagingOptions);
return Ok(result.Select(e => e.ToViewModel()).ToList());
}