Document Management in .NET: Renditions & Secure Links
Storing an uploaded file is the easy 20%. The other 80% — thumbnails, typed metadata, and secure expiring share links — is what every team reinvents badly. Here is how Granit solves all three.
Storing an uploaded file is the easy 20%. The other 80% — thumbnails, typed metadata, and secure expiring share links — is what every team reinvents badly. Here is how Granit solves all three.
Regex-parsing an LLM's prose reply breaks the day the model rephrases. Ask for a typed object instead — your C# type becomes a JSON schema the model must satisfy.
You don't need a vector database vendor to ship retrieval-augmented generation in .NET. Here's semantic search end to end — embeddings, pgvector, similarity search, and a grounded LLM answer — on the Postgres you already run.
Finance wants the numbers in Power BI, refreshed daily — again. Instead of hand-building another CSV export, expose a governed OData v4 feed from your .NET app and let Power BI pull live data through the same security pipeline as your grids.
Tax is where naive SaaS billing quietly breaks. Here is how to get EU cross-border VAT, US sales tax, and historical invoice integrity right in a .NET SaaS — with real Granit code.
Recurring billing looks like a cron job that charges a card once a month. Then a customer upgrades on day 20, a card declines, and someone overpays. Here is how the hard parts actually work in .NET.
Recurring EU billing does not require a US payment gateway. Here is how a provider-agnostic design collects a finalized invoice over SEPA — no Stripe, no Mollie, no Cloud Act exposure — and stays retry-safe end to end.
You do not need a metering vendor to bill on usage. Here is the full in-process pipeline — event ingest, idempotent dedupe, watermark rollup, quota alerts, invoice — built on Granit.Metering and Granit.Invoicing.
Row-level, schema-per-tenant, or database-per-tenant? Here is how the three isolation strategies trade off — and how Granit gives you the safe default plus a mechanical path to strict isolation when a customer demands it.
A stolen session cookie passes every auth check you have. The signal that something is wrong isn't in the token — it's in the pattern: a login from Brussels, then São Paulo, eight minutes later. Here's how to catch it in .NET.
FAPI 2.0 is the security profile required by Open Banking, healthcare APIs, and government identity systems. Most teams think conformance takes months. Granit's OpenIddict server, BFF, and resource server implement every requirement — one flag enables the full profile.
Rate limiting and bulkhead isolation are often mentioned together but solve different problems. This deep-dive explains both patterns, shows where they fail without the other, and walks through Granit's dual enforcement model — Redis-backed quotas for the time axis, concurrency limiters for the thread axis.
A server restart between your database commit and your HTTP POST drops the event forever. The fix is the transactional outbox pattern — persist the event in the same transaction as your data, relay it asynchronously, retry on failure. Here is how Granit.Webhooks implements it end-to-end.
Shipping to the EU means opt-in. Shipping to California means opt-out. Shipping to Brazil means opt-in again. Most teams hardcode GDPR and call it done. Here is how Granit resolves the right consent model automatically — per tenant, per request, without a line of conditional logic in your application code.
Your strict Content Security Policy breaks the moment one ASP.NET Core route serves HTML — Scalar, an admin page, a Keycloak iframe. The usual band-aid weakens every other endpoint. Granit's per-endpoint CSP composition keeps strict defaults strict and lets the package that mounts the UI declare its own relaxation.
Stop sprinkling CreatedAt assignments across repositories and IsDeleted = false across queries. Five interceptors and one global filter make compliance the default — and ExecuteUpdate the only thing left to watch for.
Two-tier caches are fast, but cross-pod invalidation is the part everyone gets wrong. Here is how the L1 + L2 + backplane pattern works, and how Granit wires it up with Redis.
MediatR is in-process only — no outbox, no retry, no transport. Wolverine is the CQRS bus most teams actually need. Here is how Granit uses it.
.NET 10 makes SSE a first-class citizen with TypedResults.ServerSentEvents(). Build a complete real-time notification stream from HTTP primitives to React hooks — no WebSocket plumbing required.
Stop returning bare strings from your .NET APIs. RFC 7807 Problem Details is the standard for error responses — here is why it matters, what the spec actually says, and how Granit enforces it with zero boilerplate.
SSE, SignalR, or raw WebSockets? A practical decision framework for .NET real-time applications, with protocol deep-dives, trade-offs, and ready-to-use Granit code samples for each transport.
Enterprise customers ask for a SOC 2 Type 2 report before signing. Here is how Granit's modules map to the five Trust Service Criteria — and what the framework cannot replace.
NIS 2 is now law across the EU. Here is what it requires from your .NET stack — and how Granit's supply chain pipeline and embedded security modules cover the key obligations out of the box.
Physical deletion breaks audit trails, conflicts with legal holds, and fails on append-only systems. Crypto-shredding solves all three: destroy the key, and the ciphertext becomes random noise. Here is how Granit implements it.