2 // System.Web.Caching.OutputCacheModule
5 // Jackson Harper (jackson@ximian.com)
7 // (C) 2003 Novell, Inc (http://www.novell.com)
12 using System.Web.Util;
13 using System.Collections;
15 namespace System.Web.Caching {
17 internal sealed class OutputCacheModule : IHttpModule {
19 private CacheItemRemovedCallback response_removed;
21 public OutputCacheModule ()
25 public void Dispose ()
29 public void Init (HttpApplication app)
31 app.AddOnResolveRequestCacheAsync (
32 new BeginEventHandler (OnBeginRequestCache),
33 new EndEventHandler (OnEndRequestCache));
35 app.AddOnUpdateRequestCacheAsync (
36 new BeginEventHandler (OnBeginUpdateCache),
37 new EndEventHandler (OnEndUpdateCache));
39 response_removed = new CacheItemRemovedCallback (OnRawResponseRemoved);
42 IAsyncResult OnBeginRequestCache (object o, EventArgs args, AsyncCallback cb, object data)
44 HttpApplication app = (HttpApplication) o;
45 HttpContext context = app.Context;
47 string vary_key = context.Request.FilePath;
48 CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
55 key = varyby.CreateKey (vary_key, context);
56 c = context.Cache [key] as CachedRawResponse;
60 context.Response.ClearContent ();
61 context.Response.BinaryWrite (c.GetData (), 0, c.ContentLength);
63 context.Response.ClearHeaders ();
64 c.DateHeader.Value = TimeUtil.ToUtcTimeString (DateTime.Now);
65 context.Response.SetCachedHeaders (c.Headers);
67 context.Response.StatusCode = c.StatusCode;
68 context.Response.StatusDescription = c.StatusDescription;
70 app.CompleteRequest ();
71 } else if (c != null) {
72 context.Cache.Remove (key);
76 HttpAsyncResult result = new HttpAsyncResult (cb,this);
77 result.Complete (true, o, null);
82 void OnEndRequestCache (IAsyncResult result)
86 IAsyncResult OnBeginUpdateCache (object o, EventArgs args, AsyncCallback cb, object data)
88 HttpApplication app = (HttpApplication) o;
89 HttpContext context = app.Context;
90 HttpAsyncResult result;
92 if (context.Response.IsCached && context.Response.StatusCode == 200 &&
93 !context.Trace.IsEnabled)
94 DoCacheInsert (context);
96 result = new HttpAsyncResult (cb, this);
97 result.Complete (true, o, null);
101 void OnEndUpdateCache (IAsyncResult result)
105 private void DoCacheInsert (HttpContext context)
107 string vary_key = context.Request.FilePath;
109 CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
110 CachedRawResponse prev = null;
113 if (varyby == null) {
114 string path = context.Request.MapPath (vary_key);
115 string [] files = new string [] { path };
116 string [] keys = new string [0];
117 varyby = new CachedVaryBy (context.Response.Cache, vary_key);
118 context.Cache.InsertPrivate (vary_key, varyby,
119 new CacheDependency (files, keys),
120 Cache.NoAbsoluteExpiration,
121 Cache.NoSlidingExpiration,
122 CacheItemPriority.Normal, null);
126 key = varyby.CreateKey (vary_key, context);
129 prev = context.Cache [key] as CachedRawResponse;
132 CachedRawResponse c = context.Response.GetCachedResponse ();
133 string [] files = new string [] { };
134 string [] keys = new string [] { vary_key };
135 bool sliding = context.Response.Cache.Sliding;
137 context.Cache.InsertPrivate (key, c, new CacheDependency (files, keys),
138 (sliding ? Cache.NoAbsoluteExpiration :
139 context.Response.Cache.Expires),
140 (sliding ? TimeSpan.FromSeconds (
141 context.Response.Cache.Duration) :
142 Cache.NoSlidingExpiration),
143 CacheItemPriority.Normal, response_removed);
145 varyby.ItemList.Add (key);
149 private void OnRawResponseRemoved (string key, object value, CacheItemRemovedReason reason)
151 CachedRawResponse c = (CachedRawResponse) value;
153 c.VaryBy.ItemList.Remove (key);
154 if (c.VaryBy.ItemList.Count != 0)
157 Cache cache = HttpRuntime.Cache;
158 cache.Remove (c.VaryBy.Key);