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.
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()
.HasCustomFilter(FilteringOperators.Contains, filterValue =>
{
ArgumentException.ThrowIfNullOrWhiteSpace(filterValue);
return u => u.Projects.Any(e => e.Id == Guid.Parse(filterValue));
});
builder
.Property(e => e.Passport.Number)
.EnableFiltering()
.EnableSorting()
.HasAlias("user_passportNumber");
}
}
Apply configurations by calling ApplyConfiguration<T>
:
builder.ApplyConfiguration<UserSifterConfiguration>();
Apply configurations from a particular assembly by calling ApplyConfigurationsFromAssembly
:
builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
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(i => i.Projects)
.EnableFiltering()
.HasCustomFilter(FilteringOperators.Contains, filterValue =>
{
ArgumentException.ThrowIfNullOrWhiteSpace(filterValue);
return u => u.Projects.Any(pr => pr.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 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;
}
Inherit the base implementation MikesSifter
and override the Configure
method.
public class ApplicationSifter : MikesSifter
{
protected override void Configure(MikesSifterBuilder builder)
{
builder.ApplyConfiguration<UserSifterConfiguration>();
}
}
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());
}