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.
Rename, move, add, remove, type change - VersionKit's attribute surface covers five kinds of schema evolution. This part walks the whole declarative API, the merge rules behind stacked attributes, and what the attributes deliberately refuse to express. Part 2 of the Entity Versioning with VersionKit series.
One naming class in DShop.Common decides every exchange, routing key and queue in the estate - the message topology is a string-formatting problem.
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.
Header, route, subdomain or query string: how the platform decides who is asking before it touches any data, how tenant identity becomes a connection string and a schema, and where the caching knives are hidden.
DShop.Common is the shared library nine microservices were built on - and the rough draft of a framework its authors later shipped as Convey.
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.
A 40-line entry script that is entirely commented out, thirty-one views carrying inline script blocks, a 2,904-line page file, and @section as the only architecture - the addendum's closing ledger.
The honest ledger for the whole estate - what coordinating through tables actually cost, what genuinely earned its keep, and what I would reach for now instead of using the database as a message bus.
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.
A sequel stylesheet four times the size of the original, a sheet per screen, six copied tour themes, and a modal built as one inline HTML string - what a naming convention and a tokens file actually earn.
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.
Four pipelines run dotnet test against projects with no tests and pass every time, the shared model ships as committed .nupkg files in a folder, one executable has no pipeline at all, and a DLL with no source hides an algorithm pasted inline elsewhere.
The platform bundled a client-side validation framework - one file of it twice - and wired none of it, hand-stitching every real check inside modal callbacks with manual error classes and keyup character counters.
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.
The same dashboard KPI is computed by three different formulas across role-variant procedures, rendered on a gauge with a sibling metric quietly deleted - and the fact table beneath it is an accidental Kimball star nobody designed.
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.
The business month runs the 16th to the 15th, so a year-overview proc carries twelve correlated subqueries, five-day-capped weeks, time averaged through float casts and contractor filters that drift by a digit between copies.
The honest retrospective - copy-paste as a pattern, zero tests, PII in telemetry and what employee-monitoring data demands, destructive error handling, and the handful of decisions that genuinely earned their keep.
One hierarchy, three implementations - a recursive CTE, a view that calls a scalar function on every row, and a whole family of tree procs - plus a relationship flag that is a decimal number pretending to be binary.
AutoMapper referenced and never mapped, a ghost OpenXml import, a full-framework MVC5 reference in a Core app, Hangfire packages with no jobs, unconfigured Serilog sinks, and an unregistered middleware - what unused packages cost even when nothing calls them.
Thirty-eight tables, fourteen foreign keys, none on the tables that need them - plus a shipped SSMS template index, auto-tuning suggestions accepted blind, three-state booleans and a demo mode that mutates production master data.
One class bridging the legacy ADAL KeyVaultClient and the modern SecretClient, three coexisting secret postures - managed identity, a service-principal password in config, a committed key file - and a migration frozen mid-flight.
The same database solves the same sortable-paging problem twice - once by concatenating user input straight into EXEC, once with a CASE whitelist, QUOTENAME and sp_executesql. A side-by-side of the wrong and right answer.
HTML templates seeded in OnModelCreating, a reflection mini-language that resolves hash-brace tokens against a model, a Gmail-versus-SMTP environment branch, Cc quietly added into To, and string.Format run over raw HTML.
UTC timers, IST badge gates, DateTime.Now in one executable and UtcNow in the next, columns that record neither - how a system whose entire product is timestamps got away with never deciding what time it is.