using System;
using System.Web;
using System.Web.Configuration;
using System.Web.Mvc;
namespace Website.Filters
{
[Flags]
public enum CacheType
{
ClientSide,
ServerSide
}
public class CacheableAttribute : ActionFilterAttribute
{
private static bool? cachingEnabled;
///
/// Is Caching Enabled in the application configuration?
///
public static bool OutputCachingEnabled
{
get
{
if (!cachingEnabled.HasValue)
{
var outputSettings = (OutputCacheSection)WebConfigurationManager
.GetWebApplicationSection("system.web/caching/outputCache");
cachingEnabled = (outputSettings == null || outputSettings.EnableOutputCache);
}
return cachingEnabled.Value;
}
}
///
/// Is caching enabled?
/// Use this to override the default and always explicitly
/// enabled or disable caching on this particular Action.
/// (Default = value of system.web/caching/outputCache/EnableOutputCache configuration setting)
///
public bool Enabled { get; set; }
#region Supported Types (SupportedTypes, ClientCachingEnabled, and ServerCachingEnabled properties)
///
/// The types of caching supported on this Action.
/// Defaults to both server- and client-side caching.
///
public CacheType SupportedTypes { get; set; }
protected bool ClientCachingEnabled
{
get { return Enabled && IsCacheTypeEnabled(CacheType.ClientSide); }
}
protected bool ServerCachingEnabled
{
get { return Enabled && IsCacheTypeEnabled(CacheType.ServerSide); }
}
private bool IsCacheTypeEnabled(CacheType type)
{
// Perform a bitwise operation to see whether or not this type is enabled.
return (SupportedTypes & type) == type;
}
#endregion
///
/// Maximum time (in minutes) for this content
/// to remain cached on the client.
///
public double ClientMaxAge { get; set; }
public CacheableAttribute()
{
// Set the Enabled default to that of the Output Caching
Enabled = OutputCachingEnabled;
// Default to both client- & server-side caching.
SupportedTypes = CacheType.ServerSide & CacheType.ClientSide;
// Default to 3 days (60 mins * 24 hrs * 3 days)
ClientMaxAge = 60 * 24 * 3;
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
// If client-side caching isn't enabled, just return now.
if (!ClientCachingEnabled)
return;
// Otherwise, configure the caching headers.
var cache = filterContext.HttpContext.Response.Cache;
var duration = TimeSpan.FromMinutes(ClientMaxAge);
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(duration));
cache.SetMaxAge(duration);
cache.AppendCacheExtension("must-revalidate");
}
}
}