Output caching in SharePoint is a powerful method to increase the performance of a site. But out of the box there are only very limited ways to fine tune the caching.

Using the Cache profiles it is only possible to control the caching based on query string parameters, http headers and permissions of the current user. But it is not possible to create a separate cached copy of a page for each individual users.

Caching per user is for sure not something you would like to implement on every page of your site. But often there are certain pages which should be rendered differently for different users - either because the users can customize the page to their needs or the page contains information about the user like an address or account details.

SharePoint 2010 allows assigning an individual cache profile to each page layout - which will also allow disabling the caching on pages created based on this page layout. And that's what customers often do if there is a need to show user specific information.

But often a frequently accessed page of a portal contains such information and then it makes sense to enable Caching event on an individual user bases.

MCMS 2002 had a method to achieve this using a VaryByCustom="CMSUser" directive in the page.

To achieve the same in SharePoint 2010 it is necessary to implement a custom VaryByCustomHandler:

using System;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.ApplicationRuntime;

namespace StefanG.SharePointExtensions
{
    public class VaryByUserApplication : SPHttpApplication, IVaryByCustomHandler
    {
        private const string VaryByUserString = "VaryByUser";

        public override void Init()
        {
            base.Init();

            // register our own VaryByCustomStringHandler
            this.RegisterGetVaryByCustomStringHandler
                  ((Microsoft.SharePoint.ApplicationRuntime.IVaryByCustomHandler)this);
        }

        public string GetVaryByCustomString
                   (HttpApplication app, HttpContext context, string custom)
        {
            // This code handles custom vary parameters specified in the cache profile
            string[] strings = custom.Split(';');

            // verify if our parameter is configured
            foreach (string str in strings)
            {
                // if yes, lets return a custom variation string which contains the ID of the user
                if (str == VaryByUserString)
                {
                    return SPContext.Current.Web.CurrentUser.ID.ToString();
                }
            }

            // if our parameter has not been provided just return an empty string.
            return String.Empty;
        }
    }
}

The code above implements a custom applicaton derived from SPHttpApplication which implements the IVaryByCustomHandler interface.  

When the application is initialized it registers a custom handler which parses the VaryByCustom string for our new keyword "VaryByUser" which can be configured in SharePoint using the Cache Profile properties:

 

To register our custom application we need copy the dll into the Global Assembly Cache and then reference it in the Global.asax as follows:  

<%@ Assembly Name="Microsoft.SharePoint"%>
<%@ Assembly Name="VaryBy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e721828a41c0721d"%>
<%@ Application Language="C#" Inherits="StefanG.SharePointExtensions.VaryByUserApplication" %>

The PublicKeyToken and the Assembly Name needs to be adjusted based on your specific assembly.

To assign an individual cache profile to a page layout, please follow the instructions here:

More details on how to create custom caching parameters can be found here:

The Source Code above can also be downloaded from here: