DataSurface

June 10, 2026 Β· View on GitHub

Contract-driven CRUD HTTP endpoints for ASP.NET Core

DataSurface eliminates CRUD boilerplate by generating fully-featured HTTP endpoints from a single source of truth: the ResourceContract. Define your resources once using C# attributes or database metadata, and get automatic validation, filtering, sorting, pagination, and more.

Publish NuGet

You define what a resource is β€” fields, validation, security, relations β€” and DataSurface handles:

  • CRUD endpoints
  • Validation
  • Filtering, sorting, pagination
  • Authorization & row-level security
  • Concurrency, caching, auditing, and observability

All without writing DTOs, controllers, or repetitive glue code.

🚫 What DataSurface Removes

  • Handwritten CRUD controllers
  • Read/Create/Update/Delete DTOs
  • Manual validation plumbing
  • Query parsing logic
  • Boilerplate authorization checks
  • Repeated Swagger/OpenAPI definitions

βœ… What You Keep

  • Full control over your domain model
  • Strong typing
  • Explicit security rules
  • Override hooks when you do need custom logic

Why DataSurface?

Most ASP.NET Core applications repeat the same pattern:

  • Entity
  • DTOs (Read / Create / Update)
  • Controller
  • Validation
  • Query parsing
  • Authorization checks

Multiply that by 20–50 entities and the cost becomes significant.

DataSurface collapses all of that into one contract.

You describe what is allowed, not how to wire it.

The result:

  • Fewer files
  • Less drift between layers
  • Consistent behavior across all resources
  • Faster iteration without sacrificing control

Before vs After

❌ Traditional CRUD

  • Entity
  • 3–5 DTOs
  • Controller with ~200 lines
  • Manual validation
  • Manual filtering & paging
  • Swagger configuration
  • Repeated authorization logic
User.cs
UserReadDto.cs
UserCreateDto.cs
UserUpdateDto.cs
UsersController.cs
UserValidator.cs

βœ… With DataSurface

  • Entity
  • Attributes describing the contract
[CrudResource("users")]
public class User
{
    [CrudKey]
    public int Id { get; set; }

    [CrudField(CrudDto.Read | CrudDto.Create | CrudDto.Update, RequiredOnCreate = true)]
    public string Email { get; set; } = default!;
}
app.MapDataSurfaceCrud();

That’s it!

Usage Modes

DataSurface can be used in two ways:

🌐 HTTP API (Most Common)

  • Generates REST endpoints via Minimal APIs
  • Full OpenAPI / Swagger support
  • Ideal for frontend, mobile, or external integrations
GET    /api/users
POST   /api/users
PATCH  /api/users/{id}
DELETE /api/users/{id}

βš™οΈ In-Process (No HTTP)

  • Call CRUD operations directly
  • Same validation, security, hooks, and contracts
  • Ideal for internal services, background jobs, or modular monoliths
await crudService.CreateAsync("User", body, ct);

No controllers. No HTTP. Same guarantees.

When to Use DataSurface

βœ… You build data-heavy APIs
βœ… You want consistent CRUD behavior
βœ… You want fewer DTOs and controllers
βœ… You need strong validation & security
βœ… You support dynamic or metadata-driven entities

When NOT to Use DataSurface

❌ You want full handcrafted controllers for every endpoint
❌ Your API is mostly bespoke workflows, not CRUD
❌ You dislike declarative configuration

DataSurface is not a replacement for custom business logic β€” it handles the 80% so you can focus on the 20%.

Features

