-
-
Notifications
You must be signed in to change notification settings - Fork 1
ETag and If‐None‐Match
Ieuan Walker edited this page Jun 25, 2026
·
3 revisions
ETags enable conditional requests: the client can send If-None-Match and the server can respond 304 Not Modified when the representation hasn’t changed.
This is complementary to output caching:
- Output caching can avoid re-executing endpoint handlers on the server.
- ETags can avoid re-downloading content to the client.
- Server returns a response with an
ETagheader. - Client caches the response and sends
If-None-Match: <etag>on subsequent requests. - If unchanged, server returns
304 Not Modifiedwith no body.
An ETag should represent the current state of the resource, and should be deterministic so the same etag is generated if the data is unchanged. This is because if some clients don't use ETags then they will be hitting the api logic each time, so if the etag generation logic deterministic it wont create a new tag and invalidate cached data of clients that use Etags
Common sources:
- Deterministic ETag based on the serialized object content
- A convenient extension method has been created to generate an etag based on an object - GenerateEtag
- A row-version / concurrency token
- A last-updated timestamp
A simple example using the provided extension method:
public class GetItemEndpoint : IEndpointWithoutRequest<ItemModel>
{
readonly IHttpContextAccessor _context;
public GetItemEndpoint (IHttpContextAccessor context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public static void Configure(RouteHandlerBuilder builder)
{
builder
.Get("/items/{id:int}")
.CacheOutput(TimeSpan.FromMinutes(5));
}
public async Task<ItemModel> Handle(CancellationToken ct)
{
ItemModel item = new { Id = 1, Name = "Example", UpdatedAt = new DateTime(1996, 06, 08) };
_context.HttpContext?.Response.Headers.ETag = item.GenerateEtag();
return item;
}
}Notes:
- ETag values are typically quoted
Getting Started
Endpoints
- Endpoint interfaces
- HTTP verbs
- Request binding
- Grouping
- Returning multiple different responses
- Dependency injection
Validation
- Setup
- Data annotations
- Fluent validation
- Disabling validation
- Manually return BadRequest with validation errors
Output Caching
OpenAPI & Documentation