A small ASP.NET Core library that measures how long requests take and exposes the result on the response.
There are two things you get out of the box:
- A middleware that records the total time spent serving a request.
- A filter that records the time spent inside a single action or minimal API endpoint.
Both write their result to the response so the client (or your browser dev tools) can read it without any extra plumbing.
| Header | Source | Meaning |
|---|---|---|
X-Response-Time |
middleware | Total time the request spent in the pipeline, in milliseconds. |
X-Action-Response-Time |
[ResponseTime] attribute or .WithResponseTime() filter |
Time spent inside the marked action / endpoint. |
Server-Timing |
both | Standard W3C header. Each contributor adds a metric (total, action). Browsers render this in the Network tab. |
The X-* names are kept for backward compatibility. New consumers should prefer Server-Timing because it is a documented standard and shows up in dev tools without a custom extension.
netstandard2.0, net5.0, net6.0, net7.0, net8.0, net9.0. The minimal API endpoint filter is only compiled for net7.0 and above (it relies on IEndpointFilter).
From NuGet:
Install-Package RzR.Web.Middleware.ResponseTime
Or pin a specific version:
Install-Package RzR.Web.Middleware.ResponseTime -Version x.x.x.x
Register the services and add the middleware. That is enough to start emitting X-Response-Time and Server-Timing on every response.
services.AddResponseTime();
// ...
app.UseResponseTime();For per-action timing on an MVC controller, decorate the action (or the controller) with [ResponseTime]:
[HttpGet]
[ResponseTime]
public IEnumerable<WeatherForecast> Get() => ...;For minimal APIs, chain .WithResponseTime() on the endpoint or group:
app.MapGet("/weather", () => Results.Ok(forecast))
.WithResponseTime();
var api = app.MapGroup("/api").WithResponseTime();
api.MapGet("/users", GetUsers);Pass a callback to AddResponseTime to override defaults:
services.AddResponseTime(o =>
{
o.TotalHeaderName = "X-Total-Time"; // or null/empty to suppress
o.ActionHeaderName = "X-Action-Time";
o.EmitServerTiming = true;
o.DurationFormat = "0.0"; // e.g. "12.3ms"
o.Filter = ctx => !ctx.Request.Path.StartsWithSegments("/health");
});See ResponseTimeOptions for the full list of settings.