How to set different Cache expire times for Client and Server caches

后端 未结 3 1115
终归单人心
终归单人心 2021-02-07 16:45

I would like to have certain pages have a 10 minute Cache for clients and 24 hours for the server. The reason is if the page changes, the client will fetch the updated version w

3条回答
  •  刺人心
    刺人心 (楼主)
    2021-02-07 17:16

    Under .Net 4.5, it IS possible to have different client and server caching policies without writing custom cache providers:

    // Set the cache response expiration to 3600 seconds (use your own value here).
    HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddSeconds(3600));
    
    // Set both server and browser caching.
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);
    
    // Prevent browser's default max-age=0 header on first request
    // from invalidating the server cache on each request.
    HttpContext.Current.Response.Cache.SetValidUntilExpires(true);
    
    // Set an HTTP ETag header on the page using a random GUID.
    HttpContext.Current.Response.Cache.SetETag(System.Guid.NewGuid()
                                               .ToString().Replace("-", ""));
    
    // Set last modified time.
    HttpContext.Current.Response.Cache.SetLastModified(DateTime.UtcNow);
    
    // Now here is the critical piece that forces revalidation on each request!:
    HttpContext.Current.Response.Cache.AppendCacheExtension(
        "must-revalidate, proxy-revalidate, max-age=0");
    

    The result is that each time the page gets regenerated in the server cache, it gets a new ETag. This causes the If-None-Match request to return the full page back to the browser. If the browser's cached copy is the same as what's generated in the server cache (same ETag), the browser gets back a 304 Not Modified.

    Note that none of the cache headers I appended there in AppendCacheExtension conflict with the headers emitted by native caching. Whenever you attempt to modify the caching headers emitted by .Net caching itself, .Net will always supersede what you're trying to do. The trick is to add new non-conflicting headers, not try to change what .Net is already emitting. Most importantly, you must append the max-age header. You must NOT use .SetMaxAge(), as this also sets the maximum age of the server cached copy of the page.

    This took quite a bit of effort to figure out, but it DOES work, at least in .Net 4.5.

提交回复
热议问题