FeatureDescription
Auto-generated endpointsGET, POST, PATCH, DELETE, PUT via Minimal APIs
Field-level controlChoose which fields appear in read/create/update DTOs
Default valuesAutomatically apply defaults when creating resources
Computed fieldsServer-calculated read-only fields
ValidationRequired, immutable, length, range, regex, allowed values
Field projectionSelect specific fields via ?fields= query parameter
Soft deleteBuilt-in ISoftDelete convention support
TimestampsAuto-populate CreatedAt/UpdatedAt via ITimestamped
Filtering & SortingAllowlisted fields with operators (eq, gt, contains, etc.)
PaginationBuilt-in page + pageSize with configurable max
Expansionexpand=relation with depth limits
HEAD supportHEAD requests return count headers without body
AuthorizationPer-operation policy names
Row-level securityIResourceFilter<T> for tenant/user-based query filtering
Resource authorizationIResourceAuthorizer<T> for instance-level access control
Field authorizationIFieldAuthorizer for field-level read/write control
Tenant isolationAutomatic multi-tenancy with [CrudTenant] attribute
ConcurrencyRow version + ETag / If-Match headers
HooksGlobal and entity-specific lifecycle hooks
OverridesReplace any CRUD operation with custom logic
Dynamic entitiesRuntime-defined resources without recompilation
Query cachingOptional IDistributedCache integration
Response cachingETag-based 304 responses, configurable Cache-Control
Bulk operationsBatch create/update/delete via /bulk endpoint
Import/ExportBulk data import/export in JSON or CSV format
Async streamingIAsyncEnumerable support via /stream endpoint
WebhooksPublish events when CRUD operations occur
Rate limitingASP.NET Core rate limiting integration
API key authenticationMachine-to-machine authentication
Audit loggingIAuditLogger for tracking all CRUD operations
Structured loggingBuilt-in ILogger integration with operation timing
MetricsOpenTelemetry-compatible counters and histograms
Distributed tracingActivity/span integration for request tracing
Health checksIHealthCheck implementations for monitoring
Schema endpointGET /api/$schema/{resource} returns JSON Schema
API reference UISwagger UI and Scalar reference over the generated OpenAPI document
Feature flagsSelectively enable/disable features with presets

Packages

PackagePurposeDownload
DataSurface.CoreContracts, attributes, and buildersNuGet Downloads
DataSurface.EFCoreEF Core CRUD service, hooks, query engineNuGet Downloads
DataSurface.DynamicRuntime metadata storage, dynamic CRUD serviceNuGet Downloads
DataSurface.HttpMinimal API endpoint mapping, query parsing, ETagsNuGet Downloads
DataSurface.AdminAdmin endpoints for managing dynamic entitiesNuGet Downloads
DataSurface.OpenApiSwashbuckle integration for typed schemasNuGet Downloads
DataSurface.ScalarScalar API reference UI (additive to Swagger)NuGet Downloads
DataSurface.Generator(Optional) Source generator for typed DTOsNuGet Downloads

Typical combinations:

  • Static only: Core + EFCore + Http
  • Dynamic only: Core + Dynamic + Http + Admin
  • Both: All of the above

Quick Start

1. Define your entity

using DataSurface.Core.Annotations;
using DataSurface.Core.Enums;

[CrudResource("users")]
public class User
{
    [CrudKey]
    public int Id { get; set; }

    [CrudField(CrudDto.Read | CrudDto.Create | CrudDto.Update, RequiredOnCreate = true)]
    public string Email { get; set; } = default!;

    [CrudField(CrudDto.Read | CrudDto.Filter | CrudDto.Sort)]
    public DateTime CreatedAt { get; set; }

    [CrudConcurrency]
    public byte[] RowVersion { get; set; } = default!;
}

2. Register services

using DataSurface.EFCore.Services;
using System.Reflection;

// Register contracts, EF Core services, and the full CRUD runtime.
// The generic overload aliases your DbContext to the base DbContext
// the CRUD services depend on.
builder.Services.AddDataSurfaceEfCore<AppDbContext>(opt =>
{
    opt.AssembliesToScan = [Assembly.GetExecutingAssembly()];
});

3. Map endpoints

using DataSurface.Http;

app.MapDataSurfaceCrud();

Result: Your API now has these endpoints:

  • GET /api/users β€” List with filtering, sorting, pagination
  • HEAD /api/users β€” Get count only (in X-Total-Count header)
  • GET /api/users/{id} β€” Get single resource
  • POST /api/users β€” Create
  • PATCH /api/users/{id} β€” Update
  • DELETE /api/users/{id} β€” Delete
  • GET /api/$schema/users β€” Get JSON Schema for resource

πŸ“š Documentation

Full documentation lives in /docs β€” start there for the complete guide, or jump straight to a section below.

Getting Started

Architecture

  • Overview β€” Module structure, key abstractions, diagram
  • Contracts β€” The ResourceContract system in depth
  • Request Lifecycle β€” How a request flows through the pipeline

Features

Reference

More

  • Benchmarks β€” Query engine performance analysis
  • Roadmap β€” Feature status and planned work

Contributing

Issues and pull requests are welcome. See the Roadmap for shipped features and what's planned next β€” open an issue with the enhancement label to suggest a feature.