Using VaryByCustom With OutputCache in ASP.NET MVC To Support Caching For Logged-in Users
Jun 9, 2010 By Karsten JanuszewskiSeveral pages of an upcoming Mix Online lab are fundamentally static, except for a single hyperlink that toggles depending on whether a user is logged in or not. To optimize the site, I wanted to use caching on these static pages. But by adding the OutputCache attribute to these pages, a user could end up getting a cached page with the wrong logged-in hyperlink: users who weren’t logged in would see a page that stated they were logged in—or vice versa.
The solution? Using the VaryByCustom parameter of the OutputCache attribute, so that both a logged-in and a logged-out version of the page are cached and served up appropriately. Here’s how to do it:
First, add a method to the global.asax.cs file, which overrides the VaryByCustom call:
public override string GetVaryByCustomString(HttpContext context,
string arg)
{
if (arg == "IsLoggedIn")
{
if (context.Request.Cookies["anon"] != null)
{
if (context.Request.Cookies["anon"].Value == "false")
{
return "auth";
}
else
{
return "anon";
}
}
else
{
return "anon";
}
}
else
{
return base.GetVaryByCustomString(context, arg);
}
}
Then, decorate the controller actions with the OutputCache attribute:
[OutputCache(CacheProfile = "StaticPage")]
public ActionResult Index()
{
return View();
}
When using caching, I like to keep all the profile information in web.config. This lets me update things without recompiling. Here’s what the cache profile looks like:
<caching> <outputcachesettings> <outputcacheprofiles> <clear /> <!-- 24 hours--> <add varybycustom="IsLoggedIn" varybyparam="*" duration="86400" name="StaticPage" /> </outputcacheprofiles> </outputcachesettings> </caching>
Notice how the varybyparam attribute is set with an asterisk, and the varybycustom attribute has the string IsLoggedIn,the term that gets passed to the VaryByCustom override.
I’m using my own kind of authentication (more on that in a future post),so checking a cookie is sufficient. If you’re using ASP.NET Membership Authentication, you can use slightly different logic such that pages are cached based on the username itself. See this post for a sample—and tip o’ the hat to Chris Mullins for setting me on this path!



Follow the Conversation
5 comments so far. You should leave one, too.
Karsten, thanks for posting such a valuable article
Why not : [Authorize,OutputCache(VaryByHeader="Cookie",Duration=30)] ?
Karsten, thank you for the tip. I just have one question: is it possible to cache page only for not logged in users? I do have some info on pages for those logged in that I don't want to be cached as it can be changed frequently while all info for not logged in can be cached safely.
Hi Mike -- Unfortunately, I'm not really sure. You might try posting this to an ASP.NET forum.
This really is genuinely excellent news. Thank you for sharing it with us!