Notes on the invalid Javascript in __doPostBack (Asp.Net 1.1)

G

Granger Godbold

This is in regards to the long-standing bug with the colons in the form-id. I'm not satisfied with
the main workaround that's been circulating:
http://www.asp.net/Forums/ShowPost.aspx?PostID=191953
And I'm rather annoyed that Microsoft won't put the fix out for anonymous download (However, one can
get to it from links in the above forum).
http://support.microsoft.com/default.aspx?scid=kb;en-us;818058

Anyhow, after playing around, I found out some interesting stuff:
HtmlForm.OnRenderChildren() is where the magic happens. It calls the (internal) method
Page.OnFormRender() passing it the HtmlForm.UniqueID (instead of the ClientID as it ought).

The OnFormRender method first renders hidden fields (Page.RenderHiddenFields), then renders the
ViewState field. Next it renders the __doPostBack script as necessary (Page.RenderPostBackScript),
and finally renders any registered script blocks (Page.RenderPostBackScript). After OnFormRender,
IIRC, next came Control.OnRenderChildren(), and last was Page.OnFormPostRender().

Specifically, here's the basic execution flow I saw (minus the "...", which means I didn't care to
write it down, and I'm too tired to go back and do it again):

- HtmlForm.OnRenderChildren(...)
- Page.OnFormRender(HtmlTextWriter writer, string formUniqueID)
- Page.RenderHiddenFields(...)
- Page.CreateLosFormatter(...)
- HtmlTextWriter.WriteLine()
- HtmlTextWriter.Write(string s) <3 times in a row>
- LosFormatter.SerializeInternal(...)
- HtmlTextWriter.WriteLine()
- Page.RenderPostBackScript(HtmlTextWriter writer, string formUniqueID)
- Page.RenderScriptBlocks(HtmlTextWriter writer, IDictionary scriptBlocks)
- Control.OnRenderChildren() <IIRC>
- Page.OnFormPostRender() <IIRC>

Lastly, there's an internal Page.RegisterPostBackScript() method which sets a private bool; this
variable is used to determine if __doPostBack should be rendered. I found that if you set
AutoPostBack=true in a DropDownList, Page.RegisterPostBackScript will be called in its OnPreRender
method. I was unable to find a way to determine in my own code (at the Page-level) if that method
had been called; I don't presenly know how to determine if __doPostBack will be rendered.


Given the above, I think there's an equally unsightly, but much faster workaround if one doesn't
want to apply that hotfix. You must derive your own HtmlForm object like below. Basically, it's a
simple concept: When the buggy code that grabs the form's ID runs, it uses UniqueID instead of
ClientID. So, if we just "fix" UniqueID for that one call, we're good-to-go. I isolated the
important calls to HtmlForm.RenderChildren; UniqueID gets called twice from there. I know the first
call is the important one, but I don't know for certain about the second (it's really late, and I'm
tired).

public class FixedHtmlForm : System.Web.UI.HtmlControls.HtmlForm
{
protected bool _fixDoPostBack;
protected override void RenderChildren(HtmlTextWriter writer)
{
_fixDoPostBack = true;
base.RenderChildren(writer);
_fixDoPostBack = false; // assure it gets reset even though I think this isn't needed
}

public override string UniqueID
{
get
{
if (_fixDoPostBack)
{
_fixDoPostBack = false; // stop it after the first call
return base.UniqueID.Replace(":", "_"); // this is what ClientID does
}
else
return base.UniqueID;
}
}
}


Hope this is helpful/interesting.
Granger

(Note: There aren't actually underscores in my address)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top