Filtering
Filtering is the fifth step in the request flow. It occurs after model providing and before condition checks. An unlimited number of Filters may be added to a route. They will be run in the order they were added. Each Filter takes in the dataset and IApiContext<TModel, TUser> and returns a modified dataset, either directly filtered or otherwise transformed. This new dataset will be used in place of the existing one until provided to the Operation. If there is no operation, the filtered dataset is returned by the API.
Important
When using Seltzr with an ORM like Entity Framework, avoid client-side evaluation in Filters. Client-side evaluation often results in pulling more information from the database than is necessary for the request, and can result in poor performance. If you must use client-side evaluation, see below for an example that explicitly enables it.
Builder Methods
Low-Level Methods
These methods are primarily used when you've implemented your own IFilter<TModel, TUser> and want to attach it to a route.
High-Level Methods
Builder Prefix: Filter
- Filter(Func<IApiContext<TModel, TUser>, IQueryable<TModel>, IQueryable<TModel>>)
- Filter(Func<IQueryable<TModel>, IQueryable<TModel>>)
- FilterAsync(Func<IApiContext<TModel, TUser>, IQueryable<TModel>, Task<IQueryable<TModel>>>)
- FilterAsync(Func<IQueryable<TModel>, Task<IQueryable<TModel>>>)
- FilterByParameter<T>(Expression<Func<TModel, T>>, ParameterRetriever, Expression<Func<T, T, Boolean>>)
- FilterByParameterEqual<T>(Expression<Func<TModel, T>>, ParameterRetriever)
- FilterByParameterEqualOpt<T>(Expression<Func<TModel, T>>, ParameterRetriever)
- FilterByParameterOpt<T>(Expression<Func<TModel, T>>, ParameterRetriever, Expression<Func<T, T, Boolean>>)
- FilterByQuery<T>(Expression<Func<TModel, T>>, Expression<Func<T, T, Boolean>>)
- FilterByQuery<T>(Expression<Func<TModel, T>>, String, Expression<Func<T, T, Boolean>>)
- FilterByQueryEqual<T>(Expression<Func<TModel, T>>)
- FilterByQueryEqual<T>(Expression<Func<TModel, T>>, String)
- FilterByQueryEqualOpt<T>(Expression<Func<TModel, T>>)
- FilterByQueryEqualOpt<T>(Expression<Func<TModel, T>>, String)
- FilterByQueryOpt<T>(Expression<Func<TModel, T>>, Expression<Func<T, T, Boolean>>)
- FilterByQueryOpt<T>(Expression<Func<TModel, T>>, String, Expression<Func<T, T, Boolean>>)
- FilterByRoute<T>(Expression<Func<TModel, T>>, Expression<Func<T, T, Boolean>>)
- FilterByRoute<T>(Expression<Func<TModel, T>>, String, Expression<Func<T, T, Boolean>>)
- FilterByRouteEqual<T>(Expression<Func<TModel, T>>)
- FilterByRouteEqual<T>(Expression<Func<TModel, T>>, String)
- FilterByRouteEqualOpt<T>(Expression<Func<TModel, T>>)
- FilterByRouteEqualOpt<T>(Expression<Func<TModel, T>>, String)
- FilterByRouteOpt<T>(Expression<Func<TModel, T>>, Expression<Func<T, T, Boolean>>)
- FilterByRouteOpt<T>(Expression<Func<TModel, T>>, String, Expression<Func<T, T, Boolean>>)
- FilterWhere(Expression<Func<TModel, Boolean>>)
- FilterWhere(Expression<Func<IApiContext<TModel, TUser>, TModel, Boolean>>)
- First()
- Limit(Int32)
- LimitOne()
- LimitQuery(String)
- LimitQuery(String, Int32)
- OrderBy<TKey>(Expression<Func<TModel, TKey>>)
- OrderBy<TKey>(Expression<Func<TModel, TKey>>, IComparer<TKey>)
- OrderByDescending<TKey>(Expression<Func<TModel, TKey>>)
- OrderByDescending<TKey>(Expression<Func<TModel, TKey>>, IComparer<TKey>)
- Paginate()
- Paginate(String, Int32)
- Paginate(String, String)
- Paginate(String, String, Int32)
- Skip(Int32)
- SkipQuery(String, Int32)
Extension Methods:
- FilterByPrimaryKey<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>, ParameterRetriever[])
- FilterByPrimaryKeyQuery<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>)
- FilterByPrimaryKeyQuery<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>, String[])
- FilterByPrimaryKeyRoute<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>)
- FilterByPrimaryKeyRoute<TModel, TUser>(SeltzrOptionsBuilder<TModel, TUser>, String[])
Note
Methods in italics also enforce Conditions alongside the Filter they add
Note
Methods in bold are only available with an ORM-backed version of Seltzr, e.g Seltzr.EntityFrameworkCore
Examples
Filtering using Route Values and Query Parameters
See FilterBy Builder Methods for examples on filtering using request parameters.
Explicit Client-Side Evaluation
Although client-side evaluation is generally discouraged, it is sometimes necessary for complex logic which can't be translated to a database query. To explicitly enable client-side evaluation, call FetchModels() before filtering.
app.UseSeltzr<BlogPost>("/blogs/{blogId}/posts/recent", posts => {
posts
.Filter(p => p.DateCreated > DateTime.Now.AddDays(-30))
.FetchModels()
.FilterByQueryOpt(p => p.Author, "token", (a, t) => GetToken(a) == t)
.CanGet();
});
Tip
Call FetchModels() as late as possible when filtering to keep most of the evaluation on the server.
Using LINQ analog methods to filter the dataset
Often you'll need to filter the dataset using queries traditionally available with LINQ methods. Seltzr includes several analogous methods for filtering, including FilterWhere
, Skip
, Limit
, and OrderBy
.
The following example uses some of those methods to return a sorted list of the first 10 users whose name starts with the letter "B":
app.UseSeltzr<User>("/users", posts => {
posts
.FilterWhere(u => u.Name.StartsWith("B"))
.OrderBy(u => u.Name)
.Limit(10)
.CanGet();
});
Note
Since filter methods are run in the order they were added, calling OrderBy
after Limit
would alphabetically sort the first 10 users returned by the database, not the 10 alphabetically-first users.
The SeltzrOptionsBuilder<TModel, TUser> class also has a LimitQuery
method which can be used to limit the number of returned models to a number specified by a query parameter.
app.UseSeltzr<User>("/users", posts => {
posts
.LimitQuery("count", 50) // max count is 50
.CanGet();
});
Using the Filter
method for complex logic
If the other builder methods don't suit your needs, the Filter
and FilterAsync
methods can be used for complex filtering logic. These methods take lambdas which can be passed either just the dataset, or both the IApiContext<TModel, TUser> and the dataset. The following example uses the context to get a service which filters the dataset.
app.UseSeltzr<User>("/users", posts => {
posts
.Filter((ctx, data) => {
IFilteringService Service = ctx.Services.GetRequiredService<IFilteringService>();
return Service.Filter(data);
})
.CanGet();
});
Pagination
For examples on how to use the Paginate
methods, see Pagination