in

ASP.NET Weblogs

Drew's Blog

The Joys of Technology Explored

ASP.NET PartialCachingAttribute Problem

Preface: I've seen this discussed before, but haven't really found a solution through all my searching, so I'm hoping I'm just missing something.

As you may or may not know, if you're creating a server control you can enable that control to be automagically cached by the ASP.NET output caching services by applying a PartialCachingAttribute to it. Once the control is rendered it's output is cached according to the number of seconds specified by the attribute. The control will never be instantiated or called in the rendering tree again until the cache expires. Cool right? Well, it is, but the magic happening here is unfortunately not very flexible.

When a server control is added to the page's control tree, it is checked for the PartialCachingAttribute. If the attribute is present, the control is wrapped with a PartialCachingControl instance. This PartialCachingControl class acts as a proxy for the actual server control in the page's control tree. In the OnRender implementation of PartialCachingControl is where all the magic happens (actually there's a BasePartialCachingControl class under there, but for simplicity we'll ignore that). The magic is the logic I discussed in the previous paragraph:

First, the cache is checked. If the cached output is [still] available (i.e. it hasn't expired) then it is just blasted out to the Response stream and that's that. If the cached output is not available, an instance of the actual server control is created. Next, there's a really nasty internal only hack done to switch the TextWriter for the current HttpResponse object so that it's an in-memory StringWriter instead (check out HttpResponse::SwitchWriter with ILDasm). This is done so that the PartialCachingControl can take the buffer and cache it using the caching architecture before it's blasted out to the HttpResponse's stream. Once this bit of trickery is completed, the original TextWriter is replaced on the HttpResponse and normal processing continues.

Ok, so with that dissection/explanation out of the way, the real problem is this. What if my cached server control needs to perform non-render time logic? In my specific case, I always need to emit a to a stylesheet. Well, it looks like I'm SOL and can no longer use the partial caching architecture anymore.

Has anyone solved this problem elegantly? My only option now seems to be to stop using the partial caching feature and basically do all the cache work manually within my server control's Render override. :\ I'd need to sniff the HtmlTextWriter type being used for the scope of the request, instantiate my own version of it with all the proper settings over my own StreamWriter, use that to write all my content, then get the text from the underlying StreamWriter, manually stuff it in the cache and then manually blast it out to the actual response stream.

I can't understand why PartialCachingControl doesn't at least instantiate your server control and, at the bare minimum, pass on the OnInit phase of control activation. :(

Published Nov 25 2003, 07:40 PM by drub0y
Filed under:

Comments

 

Oddur Magnusson said:

I manually override the render method to provide my own caching. Mainly because I can't set the value of the attribute dynamicly
November 25, 2003 8:42 PM
 

Andrew said:

I had some controls where I used a code only control and an ascx.

The code only control would check the cache in Render based on it's properties and then LoadControl the ascx if I needed to generate some html.
November 25, 2003 9:24 PM
 

Ian Griffiths said:

Can't you make the cached control the child of an uncached control? The uncached control wouldn't contribute anything to the output - it just wraps the cached control. That way you can put your behaviour in the uncached control, but still get caching for its child.
November 26, 2003 8:07 AM

Leave a Comment

(required)  
(optional)
(required)  
Add