There are two attributes that can be placed on an MVC Controller class improve the performance of all the methods in the class:

SessionState - By setting to readonly, methods in the controller can be called and executed in parallel by concurrent AJAX requests. However, they won't be able to make any changes to the Session[] object.

OutputCache - The responses to the class' methods will be cached for up to the specified duration. The VaryByParam value ensures that both the url and query parameters will be used to uniquely identify a request/response in the cache. The VaryByCustom value uses a method in MvcApplication to ensure that the cache is cleared when the session id changes after the user logs out and back in.

See Also:


[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
[OutputCache(NoStore=false, Duration=180, VaryByParam="*", VaryByCustom="SessionID", Location=OutputCacheLocation.Server)]
public class FeaturedSpecialsController : Controller
{
...
}

Here is the implementation of the VaryByCustom method in the AB_MvcApplication class. It supports "SessionID" as the VaryByCustom value, or a special case value of "_ExpBarSearchPopulated" that's used in the Accelerator Line-of-Business application. Any other values are passed to the base HttpApplication class.


/// <summary>
/// Used for OutputCacheAttribute on controller classes or action methods
/// </summary>
///<param name="context">An <see cref="T:System.Web.HttpContext"></see> object that contains information about the current Web request.
///<param name="custom">The custom string that specifies which cached response is used to respond to the current request.
/// <returns>If the value of the <paramref name="custom"></paramref> parameter is "browser", the browser's <see cref="P:System.Web.Configuration.HttpCapabilitiesBase.Type"></see>; otherwise, null.</returns>
/// <remarks><example>
/// <code>
/// [OutputCache(NoStore=false, Duration=180, VaryByParam="*", VaryByCustom="SessionID", Location=OutputCacheLocation.Server)]
/// </code>
/// </example>
/// When this attribute is applied to a controller class or an 
/// individual action method, the response to the method(s) will be 
/// cached for up to the specified duration. The VaryByParam value 
/// ensures that both the url and query parameters will be used 
/// to uniquely identify a request/response in the cache.
/// The VaryByCustom value "SessionID" is applied by this method
/// to ensure that the cache is cleared when the session id changes 
/// after the user logs out and back in.
/// See Also:
/// http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/improving-performance-with-output-caching-cs
/// http://stackoverflow.com/questions/2289941/outputcache-controller-attribute-vary-by-user-role-is-this-possible-in-net-mvc</remarks>
public override string GetVaryByCustomString(HttpContext context, string custom)
{
    if (custom.ToLower().Equals("sessionid"))
    {
        return GetVaryBySessionString(context);
    }
    else if (custom.ToLower().Equals("_expbarsearchpopulated"))
    {
        // For the ExpBarSearch form in the navigator, vary by sessionid to make sure
        // each user gets their own cache, and also by module number and any form fields
        // that are currently cached for the module.

        var modulenum = context.Request["modulenum"];  // From MainController.Index()
        var cacheString = AB_BaseController.am_GetExpBarCustomCacheString(modulenum, context.Session);
        return GetVaryBySessionString(context) + ";" + modulenum + ";" + cacheString;
     }

    return base.GetVaryByCustomString(context, custom);
}

/// <summary>
/// Gets the vary by session string.
/// </summary>
///<param name="context">The context.
/// <returns>System.String.</returns>
protected string GetVaryBySessionString(HttpContext context)
{
    // The combination of the ASP.NET session id and the A4DN
    // session token should be unique per-user and per-login.
    var aspSessionID = context.Request.Cookies["ASP.NET_SessionId"];
    var aspxAuth = context.Request.Cookies[".ASPXAUTH"];
    var a4dnSession = context.Request.Cookies["session"];

    if (aspSessionID != null || aspxAuth != null || a4dnSession != null)
    {
        return (aspSessionID == null ? "" : aspSessionID.Value)
             + (aspxAuth == null ? "" : aspxAuth.Value)
             + (a4dnSession == null ? "" : a4dnSession.Value);
    }
    else
    {
        return "";
    }
}