Entity Registration
options.Entity<T>(route) registers an EF Core entity with OtterApi and returns
an OtterApiEntityBuilder<T>. Every method on the builder returns the same instance,
so calls can be chained fluently.
Full builder API
Fluent builder — all options
options.Entity<TEntity>(route)
.Authorize(bool authorize = true)
.WithEntityPolicy(string policy)
.WithGetPolicy(string policy)
.WithPostPolicy(string policy)
.WithPutPolicy(string policy)
.WithPatchPolicy(string policy)
.WithDeletePolicy(string policy)
.Allow(OtterApiCrudOperation operations)
.ExposePagedResult(bool expose = true)
.WithQueryFilter(Expression<Func<T, bool>> predicate)
.WithScopedQueryFilter(Func<IServiceProvider, Expression<Func<T, bool>>> factory)
.WithCustomRoute("slug", ...)
.BeforeSave(...)
.AfterSave(...);
Restricting HTTP methods — .Allow()
By default, all five CRUD operations are enabled. Use .Allow() to restrict which
HTTP methods are accepted. Requests for a disallowed method return 405 Method Not Allowed.
Allow only GET and POST
options.Entity<Product>("products")
.Allow(OtterApiCrudOperation.Get | OtterApiCrudOperation.Post);
OtterApiCrudOperation flags
| Flag | Value | HTTP methods |
|---|---|---|
Get | 1 | GET |
Post | 2 | POST |
Put | 4 | PUT |
Delete | 8 | DELETE |
Patch | 16 | PATCH |
All | 31 | All of the above (default) |
Exposing PagedResult — .ExposePagedResult()
Calling .ExposePagedResult() enables the /pagedresult endpoint for
that entity, which returns a rich pagination envelope with total, pageCount,
and items. See Query Parameters → PagedResult.
Enable /pagedresult
options.Entity<Product>("products").ExposePagedResult();
// Now available:
// GET /api/products/pagedresult?page=1&pagesize=20
Entity requirements
- Must be registered as
DbSet<T>in the providedDbContext. If it is not, anInvalidOperationExceptionis thrown at startup. - Primary key is auto-detected (see Getting Started).
-
Filterable and sortable property types: primitives,
string,Guid,DateTime,DateTimeOffset,enum, and all nullable variants. - Navigation properties (collections, nested objects) are excluded from filtering but available via
?include=.
Practical example
Full entity configuration
options.Entity<Product>("products")
.Authorize() // require authentication
.WithPostPolicy("IsManager") // POST needs Manager role
.WithPutPolicy("IsManager") // PUT needs Manager role
.WithPatchPolicy("IsManager") // PATCH needs Manager role
.WithDeletePolicy("IsAdmin") // DELETE needs Admin role
.ExposePagedResult() // enable /pagedresult
.WithQueryFilter(p => p.IsActive) // server-side row filter
.BeforeSave((ctx, p, _, op) =>
{
if (op == OtterApiCrudOperation.Post)
p.CreatedAt = DateTime.UtcNow;
});