I have a simple ASP.NET Core 8 endpoint that returns a TypedResults.File
with an ETag. First time I hit the endpoint, the file is returned 100% OK.
Second (and subsequent) times I hit the endpoint with the same instance of the browser I get an HTTP 200 OK (from disk cache) - it never makes the actual request to my localhost server.
Here's the network traffic of the 2x requests:
Request 1:
Request 2 (which grabs it from the disk cache)
I thought that if the initial request returns an ETag then the browser is "smart enough" to do subsequent requests with the ETag + "If-None-Match" request header?
This is the code that generated the File
var etag = new EntityTagHeaderValue($"\"{invoicePdfVersion}-{lastModifiedOn.Ticks}\"");
return TypedResults.File(
pdfData, // byte array of pdf data
"application/pdf", // content type
"testing", // filename
false, // enable range processing
lastModifiedOn, // DateTime when the file was last updated/modified
etag); // etag value
I understand that I could add this to the response:
context.Response.Headers.CacheControl = "no-cache";
which I think does stop the disk cache occurring but I'm not sure if this is required? Shouldn't the MS-Code for ReturnTypes.File set all the headers up correctly so I don't need to do anything else?
I have some server side code which checks the ETag:
if (context.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var ifNoneMatch) &&
ifNoneMatch == etag.ToString())
{
return TypedResults.StatusCode(304); // HTTP NotModified.
}
but of course, this never gets hit.
What can I try next?
Relying on ETag to always check with the server requires that the response headers include the Cache-Control
header with the value no-cache
.
The no-cache response directive indicates that the response can be stored in caches, but the response must be validated with the origin server before each reuse, even when the cache is disconnected from the origin server.
The boldface part justifies this answer.