Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Post-cache substitution with Page.Render overriding

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 ?

like image 615
Benjamin Simon Avatar asked Jul 07 '11 20:07

Benjamin Simon


1 Answers

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

like image 188
TheCodeKing Avatar answered Sep 22 '22 07:09

TheCodeKing