# Response Caching

Response caching reduces the number of requests a client or proxy makes to a web server. See the Microsoft documentation for details of [Response caching in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-6.0) and how to implement the [Response Caching Middleware](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-6.0).

{% hint style="info" %}
Response caching controls `Cache-Control` HTTP headers. These headers tell browsers and proxies to cache the response, but the server still processes every request that reaches it.

For **server-side** caching that avoids re-executing the Razor rendering pipeline entirely, see the [Website Output Caching](https://docs.umbraco.com/umbraco-cms/reference/website-output-caching) article.
{% endhint %}

## Modify the `Cache-Control` header for Static Files

Example class to allow the modification of the `Cache-Control` header for static assets by file extension, but excluding Umbraco BackOffice assets.

```csharp
using System.IO;
using System;
using System.Collections.Generic;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Http.Headers;
using Microsoft.Net.Http.Headers;

using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment;

namespace Umbraco.Docs.Samples.Web.Tutorials;

public class ConfigureStaticFileOptions : IConfigureOptions<StaticFileOptions>
{
    // These are the extensions of the file types we want to cache (add and remove as you see fit)
    private static readonly HashSet<string> _cachedFileExtensions = new(StringComparer.OrdinalIgnoreCase)
    {
        ".ico",
        ".css",
        ".js",
        ".svg",
        ".woff2",
        ".jpg"
    };

    private readonly string _backOfficePath;

    public ConfigureStaticFileOptions(IOptions<GlobalSettings> globalSettings, IHostingEnvironment hostingEnvironment)
        => _backOfficePath = hostingEnvironment.GetBackOfficePath();

    public void Configure(StaticFileOptions options)
        => options.OnPrepareResponse = ctx =>
        {
            // Exclude Umbraco backoffice assets
            if (ctx.Context.Request.Path.StartsWithSegments(_backOfficePath))
            {
                return;
            }

            // Set headers for specific file extensions
            var fileExtension = Path.GetExtension(ctx.File.Name);
            if (_cachedFileExtensions.Contains(fileExtension))
            {
                ResponseHeaders headers = ctx.Context.Response.GetTypedHeaders();

                // Update or set Cache-Control header
                CacheControlHeaderValue cacheControl = headers.CacheControl ?? new CacheControlHeaderValue();
                cacheControl.Public = true;
                cacheControl.MaxAge = TimeSpan.FromDays(365);
                headers.CacheControl = cacheControl;
            }
        };
}
```

Register the service in `Program.cs`

```csharp
builder.CreateUmbracoBuilder()
    .AddBackOffice()
    .AddWebsite()
    .AddDeliveryApi()
    .AddComposers()
    .Build();

builder.Services.AddTransient<IConfigureOptions<StaticFileOptions>, ConfigureStaticFileOptions>();
```

## Modify the `Cache-Control` header for ImageSharp.Web

For setting `Cache-Control` max-age header for images processed by the ImageSharp middleware, you can set the `Umbraco:CMS:Imaging:Cache:BrowserMaxAge` setting.

See the [Images Settings](https://docs.umbraco.com/umbraco-cms/reference/configuration/imagingsettings) article for more information.

## Add the `Cache-Control` header for rendering using the [ResponseCache attribute](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-6.0#responsecache-attribute)

For example using a custom [Default Controller](https://docs.umbraco.com/umbraco-cms/implementation/default-routing/controller-selection#change-the-default-controllers) you can add the ResponseCache attribute to the `Index` method

```csharp
public class DefaultController : RenderController
{
    public DefaultController(ILogger<RenderController> logger, ICompositeViewEngine compositeViewEngine, IUmbracoContextAccessor umbracoContextAccessor) : base(logger, compositeViewEngine, umbracoContextAccessor)
    {
    }

    [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
    public override IActionResult Index()
    {
        return CurrentTemplate(new ContentModel(CurrentPage));
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.umbraco.com/umbraco-cms/reference/response-caching.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
