@@ -34,36 +34,54 @@ public DonutOutputCacheAttribute()
3434 Location = ( OutputCacheLocation ) ( - 1 ) ;
3535 }
3636
37+ /// <summary>
38+ /// Gets or sets the cache duration, in seconds.
39+ /// </summary>
3740 public int Duration
3841 {
3942 get ;
4043 set ;
4144 }
4245
46+ /// <summary>
47+ /// Gets or sets the vary-by-param value.
48+ /// </summary>
4349 public string VaryByParam
4450 {
4551 get ;
4652 set ;
4753 }
4854
55+ /// <summary>
56+ /// Gets or sets the vary-by-custom value.
57+ /// </summary>
4958 public string VaryByCustom
5059 {
5160 get ;
5261 set ;
5362 }
5463
64+ /// <summary>
65+ /// Gets or sets the cache profile name.
66+ /// </summary>
5567 public string CacheProfile
5668 {
5769 get ;
5870 set ;
5971 }
6072
73+ /// <summary>
74+ /// Gets or sets the location.
75+ /// </summary>
6176 public OutputCacheLocation Location
6277 {
6378 get ;
6479 set ;
6580 }
6681
82+ /// <summary>
83+ /// Gets or sets a value that indicates whether to store the cache.
84+ /// </summary>
6785 public bool NoStore
6886 {
6987 get
@@ -108,18 +126,26 @@ public void OnException(ExceptionContext filterContext)
108126 }
109127 }
110128
129+ /// <summary>
130+ /// Called before an action method executes.
131+ /// </summary>
132+ /// <param name="filterContext">The filter context.</param>
111133 public override void OnActionExecuting ( ActionExecutingContext filterContext )
112134 {
113135 _cacheSettings = BuildCacheSettings ( ) ;
114136
115137 var cacheKey = _keyGenerator . GenerateKey ( filterContext , _cacheSettings ) ;
116138
139+ // Are we actually storing data on the server side ?
117140 if ( _cacheSettings . IsServerCachingEnabled )
118141 {
119142 var cachedItem = _outputCacheManager . GetItem ( cacheKey ) ;
120143
144+ // We have a cached version on the server side
121145 if ( cachedItem != null )
122146 {
147+ // We inject the previous result into the MVC pipeline
148+ // The MVC action won't execute as we injected the previous cached result.
123149 filterContext . Result = new ContentResult
124150 {
125151 Content = _donutHoleFiller . ReplaceDonutHoleContent ( cachedItem . Content , filterContext ) ,
@@ -128,28 +154,35 @@ public override void OnActionExecuting(ActionExecutingContext filterContext)
128154 }
129155 }
130156
157+ // Did we already injected something ?
131158 if ( filterContext . Result != null )
132159 {
133- return ;
160+ return ; // No need to continue
134161 }
135162
163+ // We are hooking into the pipeline to replace the response Output writer
164+ // by something we own and later eventually gonna cache
136165 var cachingWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
137166
138167 var originalWriter = filterContext . HttpContext . Response . Output ;
139168
140169 filterContext . HttpContext . Response . Output = cachingWriter ;
141170
171+ // Will be called back by OnResultExecuted -> ExecuteCallback
142172 filterContext . HttpContext . Items [ cacheKey ] = new Action < bool > ( hasErrors =>
143173 {
174+ // Removing this executing action from the context
144175 filterContext . HttpContext . Items . Remove ( cacheKey ) ;
145176
177+ // We restore the original writer for response
146178 filterContext . HttpContext . Response . Output = originalWriter ;
147179
148180 if ( hasErrors )
149181 {
150- return ;
182+ return ; // Something went wrong, we are not going to cache something bad
151183 }
152184
185+ // Now we use owned caching writer to actually store data
153186 var cacheItem = new CacheItem
154187 {
155188 Content = cachingWriter . ToString ( ) ,
@@ -165,15 +198,22 @@ public override void OnActionExecuting(ActionExecutingContext filterContext)
165198 } ) ;
166199 }
167200
201+ /// <summary>
202+ /// Called after an action result executes.
203+ /// </summary>
204+ /// <param name="filterContext">The filter context.</param>
168205 public override void OnResultExecuted ( ResultExecutedContext filterContext )
169206 {
170207 if ( _cacheSettings == null )
171208 {
172209 return ;
173210 }
174211
212+ // See OnActionExecuting
175213 ExecuteCallback ( filterContext , filterContext . Exception != null ) ;
176214
215+ // If we are in the context of a child action, the main action is responsible for setting
216+ // the right HTTP Cache headers for the final response.
177217 if ( ! filterContext . IsChildAction )
178218 {
179219 _cacheHeadersHelper . SetCacheHeaders ( filterContext . HttpContext . Response , _cacheSettings ) ;
@@ -228,7 +268,7 @@ protected CacheSettings BuildCacheSettings()
228268 return cacheSettings ;
229269 }
230270
231- protected void ExecuteCallback ( ControllerContext context , bool hasErrors )
271+ private void ExecuteCallback ( ControllerContext context , bool hasErrors )
232272 {
233273 var cacheKey = _keyGenerator . GenerateKey ( context , _cacheSettings ) ;
234274
0 commit comments