liveBook · Manning

Absolute expiration

As explained in Building Web APIs with ASP.NET Core

Absolute expiration is a cache policy that invalidates an entry at a fixed time or after a fixed duration.

Absolute expiration invalidates a cache entry at a fixed time or after a fixed duration. A board-game API can cache each filtered result for 30 seconds, then query EF Core again. section 8.3.3

Apply absolute expiration through a cache-or-query flow:

  • Build a cache key from the request parameters so different queries receive different entries. section 8.3.3
  • Call IMemoryCache.TryGetValue with the key; return the cached board-game array when it exists. section 8.3.3
  • When the key is absent, retrieve results with EF Core and store them with an absolute expiration of 30 seconds. section 8.3.3

Filtered board-game requests

A request containing different GET parameters produces a different serialized cache key. The first request queries the database and caches its result; repeated requests can use that result until 30 seconds have elapsed. Breakpoints verify whether the cache path or database path runs. section 8.3.3

Listing 8.6 BoardGamesController’s Get method
[HttpGet(Name = "GetBoardGames")]
[ResponseCache(CacheProfileName = "Any-60")]
public async Task<RestDTO<BoardGame[]>> Get(
    [FromQuery] RequestDTO<BoardGameDTO> input)
{
  _logger.LogInformation(CustomLogEvents.BoardGamesController_Get,
      "Get method started.");
 
var query = _context.BoardGames.AsQueryable();                         #1
if (!string.IsNullOrEmpty(input.FilterQuery))                        #2
query = query.Where(b => b.Name.Contains(input.FilterQuery));
 
var recordCount = await query.CountAsync();                           #3
 
BoardGame[]? result = null;                                            #4
var cacheKey = $"{input.GetType()}-{JsonSerializer.Serialize(input)}";#5
if (!_memoryCache.TryGetValue<BoardGame[]>(cacheKey, out result))     #6
{
query = query                                                  #7
.OrderBy($"{input.SortColumn} {input.SortOrder}")
.Skip(input.PageIndex * input.PageSize)
.Take(input.PageSize);
result = await query.ToArrayAsync();
_memoryCache.Set(cacheKey, result, new TimeSpan(0, 0, 30));
}
 
  return new RestDTO<BoardGame[]>()
  {
Data = result,                                                    #8
    PageIndex = input.PageIndex,
    PageSize = input.PageSize,
    RecordCount = recordCount,
    Links = new List<LinkDTO> {
      new LinkDTO(
        Url.Action(
          null,
          "BoardGames",
          new { input.PageIndex, input.PageSize },
          Request.Scheme)!,
        "self",
        "GET"),
    }
  };
}

Inspect the complete Get method, including query construction, JSON-based cache-key creation, cache lookup, and conditional database access. section 8.3.3

How Building Web APIs with ASP.NET Core covers it

How deep it goes
Shows cache-key construction, lookup, conditional querying, and 30-second configuration without describing cache internals.
Examples
Uses filtered board-game arrays, serialized request DTOs, a 30-second lifetime, and debugger breakpoints to verify cache behavior.
What you can do after
Build it from scratch by adding parameter-specific cache keys, conditional retrieval, and absolute expiration to a controller method.
How it connects
Links absolute expiration with in-memory caching, cache keys, GET parameters, EF Core, IMemoryCache, and JSON serialization.

This explainer was generated by Manning's knowledge graph from the text of Building Web APIs with ASP.NET Core. The section links point to the parts of the book it draws on.