Fix JavaScript Error in Web Forms Spot the Culprit
Hi, I’m the developer who had to chase down this bug for our latest Web Forms project. Below is the exact path I took from seeing the red error line in IE to pushing a cleaner, user-friendly page into production. I’m sharing every step so the next person (maybe future-me) can fix it in minutes instead of hours.
Error Show:
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['ctl01'];
if (!theForm) {
theForm = document.ctl01;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
Asp.Net/HTML:
<asp:ScriptManager ID="manager" runat="server" ></asp:ScriptManager>
<asp:UpdatePanel ID="platformOutputTypes" runat="server" UpdateMode="Always" >
<ContentTemplate >
<p>
<label>Platform</label>
<asp:DropDownList ID="platform" AutoPostBack="true" runat="server" onselectedindexchanged="PlatformSelectedIndexChanged" ></asp:DropDownList>
</p>
<asp:CheckBoxList TextAlign="Left" ID="reportOutputTypes" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
I’m also using jQuery on the page.
The Code That Explode
I started with a bare bones test page so I could reproduce the problem without the noise of our full master page. Paste this into a brand-new Web Forms site and pick a value in the drop-down you’ll slam straight into theForm.submit();.
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>UpdatePanel test</title>
</head>
<body>
<form id="ctl01" runat="server">
<asp:ScriptManager ID="manager" runat="server" />
<asp:UpdatePanel ID="platformOutputTypes" runat="server" UpdateMode="Always">
<ContentTemplate>
<p>
<label>Platform </label>
<asp:DropDownList
ID="platform"
AutoPostBack="true"
OnSelectedIndexChanged="PlatformSelectedIndexChanged"
runat="server">
</asp:DropDownList>
</p>
<asp:CheckBoxList ID="reportOutputTypes" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
And here’s the little script ASP.NET pushes into the page submit() is where IE trips:
<script type="text/javascript">
var theForm = document.forms['ctl01'];
if (!theForm) { theForm = document.ctl01; }
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit(); <!-- boom -->
}
}
</script>
Why IE Screams “Member not found”
- Straight fact:
theFormis the real<form>. - JavaScript expects
theForm.submitto be a function. - Ancient IE has a quirk any control called
submitinside that form hides the real function. - So when the script calls
submit(), IE finds an<input>element instead of the built-in method and raises Member not found.
Sneaky Ways The Name Slips in
| Culprit | What it looks like in HTML |
|---|---|
| A later button | <input type="button" id="submit" …> |
| A jQuery plug-in | <input type="hidden" name="submit" …> |
| A poorly-named server control | <asp:Button ID="submit" …> |
My Quick Rescue Checklist
- View the generated HTML (F12 ➜ Elements ➜ search
submit). - Rename every
id/namethat collides—submit➜btnSubmit,reset➜btnReset, etc. - Re-load, smile, zero errors.
Tip: In ASP.NET 4+ set ClientIDMode="Static" and take full control of client IDs.
The Cleaned Up
I rewired the markup so no control shadows a form method and split the logic into tidy pieces.
<asp:ScriptManager runat="server" />
<asp:UpdatePanel ID="upMain" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<!-- platform selector -->
<asp:DropDownList
ID="ddlPlatform"
runat="server"
AutoPostBack="true"
OnSelectedIndexChanged="PlatformChanged">
</asp:DropDownList>
<!-- a real button, safely named -->
<asp:Button ID="btnGo" runat="server"
Text="Refresh" CssClass="btn"
OnClick="BtnGo_Click" />
<!-- outputs that depend on the platform -->
<asp:CheckBoxList ID="cblOutputs" runat="server" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlPlatform"
EventName="SelectedIndexChanged" />
<asp:AsyncPostBackTrigger ControlID="btnGo"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
Code-behind (C#):
Protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ddlPlatform.DataSource = GetPlatforms();
ddlPlatform.DataBind();
}
}
protected void PlatformChanged(object sender, EventArgs e) => ReloadOutputs();
protected void BtnGo_Click(object sender, EventArgs e) => ReloadOutputs();
private void ReloadOutputs()
{
cblOutputs.DataSource = GetOutputs(ddlPlatform.SelectedValue);
cblOutputs.DataBind();
}
Result: the page posts back smoothly, no JavaScript crash, and our QA team finally closed the ticket.
Little UX Booster
All front-end only drop each snippet in Site.js and register it with ScriptManager.
Loading Spinner During async
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(() => $('#spinner').show());
Sys.WebForms.PageRequestManager.getInstance().add_endRequest (() => $('#spinner').hide());
<div id="spinner" style="display:none">Loading…</div>
Remember The Last Chosen Platform
$(function () {
const key = 'lastPlatform';
const $ddl = $('#<%= ddlPlatform.ClientID %>');
$ddl.val(localStorage.getItem(key) || $ddl.val());
$ddl.change(() => localStorage.setItem(key, $ddl.val()));
});
Instant Client Side Filter for The Check Box List
$(function () {
const $list = $('#<%= cblOutputs.ClientID %>');
const $search = $('<input type="text" placeholder="Filter…">').insertBefore($list);
$search.on('input', function () {
const q = this.value.toLowerCase();
$list.find('input[type=checkbox]').each(function () {
const $item = $(this).parent();
$item.toggle($item.text().toLowerCase().includes(q));
});
});
});
Final Thought
That’s the one-line lesson this bug hammered into my brain. The fix was nothing more than a rename, yet it burned a chunk of my afternoon because I chased the Update Panel, jQuery, even the network tab before I opened the raw HTML.