You are reading a MIX Online Opinion. In which we speak our minds. Karsten Januszewski Meet Karsten Arrow

Lab Notes

5Comment Retweet

Using VaryByCustom With OutputCache in ASP.NET MVC To Support Caching For Logged-in Users

Jun 9, 2010 By Karsten Januszewski

Several 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.

Muhammad Adeel Zahid said on Jul 26, 2011

Karsten, thanks for posting such a valuable article

hummm said on Jul 28, 2011

Why not : [Authorize,OutputCache(VaryByHeader="Cookie",Duration=30)] ?

Mike said on Nov 15, 2011

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.

Karsten Januszewski said on Nov 15, 2011

Hi Mike -- Unfortunately, I'm not really sure. You might try posting this to an ASP.NET forum.

Burberry Online Shop said on Apr 26, 2012

This really is genuinely excellent news. Thank you for sharing it with us!