Skip to content

ZibStack.NET.Dto — Alternatives

“CRUD in .NET” isn’t one library — it’s usually a stack: a mapper (AutoMapper / Mapster / Mapperly), a query DSL (Sieve / OData), a validation lib (FluentValidation), a pipeline (MediatR), a scaffolding template (OnionAPI / VS). ZibStack.NET.Dto collapses the request/response/query/mapping/endpoints surface into compile-time generation from one [CrudApi] attribute, while deliberately staying out of the mediator and sink business.

The main table below compares the four most common picks — AutoMapper, Mapperly, Sieve, OData. Additional tools (Mapster, MediatR, VS Scaffolding) are discussed in prose below.

FeatureZibStack.NET.DtoAutoMapperMapperlySieveOData
ScopeCRUD DTO + endpoints + query + mapping + JSON Merge Patchobject mappingobject mappingfilter / sort / pagingfull query protocol + endpoints
DispatchRoslyn source gen (compile time)runtime reflection + expression treesRoslyn source genruntime reflectionruntime + query translator
Price✅ MIT freeCommercial (2025 change)MIT freeMIT freeMIT free
DTOs from entity✅ auto from [CrudApi] (Create / Update / Response / Query variants)manual CreateMap<T, TDto>()manual partial classn/aauto-project
JSON Merge Patch / partial updatePatchField<T> tri-state (null / missing / set)partial via PATCH
Filter / sort / paging DSL[QueryDto] + filter/sort DSLn/an/aSieve(CanSort=true)✅ heavy OData protocol
Minimal API endpoint generationMap{Entity}Endpoints(...)❌ (controller only)
[ApiController] generation✅ both Minimal API and Controller styles
Sensitive / response-filtering attrs[DtoIgnore(target)], [DtoOnly], [ListIgnore], [QueryIgnore][Select]
External-type configurationIDtoConfigurator fluent + [CreateDtoFor] / [UpdateDtoFor]Profilespartial classattributeEDM builder
Runtime reflection❌ zero reflection✅ heavy
Output visibility✅ generated .g.cs in obj/ on buildobscure (runtime)✅ visible partialsobscureobscure
Regenerates on source change✅ on every build, no driftn/a✅ on buildn/an/a

Other tools worth mentioning:

  • Mapster — mapping-only; runtime with optional Mapster.Tool codegen. Active but development stalled in 2025; MIT free. Good pick if you need just mapping and don’t want AutoMapper’s new commercial license.
  • MediatR — request/response pipeline with behaviors (validation, logging, caching). Went commercial in 2025. Solves a different problem than Dto — cross-cutting pipelines for any request, not just CRUD. Use both if you need pipelines on top of CRUD.
  • VS Scaffolding / OnionAPI templates — drop code once, then you own it. No regeneration; the moment your entity changes, you maintain the scaffold by hand.

ZibStack.NET.Dto isn’t a mediator and doesn’t try to be — MediatR-style cross-cutting pipelines (pre/post handlers, notifications, dispatching commands by type) still belong in MediatR or a hand-rolled equivalent. ZibStack.NET.Dto only handles the per-entity CRUD surface.

For mapping, the generated Create/Update/Response converters are opinionated — they map by property name, respect [DtoIgnore] / [DtoOnly] filtering, and support [Flatten] for nested-to-flat mappings. Complex many-to-one / recursive mappings that AutoMapper’s ForMember(…) handles are outside Dto’s scope; write a manual mapper on top (as a partial method).

Greenfield project or a fresh CRUD resource where the usual stack (AutoMapper + MediatR + Sieve + hand-written endpoints + VS scaffold) feels like a lot of boilerplate for what boils down to “REST over an entity.” One [CrudApi] attribute generates every variant DTO, every endpoint, the query DSL, and the mapping layer. AOT-friendly, zero-reflection, visible .g.cs output. PatchField<T> is the JSON Merge Patch tri-state model that nobody else in this space implements.

  • MediatR — you need the full request/response pipeline with behaviors (validation, logging, caching) dispatched by type across hundreds of commands/queries, not just CRUD.
  • Mapperly — pure object-to-object mapping, no endpoints, no query — and you want a source-generated mapper without the opinion about what a “CRUD DTO” looks like.
  • AutoMapper — existing codebase already on it, or you need its complex ForMember / Profile mappings the built-in generator won’t synthesize.
  • OData — you need the full OData protocol ($expand, $select, $orderby, $count) on the wire, with clients that speak it natively.
  • Sieve — you just want filter/sort/paging on existing endpoints, no DTO generation.