An Attendance Platform in ASP.NET Core
Badge gates, WFH timers and shift allowances - the shape of a seven-project intranet attendance platform, the onion it almost is, and the roadmap for fourteen more parts.
221 articles filed under this topic.
Badge gates, WFH timers and shift allowances - the shape of a seven-project intranet attendance platform, the onion it almost is, and the roadmap for fourteen more parts.
A 6.23 MB JavaScript bundle loaded on every page, a manifest that minifies CSS but concatenates JS, and two copies of jQuery - the first of four frontend chapters the attendance series skipped.
Hard deletes destroy the audit trail; soft deletes clutter live tables forever. Introducing ArchiveKit, a .NET library that intercepts deletions and stores immutable archive snapshots with TTL policies and cascade archiving.
Unit tests mock what you assume, end-to-end tests tell you too late - consumer-driven contract testing closes the gap, and a small open-source .NET library called Pactify is the clearest way I know to learn how it works. Part 1 of a series.
The 22-part Convey series read the packages; it never once walked the sample system that ships with them. Opening the missing chapters with the trip an order takes through Orders, Pricing and Deliveries — and what the samples quietly teach that no package README does.
Rename a property, change a type, ship the release - and every payload you stored last year stops deserialising. Introducing VersionKit, a .NET library that declares schema history as attributes and migrates old data on read.
Controllers grow sideways and Minimal APIs grow into soup. FastEndpoints bets on a third shape - one class per endpoint - and this series reads its source to see how the bet is implemented. Part 1 of FastEndpoints in Depth.
Seventeen parts of reading FastEndpoints and the series never once mentioned mappers - the entity-translation layer half the endpoint base classes exist to serve. The Missing Chapters opens with the biggest gap: where mappers live, how they are found, and why they are secretly singletons. Part 1 of FastEndpoints — The Missing Chapters.
Every team's fifth microservice ships with the same four hundred lines of bootstrap code as the first four. Opening a deep-dive series on Convey, the open-source .NET toolkit that turned that boilerplate into thirty composable packages.
Database-per-tenant, schema-per-tenant, or packed into a shared database? Kicking off a series on building a multi-tenant platform where one EF Core codebase supports all three isolation strategies behind a single control plane.
DShop is one e-commerce shop stamped out as nine microservices over RabbitMQ - this series reads the real source to see how the topology holds together and where it drifts. Part 1 of Nine Services and a Message Bus.
A guided tour of FeedR, DevMentors' open-source .NET microservices sample for real-time data feeds - six services, Redis pub/sub, Apache Pulsar and a gRPC stream, and the two-tier eventing model that makes it worth reading. Part 1 of a source-level deep dive.
Split one database into five services and the transaction you deleted does not disappear - it goes feral. On sagas, compensation, process managers, and Chronicle, the small open-source .NET library this series reads line by line.
Dozens of Azure Functions and Logic Apps need each other's URLs and keys, and there is no Kubernetes, no sidecar, no mesh to hand them out. How a small .NET library turned one Key Vault and a naming convention into a working discovery layer - the consumer side of a registry made of secrets. Part 1 of a new series.
Convey sells a microservice in thirty lines, and Pacco builds ten of them - this series reads the whole estate to price what the framework compresses and what every consumer pays for by hand. Part 1 of The Convey Consumer Tax.
Five executables, zero queues - how an attendance platform coordinated a web app, three Azure Functions and a console job through one SQL database, and what that choice bought and cost. Part 1 of the series.
DShop.Common is the shared library nine microservices were built on - and the rough draft of a framework its authors later shipped as Convey.
Nobody in Pacco approves an order - a vehicle reservation does. A tour of DevMentors' parcel-delivery estate, the domain it models, and the fifteen-part series it earns.
Wire four services into a .NET Aspire AppHost and run it once - traces, logs, health and environment variables for the whole system, before you have written a single line of observability code. Part 1 of a series on Aspire in production.
SaveChanges is already a transaction, until it isn't enough. A tour of explicit transactions, TransactionScope, execution strategies and the failure modes that only show up in production.
Every stored payload carries a __version stamp; every read walks it up one step at a time. This part dissects VersionKit's lazy migration pipeline - the MigrationRunner API, the JsonElement traps System.Text.Json sets for dictionary code, and reading history on purpose. Part 4 of the Entity Versioning with VersionKit series.
An audit of the messaging patterns DShop.Common leaves out - no outbox, no inbox, no consumed dead-letter - and how each absence became a Convey package.
Chronicle's entire programming model is Saga<TData>, ISagaStartAction, and ISagaAction. Building a full order-fulfilment saga to learn what Complete() promises, what Reject() actually does, and why a saga can have more than one beginning.
AddFastEndpoints never asks you to register an endpoint. Reading the discovery code shows how a reflection scan over five interfaces becomes a validated endpoint catalogue - and which mistakes it turns into startup crashes on purpose. Part 2 of FastEndpoints in Depth.
Operations drives an order from created to approved across three services, and rolls it back when a step fails - a textbook process manager with compensation, read from the real Chronicle-backed source. Part 6 of Nine Services and a Message Bus.
You built schema-aware migrations, provisioned tenant A, and everything worked. Tenant B provisions without a single error — and gets no tables. EF Core's model cache is the silent culprit, and IModelCacheKeyFactory is the three-field fix.
A complete broker-requeue retry implementation sits in DShop.Common's subscriber, fully written and never called - and its comment explains exactly why.
The resolution path of a Key Vault-backed discovery client - three fail-fast environment variables, DefaultAzureCredential with a user-assigned managed identity, a name composed as service-plus-environment, a tolerant JSON parser, and a process-lifetime cache with a bug I shipped and honest trade-offs I chose. Part 2 of Service Discovery Without a Service Mesh.
DShop moves data between services two opposite ways - one rebuilds a local replica from the event payload, the other treats the event as a doorbell and fetches over HTTP - and the estate runs both at once. Part 5 of Nine Services and a Message Bus.
Unit tests mock what you assume, end-to-end tests tell you too late - consumer-driven contract testing closes the gap, and a small open-source .NET library called Pactify is the clearest way I know to learn how it works. Part 1 of a series.
Why ArchiveKit's inline archive limit defaults to exactly 14, how EF Core's MaxBatchSize turns archiving into arithmetic, and an honest inventory of every deletion path the interceptor cannot see - synchronous saves, ExecuteDelete, and raw SQL. Part 3 of the Archive-on-Delete with ArchiveKit series.
DShop.Common decides a message's fate from the type of exception a handler throws - domain failures become events, infrastructure failures get retried.
A guided tour of FeedR, DevMentors' open-source .NET microservices sample for real-time data feeds - six services, Redis pub/sub, Apache Pulsar and a gRPC stream, and the two-tier eventing model that makes it worth reading. Part 1 of a source-level deep dive.
DShop answers the shared-kernel question twice - eight services copy every event contract locally, one references a shared package - and both answers are in the same estate with their real costs on show. Part 4 of Nine Services and a Message Bus.
Every team's fifth microservice ships with the same four hundred lines of bootstrap code as the first four. Opening a deep-dive series on Convey, the open-source .NET toolkit that turned that boilerplate into thirty composable packages.
At startup VersionKit reflects over your model assembly and compiles property attributes into an executable pipeline - one migration step per version pair, five operation types, all of them deliberately idempotent. Part 3 of the Entity Versioning with VersionKit series.
DShop.Common's correlation context threads request identity through every message hop - and a long positional argument list quietly transposes half its fields.
Split one database into five services and the transaction you deleted does not disappear - it goes feral. On sagas, compensation, process managers, and Chronicle, the small open-source .NET library this series reads line by line.
Controllers grow sideways and Minimal APIs grow into soup. FastEndpoints bets on a third shape - one class per endpoint - and this series reads its source to see how the bet is implemented. Part 1 of FastEndpoints in Depth.
The same event is declared three times across DShop, and one copy quietly drops a field - here is the contract drift in the real source and the canonical-model cure that would have caught it. Part 3 of Nine Services and a Message Bus.
In DShop.Common a command and an event are published by identical code - the difference between them is a marker interface and a promise nothing enforces.
EF Core wants one database, one model and one migrations history table. Schema-per-tenant breaks all three assumptions. Constructor-injected migrations, a per-schema history table and a replaced IMigrationsAssembly put one migration set in charge of every tenant schema.
Dozens of Azure Functions and Logic Apps need each other's URLs and keys, and there is no Kubernetes, no sidecar, no mesh to hand them out. How a small .NET library turned one Key Vault and a naming convention into a working discovery layer - the consumer side of a registry made of secrets. Part 1 of a new series.
Nine DShop services share one skeleton stamped out by hand - and the places they quietly disagree teach more than the places they match. A drift catalogue read from the real source. Part 2 of Nine Services and a Message Bus.
The anatomy of ArchiveKit's SaveChangesInterceptor - detecting soft-deleted entities in the change tracker, building archive rows with zero extra database reads, and the one line of state-flip ordering that keeps EF from cascade-deleting the archive you just wrote. Part 2 of the Archive-on-Delete with ArchiveKit series.