Nefarius.HttpClient.LiteDbCache 2.5.0

Prefix Reserved
dotnet add package Nefarius.HttpClient.LiteDbCache --version 2.5.0
                    
NuGet\Install-Package Nefarius.HttpClient.LiteDbCache -Version 2.5.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nefarius.HttpClient.LiteDbCache" Version="2.5.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nefarius.HttpClient.LiteDbCache" Version="2.5.0" />
                    
Directory.Packages.props
<PackageReference Include="Nefarius.HttpClient.LiteDbCache" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nefarius.HttpClient.LiteDbCache --version 2.5.0
                    
#r "nuget: Nefarius.HttpClient.LiteDbCache, 2.5.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nefarius.HttpClient.LiteDbCache@2.5.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nefarius.HttpClient.LiteDbCache&version=2.5.0
                    
Install as a Cake Addin
#tool nuget:?package=Nefarius.HttpClient.LiteDbCache&version=2.5.0
                    
Install as a Cake Tool

Nefarius.HttpClient.LiteDbCache

GitHub Workflow Status Requirements Nuget Nuget

Adds disk-based response caching to HttpClient named instances using LiteDB.

Motivation

Sometimes a response from a remote HTTP service doesn't change frequently and fetching it again multiple times within a certain time span is wasteful and puts unnecessary delays on the caller. Offline caching to the rescue! However, manually storing and fetching responses gets verbose and complex fast, why not hide that complexity away and let IHttpClientFactory deal with it behind the scenes?

This library provides the extension method AddLiteDbCache you can chain your named HTTP client call with and specify an embedded database location to use for offline caching, no other code changes are required.

Why not use IMemoryCache?

The goal of the cache is to survive application/service restarts.

Why not use IDistributedCache?

This library is aimed at end-user clients where you wish to drag in as little dependency on 3rd party services as possible. An embedded database sitting in some folder does the trick there perfectly. It's usually not the brightest idea to require spinning up a Redis or MongoDB instance on a client's machine just to get some basic persisted storage capabilities. 😉

Features

  • Each named HTTP client gets its own backing cache database instance which is kept exclusively open by default throughout application lifetime for performance benefits.
  • Cached entries expiration (and exclusion) can be configured globally per named instance or overridden per request.
  • Upstream Cache-Control / Expires headers can optionally bound or skip storage.
  • Expired entries can optionally be served when a refresh fails (stale-if-error / offline fallback).

How to use

Register one or more named HTTP clients with AddLiteDbCache. This example snippet registers a cached client that will query your public IP address using https://ifconfig.me/ and cache the response for 10 minutes to a local embedded database instance:

builder.Services.AddHttpClient("ifconfig", cfg =>
{
    cfg.BaseAddress = new Uri("https://ifconfig.me");
    
}).AddLiteDbCache(options =>
{
    // note: ensure that the path given already exists or you'll get a runtime exception
    options.ConnectionString = @"C:\Temp\ifconfig.db";
    options.CollectionName = "ifconfig-response-cache";
    options.EntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
});

This cached named client can now be consumed like any other HttpClient wherever needed:

HttpClient client = _clientFactory.CreateClient("ifconfig");

HttpResponseMessage result = await client.GetAsync("/", ct);

string? publicIP = await result.Content.ReadAsStringAsync(ct);

If a cached entry exists, the response (headers, body content etc.) will be pulled and returned from the local database and no remote web request will be issued until the cache entry expires.

Honour upstream cache headers

Set HonorCacheControl to let the remote Cache-Control and Expires headers influence storage. This stays off by default so existing clients keep their configured TTLs.

}).AddLiteDbCache(options =>
{
    options.ConnectionString = @"C:\Temp\ifconfig.db";
    options.CollectionName = "ifconfig-response-cache";
    options.EntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
    options.EntryOptions.HonorCacheControl = true;
});

When enabled:

  • Cache-Control: no-store and no-cache skip caching entirely (no-cache is treated as a bypass, not as HTTP revalidation with ETag / Last-Modified).
  • max-age (minus Age / apparent age from Date) is an upper bound on how long the entry may be reused.
  • Expires is used only when max-age is absent.
  • Responses that are already stale on arrival are not stored.
  • Local expiration options still apply; the earliest expiry wins.

Per-request cache options

Attach a LiteDbCacheEntryOptions instance to override the named client's defaults for that call only. Convenience overloads exist for GET, HEAD, DELETE, POST, PUT, and PATCH (the verbs the cache engine currently keys), including the common System.Net.Http.Json helpers:

LiteDbCacheEntryOptions cache = new()
{
    HonorCacheControl = true,
    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(2)
};

HttpResponseMessage result = await client.GetAsync("/", cache, ct);

IpResponse? ip = await client.GetFromJsonAsync<IpResponse>("/", cache, ct);

You can still attach options to an existing HttpRequestMessage when you need custom methods, headers, or completion behavior:

HttpRequestMessage request = new(HttpMethod.Get, "/");
request.Headers.Accept.Add(new("application/json"));
HttpResponseMessage result = await client.SendAsync(request, cache, ct);

Serve stale content when refresh fails

By default an expired entry is discarded before the remote call. Set ServeStaleOnError to keep it and return that snapshot when the refresh fails (transport error, timeout, or a non-success status). Successful refreshes replace the entry as usual. Caller cancellation is not treated as a failure.

options.EntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
options.EntryOptions.ServeStaleOnError = true;

Stale fallbacks still report IsCached() and also IsStale(), and include the X-LiteDb-Cache-Stale header.

Advanced usage

Cache database access

Inject the ILiteDbCacheDatabaseInstances interface to get access to the LiteDatabase instances and other database management methods (cache purge and alike).

Documentation

Link to API docs.

Sources & 3rd party credits

This library benefits from these awesome projects ❤ (appearance in no special order):

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.5.0 37 9/11/2026
2.4.1 1,749 1/24/2025
2.4.0 241 1/22/2025
2.3.0 629 11/20/2024
2.3.0-pre001 148 11/20/2024
2.2.2 447 7/9/2024
2.2.1 266 6/12/2024
2.2.0 406 6/12/2024
2.1.4 224 6/7/2024
2.1.3 222 6/7/2024
2.1.2 533 3/5/2024
2.1.1 209 2/27/2024
2.1.0-pre 198 2/24/2024
2.0.6 231 2/23/2024
2.0.5-pre 180 2/23/2024
2.0.4-pre 212 2/23/2024
1.9.0 234 2/22/2024
1.8.0 263 2/22/2024
1.7.1 220 2/21/2024
Loading failed