// // System.Web.HttpCachePolicy // // Authors: // Patrik Torstensson (Patrik.Torstensson@labs2.com) // Tim Coleman (tim@timcoleman.com) // Gonzalo Paniagua Javier (gonzalo@ximian.com) // using System; using System.Collections; using System.Text; using System.Web.UI; using System.Web.Util; namespace System.Web { class CacheabilityUpdatedEventArgs : EventArgs { public readonly HttpCacheability Cacheability; public CacheabilityUpdatedEventArgs (HttpCacheability cacheability) { Cacheability = cacheability; } } internal delegate void CacheabilityUpdatedCallback (object sender, CacheabilityUpdatedEventArgs args); public sealed class HttpCachePolicy { internal HttpCachePolicy () { } #region Fields HttpCacheVaryByHeaders varyByHeaders = new HttpCacheVaryByHeaders (); HttpCacheVaryByParams varyByParams = new HttpCacheVaryByParams (); ArrayList validationCallbacks; StringBuilder cacheExtension; HttpCacheability cacheability; string etag; bool etagFromFileDependencies; bool haveExpireDate; DateTime expireDate; bool haveLastModified; DateTime lastModified; bool lastModifiedFromFileDependencies; bool noServerCaching; bool noStore; bool noTransforms; HttpCacheRevalidation revalidation; bool slidingSpiration; bool validUntilExpires; string varyByCustom; bool haveMaxAge; TimeSpan maxAge; bool haveProxyMaxAge; TimeSpan proxyMaxAge; ArrayList fields; bool slidingExpiration; int duration; #endregion internal event CacheabilityUpdatedCallback CacheabilityUpdated; #region Properties public HttpCacheVaryByHeaders VaryByHeaders { get { return varyByHeaders; } } public HttpCacheVaryByParams VaryByParams { get { return varyByParams; } } internal DateTime Expires { get { return expireDate; } } internal int Duration { get { return duration; } set { duration = value; } } internal bool Sliding { get { return slidingExpiration; } } #endregion // Properties #region Methods public void AddValidationCallback (HttpCacheValidateHandler handler, object data) { if (handler == null) throw new ArgumentNullException ("handler"); if (validationCallbacks == null) validationCallbacks = new ArrayList (); validationCallbacks.Add (new Pair (handler, data)); } public void AppendCacheExtension (string extension) { if (extension == null) throw new ArgumentNullException ("extension"); if (cacheExtension == null) cacheExtension = new StringBuilder (extension); else cacheExtension.Append (", " + extension); } public void SetCacheability (HttpCacheability cacheability) { if (cacheability < HttpCacheability.NoCache || cacheability > HttpCacheability.Public) throw new ArgumentOutOfRangeException ("cacheability"); if (this.cacheability > 0 && cacheability > this.cacheability) return; this.cacheability = cacheability; if (CacheabilityUpdated != null) CacheabilityUpdated (this, new CacheabilityUpdatedEventArgs (cacheability)); } public void SetCacheability (HttpCacheability cacheability, string field) { if (field == null) throw new ArgumentNullException ("field"); if (cacheability != HttpCacheability.Private && cacheability != HttpCacheability.NoCache) throw new ArgumentException ("Must be NoCache or Private", "cacheability"); if (fields == null) fields = new ArrayList (); fields.Add (new Pair (cacheability, field)); } public void SetETag (string etag) { if (etag == null) throw new ArgumentNullException ("etag"); if (this.etag != null) throw new InvalidOperationException ("The ETag header has already been set"); if (etagFromFileDependencies) throw new InvalidOperationException ("SetEtagFromFileDependencies has already been called"); this.etag = etag; } public void SetETagFromFileDependencies () { if (this.etag != null) throw new InvalidOperationException ("The ETag header has already been set"); etagFromFileDependencies = true; } public void SetExpires (DateTime date) { if (haveExpireDate && date > expireDate) return; haveExpireDate = true; expireDate = date; } public void SetLastModified (DateTime date) { if (date > DateTime.Now) throw new ArgumentOutOfRangeException ("date"); if (haveLastModified && date < lastModified) return; haveLastModified = true; lastModified = date; } public void SetLastModifiedFromFileDependencies () { lastModifiedFromFileDependencies = true; } public void SetMaxAge (TimeSpan date) { if (date < TimeSpan.Zero) throw new ArgumentOutOfRangeException ("date"); if (haveMaxAge && maxAge < date) return; maxAge = date; haveMaxAge = true; } public void SetNoServerCaching () { noServerCaching = true; } public void SetNoStore () { noStore = true; } public void SetNoTransforms () { noTransforms = true; } public void SetProxyMaxAge (TimeSpan delta) { if (delta < TimeSpan.Zero) throw new ArgumentOutOfRangeException ("delta"); if (haveProxyMaxAge && proxyMaxAge < delta) return; proxyMaxAge = delta; } public void SetRevalidation (HttpCacheRevalidation revalidation) { if (revalidation < HttpCacheRevalidation.AllCaches || revalidation > HttpCacheRevalidation.None) throw new ArgumentOutOfRangeException ("revalidation"); if (this.revalidation > revalidation) this.revalidation = revalidation; } public void SetSlidingExpiration (bool slide) { slidingExpiration = slide; } public void SetValidUntilExpires (bool validUntilExpires) { this.validUntilExpires = validUntilExpires; } public void SetVaryByCustom (string custom) { if (custom == null) throw new ArgumentNullException ("custom"); if (varyByCustom != null) throw new InvalidOperationException ("VaryByCustom has already been set."); varyByCustom = custom; } internal string GetVaryByCustom () { return varyByCustom; } [MonoTODO] public void SetAllowResponseInBrowserHistory (bool allow) { throw new NotImplementedException (); } internal void SetHeaders (HttpResponse response, ArrayList headers) { string cc, expires; if (cacheability > HttpCacheability.NoCache) { cc = String.Format ("{0}, max-age={1}", cacheability, (long) maxAge.TotalSeconds); expires = TimeUtil.ToUtcTimeString (expireDate); } else { cc = "no-cache"; response.CacheControl = cc; expires = "-1"; } headers.Add (new HttpResponseHeader ("Cache-Control", cc)); headers.Add (new HttpResponseHeader ("Expires", expires)); if (etag != null) headers.Add (new HttpResponseHeader ("ETag", etag)); if (haveLastModified) headers.Add (new HttpResponseHeader ("Last-Modified", TimeUtil.ToUtcTimeString (lastModified))); if (!varyByParams.IgnoreParams) { HttpResponseHeader vb = varyByParams.GetResponseHeader (); if (vb != null) headers.Add (vb); } } #endregion // Methods } }