ASP.NET MVC
caching
attribute
prevent caching
web development

Prevent Caching in ASP.NET MVC for specific actions using an attribute

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Some ASP.NET MVC actions should never be cached by the browser or intermediary proxies. Examples include account pages, dashboards with sensitive data, and actions that reflect rapidly changing server state. The cleanest way to enforce that per action is a custom attribute that sets the appropriate HTTP cache headers in one reusable place.

Why Response Headers Matter

Preventing caching is fundamentally an HTTP concern. Browsers and proxies decide whether to reuse a response by looking at headers such as Cache-Control, Pragma, and Expires.

If you only avoid server-side output caching but forget the response headers, a browser may still keep stale or sensitive content around longer than intended.

Create a Reusable NoCacheAttribute

In classic ASP.NET MVC, an action filter is a good place to centralize the no-cache policy.

csharp
1using System;
2using System.Web;
3using System.Web.Mvc;
4
5public class NoCacheAttribute : ActionFilterAttribute
6{
7    public override void OnResultExecuting(ResultExecutingContext filterContext)
8    {
9        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
10        cache.SetCacheability(HttpCacheability.NoCache);
11        cache.SetNoStore();
12        cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
13        cache.SetExpires(DateTime.UtcNow.AddDays(-1));
14        filterContext.HttpContext.Response.AppendHeader("Pragma", "no-cache");
15
16        base.OnResultExecuting(filterContext);
17    }
18}

This keeps the behavior reusable and easy to audit.

Apply It Only Where Needed

Once the attribute exists, decorate the actions that should never be cached.

csharp
1public class AccountController : Controller
2{
3    [NoCache]
4    public ActionResult Profile()
5    {
6        return View();
7    }
8
9    [NoCache]
10    public ActionResult Billing()
11    {
12        return View();
13    }
14}

That is much cleaner than repeating header logic in every controller action.

Compare with OutputCache

Older MVC code often uses OutputCache to control caching. For a strict no-cache policy, you will sometimes see:

csharp
1[OutputCache(Duration = 0, VaryByParam = "*", NoStore = true)]
2public ActionResult Dashboard()
3{
4    return View();
5}

This can help, but a custom attribute is often clearer when your goal is specifically "do not allow caching". It also gives you one place to add or adjust headers later.

Test the Result in the Browser and Network Tools

Do not assume the attribute works just because the action compiles. Verify the actual response headers in browser developer tools or an HTTP client.

You want to see headers consistent with a no-cache or no-store policy. That is the real proof that clients will receive the intended behavior.

This is especially important when reverse proxies, CDNs, or custom middleware are in the request path. A controller-level attribute can be correct while a downstream layer still rewrites or appends caching headers.

Know the Limits

No-cache headers tell compliant clients and proxies not to reuse the response without revalidation. They are not a substitute for authentication, authorization, or transport security. Sensitive actions still need proper access control.

Also remember that back-button behavior and browser history can feel cache-like even when response caching is disabled. Users sometimes describe that as "the page was cached", when the browser is actually re-rendering from history mechanisms.

That distinction matters during debugging. A developer may think the attribute failed when the real issue is browser history behavior rather than HTTP response reuse.

Common Pitfalls

  • Confusing server-side output caching with browser-side HTTP caching.
  • Repeating header-setting code in many actions instead of using one attribute.
  • Assuming Duration = 0 alone is enough for every client and proxy.
  • Forgetting to verify the actual response headers in network tools.
  • Using no-cache headers as if they replace authentication or authorization.

Summary

  • Preventing caching in MVC actions is mainly about sending the right HTTP headers.
  • A custom NoCacheAttribute is a clean reusable way to enforce that policy.
  • Apply the attribute only to actions that truly need fresh or sensitive responses.
  • 'OutputCache can help, but a dedicated attribute is often clearer for no-cache intent.'
  • Always verify the resulting headers instead of assuming the policy is active.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.