Post-cache substitution with Page.Render overriding
Asked Answered
P

1

12

The context

I have an Asp .Net web application with some pages that inherit from a base class "BasePage". This BasePage class inherits from System.Web.ui.Page and I've overriden the Render method so that I can intercept the HTML stream before it is sent to the client browser.

Here is the code of my Render method :

protected override void Render(HtmlTextWriter writer){

    MemoryStream memoryStream = new MemoryStream();

    try
    {
        using (StreamWriter streamWriter = new StreamWriter(memoryStream))
        {
            var textWriter = new HtmlTextWriter(streamWriter);
            base.Render(textWriter);
            textWriter.Flush();
            memoryStream.Position = 0;

            using (StreamReader reader = new StreamReader(memoryStream))
            {
                string finalHtml = reader.ReadToEnd();

                // Processing filters
                finalHtml = FilterManager.ProcessFilters(finalHtml);

                // Writing output to client
                writer.Write(finalHtml);
                reader.Close();
            }
        }
    }
    catch(ObjectDisposedException)
    {

    }
    finally
    {
        memoryStream.Dispose();
    }
}

So far, so good. It works. The reason I didn't use the response filtering feature is that I knew it wouldn't be compatible with Post-cache substitution

Yes. I do also want to use outputcache substitution. For testing purposes, I've added a small asp .net control in my aspx page :

<asp:Substitution runat="server" id="UnCachedArea" methodname="GetFreshDateTime" />

with the corresponding static method int the code behind :

protected static string GetFreshDateTime(HttpContext context)
{
    return DateTime.Now.ToString();
} 

... and... it works !! I've both my filters working only on the first page load and the substitution occuring for every refresh I make on the page.

The problem

The substitution string is inserted at the wrong place, just after the opening body tag whereas my susbtitution control is located at the very bottom of the page, in the footer.

Any clues ?

Purport answered 7/7, 2011 at 20:12 Comment(3)
We have the same problem here... I started a bounty. I hope a good soul will help us.Penurious
forums.asp.net/p/1049086/1478039.aspxPenurious
If you take out the custom render it works right?Tavie
T
1

It's because you have modified the render to flatten the output into a single string, and this is what gets cached.

Normally with donut caching the cached render output leaves dynamic region markers in the cached response for the substitution blocks that are populated post-cache. In writing a string directly into the HtmlTextWriter you have broken the ability for ASP.NET to do this. It's the same reason why you cannot use ResponseFilters.

Scott Gu has at good article on the subject

Tavie answered 27/8, 2011 at 13:4 Comment(3)
So if I understand, the answer is : it's not possible to use outputcaching with substitution AND post render filtering (regardless the method we use), and there aren't any possible tricks to manage to do it because it's inherent to asp .net outputcache conception ?Purport
Well if you write your content as a string into the HtmlTextWriter then no. There might be other ways depending on what you doing with the filters. Would control adapters help? Or more granular filtering within specific controls outside of the main content render?Tavie
Alright. I've kind of given up working on this problem anyway regarding my current priorities and the little benefits I could gain finding a way to solve it... Thx for all your precisionsPurport

© 2022 - 2024 — McMap. All rights reserved.