{"id":11498,"date":"2025-08-17T20:50:38","date_gmt":"2025-08-17T20:50:38","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=11498"},"modified":"2025-08-17T20:50:38","modified_gmt":"2025-08-17T20:50:38","slug":"output-caching-in-asp-net-core","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/output-caching-in-asp-net-core\/","title":{"rendered":"Output caching in ASP.NET core"},"content":{"rendered":"<p>Output caching can be used on your endpoints so that if the same request comes into your endpoint within an &#8220;cache expiry&#8221; time then the endpoint will not get called and the stored\/cached response from a previous call will be returned.<\/p>\n<p>To make that clearer the endpoint&#8217;s method will NOT be called, the response is cached and hence returned via the ASP.NET middleware.<\/p>\n<p>This is particularly useful for static or semi-static context.<\/p>\n<p>Out of the box, the OutputCache can handle caching for different query parameters and routes can be easily set up to handle caching.<\/p>\n<p>I&#8217;m going to setup the output cache to use Redis<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nbuilder.AddRedisOutputCache(&quot;cache&quot;);\r\n\r\nbuilder.Services.AddOutputCache(options =&gt;\r\n{\r\n    options.AddPolicy(&quot;ShortCache&quot;, builder =&gt; builder.Expire(TimeSpan.FromSeconds(10)));\r\n});\r\n<\/pre>\n<p>Now from a minimal API endpoint we can apply output caching using <em>CacheOutput<\/em> as below <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/cached\/{id}&quot;, (int id) =&gt; new\r\n    {\r\n        Message = $&quot;Output Cache {id}&quot;,\r\n        Timestamp = DateTime.UtcNow\r\n    })\r\n    .CacheOutput(c =&gt; c.VaryByValue(\r\n        ctx =&gt; new KeyValuePair&lt;string, string&gt;(&quot;id&quot;, ctx.Request.RouteValues&#x5B;&quot;id&quot;]?.ToString() ?? string.Empty)));\r\n<\/pre>\n<p>Each unique id gets its own cached response.<\/p>\n<p>The endpoint is only executed once per id within the cache duration.<br \/>\n&#8211; The VaryByValue method lets you define custom cache keys based on route values, headers, or query strings.<br \/>\n&#8211; Without this, \/cache\/1 and \/cache\/2 might share a cache entry or overwrite each other depending on the default key behavior.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\napp.MapGet(&quot;\/cached-query&quot;, (int id) =&gt; new\r\n    {\r\n        Message = $&quot;Output Cache {id}&quot;,\r\n        Timestamp = DateTime.UtcNow\r\n    })\r\n    .CacheOutput();\r\n<\/pre>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\napp.UseOutputCache();\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Output caching can be used on your endpoints so that if the same request comes into your endpoint within an &#8220;cache expiry&#8221; time then the endpoint will not get called and the stored\/cached response from a previous call will be returned. To make that clearer the endpoint&#8217;s method will NOT be called, the response is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[200,79],"tags":[],"class_list":["post-11498","post","type-post","status-publish","format-standard","hentry","category-asp-net-core","category-caching"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11498","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=11498"}],"version-history":[{"count":3,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11498\/revisions"}],"predecessor-version":[{"id":11641,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11498\/revisions\/11641"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=11498"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=11498"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=11498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}