CacheWeave.Core
1.0.7
dotnet add package CacheWeave.Core --version 1.0.7
NuGet\Install-Package CacheWeave.Core -Version 1.0.7
<PackageReference Include="CacheWeave.Core" Version="1.0.7" />
<PackageVersion Include="CacheWeave.Core" Version="1.0.7" />
<PackageReference Include="CacheWeave.Core" />
paket add CacheWeave.Core --version 1.0.7
#r "nuget: CacheWeave.Core, 1.0.7"
#:package CacheWeave.Core@1.0.7
#addin nuget:?package=CacheWeave.Core&version=1.0.7
#tool nuget:?package=CacheWeave.Core&version=1.0.7

CacheWeave
Provider-agnostic, declarative response caching for ASP.NET Core.
Decorate any controller action, Razor Page handler, or Minimal API endpoint with [CacheWeave] and responses are cached automatically — no boilerplate, no manual cache key management, no stampede risk.
[HttpGet]
[CacheWeave("products", ExpirySeconds = 300)]
public async Task<IActionResult> GetProducts([FromQuery] int page = 1)
=> Ok(await _mediator.Send(new GetProductsQuery { Page = page }));
Features
| Feature | Detail |
|---|---|
| Attribute-based caching | [CacheWeave] on any MVC action, Razor Page, or Minimal API endpoint |
| Automatic key derivation | Omit the key and CacheWeave derives it from ControllerName.ActionName via reflection |
| Eviction | [CacheWeaveEvict] by exact key or prefix, post-action, with multi-attribute support |
| Stampede protection | Per-key SemaphoreSlim by default; swap for a distributed lock in multi-instance deployments |
| Conditional caching | NoCacheWhen flags — skip caching on errors, empty results, or both |
| Sliding expiry | Emulated by re-writing the entry on every cache hit |
| Route parameters | Route values (e.g. {id}) are automatically included in cache keys — framework keys (controller, action, page, area) are excluded |
| Body hashing | SHA-256 hash of the request body (or selected fields) appended to the key for POST endpoints |
| Compression | Optional GZip compression before storage — transparent to callers |
| Serializer choice | System.Text.Json (default) or Newtonsoft.Json, configured globally |
| OpenTelemetry | Hit/miss/set/eviction counters + duration histogram + Activity spans, all opt-in |
| Configurable logging | Diagnostic log level set globally — surface cache activity at Information in production |
| Programmatic API | ICacheWeaveService for GetOrSetAsync, SetAsync, InvalidateAsync |
| Fault-tolerant | All cache I/O wrapped in try/catch — Redis outage degrades to cache-miss behaviour, never a 500 |
| 7 providers | Redis, InMemory, SQLite, NCache, DynamoDB, Memcached, FASTER KV |
| Multi-target | net8.0, net9.0, net10.0 |
Quick Start
1. Install
dotnet add package CacheWeave.Core
dotnet add package CacheWeave.Redis # or CacheWeave.InMemory, etc.
2. Register
// Program.cs
builder.Services.AddCacheWeave(options =>
{
options.Serializer = CacheWeaveSerializerType.SystemTextJson; // default
options.GlobalKeyPrefix = "my-app"; // e.g. "my-app:products:list"
options.KeyVersion = "v1";
options.DefaultExpiry = TimeSpan.FromMinutes(5);
options.EnableMetrics = true;
options.DiagnosticLogLevel = LogLevel.Debug;
options.EnableCompression = false;
});
builder.Services.AddCacheWeaveRedis("localhost:6379");
// or: builder.Services.AddCacheWeaveInMemory();
// Wire [CacheWeave] and [CacheWeaveEvict] attributes into the MVC pipeline
builder.Services.AddControllers().AddCacheWeaveFilters();
3. Decorate
// Explicit key
[HttpGet]
[CacheWeave("products:list", ExpirySeconds = 300, IncludeQueryParams = true)]
public Task<IActionResult> GetAll([FromQuery] int page = 1) { ... }
// Derived key — resolves to "Products.GetAll" automatically
[HttpGet]
[CacheWeave]
public Task<IActionResult> GetAll() { ... }
// Route parameters — {id} is automatically included in the cache key
// GET /products/42 → key: "products:id=42"
[HttpGet("{id}")]
[CacheWeave("products")]
public Task<IActionResult> GetById(int id) { ... }
// Route params + query params combined
// GET /products/42/reviews?page=2 → key: "products:reviews:id=42:page=2"
[HttpGet("{id}/reviews")]
[CacheWeave("products:reviews")]
public Task<IActionResult> GetReviews(int id, [FromQuery] int page = 1) { ... }
// Exclude specific route params from the key
[HttpGet("{id}/{version}")]
[CacheWeave("products", ExcludeRouteParams = ["version"])]
public Task<IActionResult> GetById(int id, string version) { ... }
// Disable route params entirely
[HttpGet("{id}")]
[CacheWeave("products", IncludeRouteParams = false)]
public Task<IActionResult> GetById(int id) { ... }
// Minimal API with route parameters
app.MapGet("/products/{id}", (int id) => ...)
.WithCacheWeave("products");
// Minimal API — exclude specific route params
app.MapGet("/products/{id}/{version}", (int id, string version) => ...)
.WithCacheWeave("products", excludeRouteParams: ["version"]);
// Evict on mutation
[HttpPost]
[CacheWeaveEvict(Prefix = "products:")]
public Task<IActionResult> Create([FromBody] CreateProductCommand cmd) { ... }
Configuration Reference
All options are set via AddCacheWeave(options => ...):
| Property | Type | Default | Description |
|---|---|---|---|
KeySeparator |
string |
":" |
Separator between key segments |
GlobalKeyPrefix |
string? |
null |
Prepended to every key — use to namespace keys when multiple apps share one Redis |
KeyVersion |
string? |
null |
Global version injected after the base key |
DefaultExpiry |
TimeSpan? |
5 min |
TTL when not set on the attribute |
DefaultNoCacheCondition |
NoCacheCondition |
OnErrorOrEmpty |
Global skip-cache rule |
Serializer |
CacheWeaveSerializerType |
SystemTextJson |
SystemTextJson or NewtonsoftJson |
EnableCompression |
bool |
false |
GZip compress values before storage |
EnableMetrics |
bool |
true |
Emit OTel metrics and Activity spans |
DiagnosticLogLevel |
LogLevel |
Debug |
Log level for internal diagnostics |
Attribute Reference
[CacheWeave]
| Property | Type | Default | Description |
|---|---|---|---|
Key (ctor) |
string? |
null |
Base key. Omit to derive from controller/action name |
ExpirySeconds |
int |
-1 (global) |
TTL. 0 = no expiry |
IncludeRouteParams |
bool |
true |
Append sorted route params (path segments) to key |
ExcludeRouteParams |
string[] |
[] |
Route params to strip from key |
IncludeQueryParams |
bool |
true |
Append sorted query params to key |
ExcludeParams |
string[] |
[] |
Query params to strip from key |
HashBody |
bool |
false |
Append SHA-256 body hash to key |
HashBodyFields |
string[] |
[] |
Hash only these fields (empty = entire body) |
SlidingExpiry |
bool |
false |
Reset TTL on every cache hit |
NoCacheWhen |
NoCacheCondition |
OnErrorOrEmpty |
Skip caching condition |
[CacheWeaveEvict]
| Property | Type | Default | Description |
|---|---|---|---|
Key |
string? |
null |
Exact key to evict |
Prefix |
string? |
null |
Evict all keys with this prefix |
EvictOnFailure |
bool |
false |
Evict even when the action fails |
Multiple [CacheWeaveEvict] attributes are allowed on a single action.
Providers
| Package | Backing store | RemoveByPrefix |
|---|---|---|
CacheWeave.Redis |
StackExchange.Redis | Yes (SCAN + DEL) |
CacheWeave.InMemory |
IMemoryCache |
Yes (prefix scan) |
CacheWeave.SQLite |
Microsoft.Data.Sqlite | Yes (SQL LIKE) |
CacheWeave.NCache |
Alachisoft NCache | No |
CacheWeave.DynamoDB |
AWS DynamoDB | No |
CacheWeave.Memcached |
EnyimMemcachedCore | No |
CacheWeave.Faster |
Microsoft FASTER KV | No |
OpenTelemetry
builder.Services.AddOpenTelemetry()
.WithMetrics(b => b.AddCacheWeaveMeter())
.WithTracing(b => b.AddCacheWeaveInstrumentation());
Metrics emitted:
| Metric | Type | Description |
|---|---|---|
cacheweave.hits |
Counter | Cache hits |
cacheweave.misses |
Counter | Cache misses |
cacheweave.sets |
Counter | Cache writes |
cacheweave.evictions |
Counter | Explicit evictions |
cacheweave.duration |
Histogram (ms) | Time to resolve a cache operation |
All instruments carry cache.key (or cache.prefix) tags.
Programmatic API
public class ProductService(ICacheWeaveService cache)
{
public Task<Product?> GetAsync(Guid id) =>
cache.GetOrSetAsync(
$"products:{id}",
ct => _repo.FindAsync(id, ct),
expiry: TimeSpan.FromMinutes(10));
public Task InvalidateAsync(Guid id) =>
cache.InvalidateAsync($"products:{id}");
}
License
GPL-3.0 — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Newtonsoft.Json (>= 13.0.3)
-
net8.0
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.0)
- Newtonsoft.Json (>= 13.0.3)
-
net9.0
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.0)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages (8)
Showing the top 5 NuGet packages that depend on CacheWeave.Core:
| Package | Downloads |
|---|---|
|
CacheWeave.Redis
Redis provider for CacheWeave using StackExchange.Redis and Microsoft.Extensions.Caching.StackExchangeRedis. |
|
|
CacheWeave.DynamoDB
DynamoDB provider for CacheWeave using AWSSDK.DynamoDBv2. |
|
|
CacheWeave.InMemory
In-memory provider for CacheWeave using Microsoft.Extensions.Caching.Memory. |
|
|
CacheWeave.Memcached
Memcached provider for CacheWeave using EnyimMemcachedCore. |
|
|
CacheWeave.NCache
NCache provider for CacheWeave using Alachisoft.NCache.SDK. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Merge pull request #11 from teghoz/develop
release: v1.0.7 — fix README rendering on nuget.org