Skip to content

Cache Shim

The CacheShim class provides compatibility with the ASP.NET Web Forms Cache object (System.Web.Caching.Cache). It wraps ASP.NET Core's IMemoryCache so that migrated code-behind using Cache["key"] dictionary-style access compiles and functions correctly without rewriting.

Original Microsoft implementation: https://docs.microsoft.com/en-us/dotnet/api/system.web.caching.cache?view=netframework-4.8

Background

In ASP.NET Web Forms, the Cache object was available on every Page and through HttpRuntime.Cache:

// Web Forms code-behind
Cache["products"] = GetProductList();
var products = (List<Product>)Cache["products"];
Cache.Insert("config", configData, null,
    DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
Cache.Remove("products");

The Cache provided application-wide in-memory storage with optional expiration policies.

Blazor Implementation

In Blazor, application caching is handled by IMemoryCache from Microsoft.Extensions.Caching.Memory. The CacheShim bridges the gap by:

  1. Dictionary-style accessCache["key"] get/set works like Web Forms
  2. Insert() overloads — Supports no-expiry, absolute expiry, and sliding expiry
  3. Get<T>(key) — Type-safe retrieval (bonus over Web Forms)
  4. Remove(key) — Removes and returns the cached value, matching Web Forms behavior

Availability

CacheShim is automatically registered when you call AddBlazorWebFormsComponents() in Program.cs. It requires IMemoryCache:

// Program.cs — both are handled by AddBlazorWebFormsComponents()
builder.Services.AddMemoryCache();
builder.Services.AddScoped<CacheShim>();

Access it through WebFormsPageBase:

@inherits WebFormsPageBase

@code {
    protected override void OnInitialized()
    {
        base.OnInitialized();
        Cache["greeting"] = "Hello, World!";
        var greeting = (string)Cache["greeting"];
    }
}

Web Forms Usage

// Simple get/set
Cache["products"] = GetProductList();
var products = (List<Product>)Cache["products"];

// Insert with absolute expiration
Cache.Insert("config", configData, null,
    DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);

// Insert with sliding expiration
Cache.Insert("session-data", sessionData, null,
    Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20));

// Remove
object removed = Cache.Remove("products");

Blazor Usage

@inherits WebFormsPageBase

@code {
    private List<Product> _products = new();

    protected override void OnInitialized()
    {
        base.OnInitialized();

        // Dictionary-style set
        Cache["products"] = GetProductList();

        // Dictionary-style get (returns object?)
        _products = (List<Product>)Cache["products"];

        // Type-safe get (returns T? — no cast needed)
        _products = Cache.Get<List<Product>>("products");

        // Insert with absolute expiration
        Cache.Insert("config", LoadConfig(),
            DateTimeOffset.Now.AddHours(1));

        // Insert with sliding expiration
        Cache.Insert("session-data", GetSessionData(),
            TimeSpan.FromMinutes(20));

        // Remove and get the removed value
        object? removed = Cache.Remove("products");
    }

    private void RefreshProducts()
    {
        // Setting null removes the item
        Cache["products"] = null;

        // Re-populate
        Cache["products"] = GetProductList();
    }
}

API Reference

Method Signature Description
Indexer get Cache["key"]object? Gets item or null
Indexer set Cache["key"] = value Sets item; null removes it
Get<T> Cache.Get<T>(key)T? Type-safe retrieval
Insert Cache.Insert(key, value) No expiration
Insert Cache.Insert(key, value, DateTimeOffset) Absolute expiration
Insert Cache.Insert(key, value, TimeSpan) Sliding expiration
Remove Cache.Remove(key)object? Removes and returns item

Migration Path

Web Forms BWFC Shim Native Blazor
HttpRuntime.Cache["key"] Cache["key"] IMemoryCache.TryGetValue()
Cache["key"] = value Cache["key"] = value cache.Set(key, value)
Cache.Insert(key, val, null, expiry, noSliding) Cache.Insert(key, val, expiry) cache.Set(key, val, opts)
Cache.Remove(key) Cache.Remove(key) cache.Remove(key)

Moving On

CacheShim is a migration bridge. As you refactor:

  1. Replace with IMemoryCache — Inject IMemoryCache directly for full control over cache entry options
  2. Consider IDistributedCache — For multi-server deployments, switch to Redis or SQL Server distributed caching
  3. Use typed wrappers — Create service classes that encapsulate caching logic instead of sprinkling Cache["key"] throughout pages
@* Before (migration shim) *@
@inherits WebFormsPageBase
@code {
    var products = (List<Product>)Cache["products"];
    Cache.Insert("products", newList, DateTimeOffset.Now.AddHours(1));
}

@* After (native Blazor) *@
@inject IMemoryCache MemoryCache
@code {
    MemoryCache.TryGetValue("products", out List<Product> products);
    MemoryCache.Set("products", newList, DateTimeOffset.Now.AddHours(1));
}

See Also