Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net Core 2.0 - ResponseCaching Middleware - Not Caching on Server

I want to use server-side response caching (output cache) with asp.net core 2.0 and found out about Response Caching Middleware and wanted to give it a try with a brand new asp.core mvc project.

Here is the description from the link above which makes me think this could be used like output cache.

The middleware determines when responses are cacheable, stores responses, and serves responses from cache.

Here is how my startup.cs looks like.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCaching();
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseResponseCaching();

        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

and here is the HomeController.cs

[ResponseCache(Duration = 60)]
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        return View();
    }

    public IActionResult Contact()
    {
        ViewData["Message"] = "Your contact page.";

        return View();
    }

    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}

there is also a timestamp at the bottom of _Layout.cshtml file so i can tell when the page is rendered, like below.

<p>&copy; 2018 - ResponseCachingMiddleware - @DateTime.UtcNow</p>

Cache-Control headers seem to be fine, this is what I get in headers when I load the page but time stamp keeps getting updated on every refresh every second.

Cache-Control:public,max-age=60

What I'm understanding from MS documentations is Response Caching Middleware is the server-side caching mechanism that takes care of caching the response while Response Caching seems to be just a filter to manipulate response headers for caching.

Can't tell if there is something wrong with my understanding or code and I wanna complain that I'm feeling this way too often since I started prototyping with ASP.Net Core. Maybe you could also suggest better resources as a side topic.

I've checked out this post before ASP.NET Core 2.0 - Http Response Caching Middleware - Nothing cached

Also checked this out but it seems like the only difference is I'm using mvc. https://github.com/aspnet/ResponseCaching/blob/dev/samples/ResponseCachingSample/Startup.cs

Thanks

Edit: I'm seeing the message below in the output window, cannot find anything about it on google except the few places I already checked for response caching middleware.

Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware:Information: The response could not be cached for this request.

Note: I wish I could create #response-caching-middleware tag. Not sure #responsecache is relevant.

like image 427
Engin Avatar asked Jan 12 '18 19:01

Engin


People also ask

What is caching in middleware?

The middleware determines when responses are cacheable, stores responses, and serves responses from cache. For an introduction to HTTP caching and the [ResponseCache] attribute, see Response Caching. The Response caching middleware: Enables caching server responses based on HTTP cache headers.

How use Redis cache in ASP.NET Core?

You can configure an Azure Redis Cache for an Azure-hosted ASP.NET Core app, and use an Azure Redis Cache for local development. An app configures the cache implementation using a RedisCache instance (AddStackExchangeRedisCache). Create an Azure Cache for Redis. Copy the Primary connection string (StackExchange.

What is response caching in .NET Core?

Response caching reduces the number of requests a client or proxy makes to a web server. Response caching also reduces the amount of work the web server performs to generate a response. Response caching is controlled by headers that specify how you want client, proxy, and middleware to cache responses.


1 Answers

I had the same issue, I was about to pull my hairs over it, I'd set app.UseResponseCaching(); as well as services.AddResponseCaching(); and add ResponseCache on top of my action exactly like what was told in Microsoft official Docs, despite the the cache-controll header was set correctly on response returning from server but still nothing cached at server-side.

After couple of hours of sweating on this issue I figured out where the problem arises and why nothing cached at server.

Browsers by default set cache-controll value to max-age=0 for the request (if the request is not caused by back or forward) even though you set cache-controller correctly in your response by adding ResponseCache attribute on top of you action (or controller) since the cache-controller sent by request is set to max-age=0, the server is unable to cache response, I think this must be added to list of Response Caching limitation as well

Anyway you can override browser default behavior by adding few line of code right before calling app.UseResponseCaching(); on the other hand you need to add a custom middle-ware to modify request cache-control header value before calling app.UseResponseCaching();.

See code below, worked for me hope work for you too

 app.Use(async (ctx, next) =>
        {
            ctx.Request.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
            {
                Public = true,
                MaxAge = TimeSpan.FromSeconds(60)
            };
            await next();
        }
            );
        app.UseResponseCaching();

for ensuring that ResponseCaching works as expected you can also use postman but you must set 'Send no-cache Header' to off in the setting, see image below

enter image description here

like image 182
Code_Worm Avatar answered Oct 13 '22 00:10

Code_Worm