Friday, November 13

Disable button after sumit

Originally, an asp.net page has a button
< id="btnCreate" text="Create" runat="server" onclick="btnCreate_Click">
to fire the btnCreate_Click event.

The event takes a few seconds to perform its job, so the client complained that sometimes she clicked the button twice, and 2 items are created. "It would be better if the button is disabled after clicked".

Sure, we programmers can do that.

Adding "btnCreate.Enabled=flase" into the btnCreate_Click event can not do the trick, because this property will not be set until all the jobs in this event are performed and the new page is return to client's browser. A javascript applet must be activated to disable this button, when the form is being submitted into server and firing up the event.

How about adding javascript directly in this button like:
< id="btnCreate" text="Create" runat="server" onclick="btnCreate_Click" onclientclick= "
"this.value='Please wait...'; this.disabled = true; " + ClientScript.GetPostBackEventReference(btnCreate, string.Empty) + ";");
It worked perfectly for IE and Firefox 3.0, until the Firefox 3.5 was release in July 2009.

At this point, the HTML source of rendered page is like:
< input type="submit" name="ctl00$MainPageContent$btnCreate" value="Create" onclick="this.value='Please wait...'; this.disabled = true; ;__doPostBack('ctl00$MainPageContent$btnCreate','')" id="ctl00_MainPageContent_btnCreate" />

After July, I got reports saying duplicate items were generated at the same second. I collected all the Addons from the clients and literally added them into my Firefox (it was 3.0 because I didn't notice the version is playing an important role) one by one. After adding one Addon, I restarted the Firefox and visited the same page to click the button. After adding all 15 Addons, there is no duplicate items from my Firefox.
Finally the Firefox version number is located as the source of this issue. Paros and Firebug is deployed to catch the traffic. Only one post action from Firefox 3.5 fires up the btnCreate_Click event twice. That is so weird. Is that a bug in Firefox 3.5, or in Asp.NET?

I don't see any Googled page mentioned this problem, and there was no solution existed, until this blog is written.

Solution: Step 1, modify the button as
< id="btnCreate" text="Create" runat="server" onclick="btnCreate_Click" style="color: rgb(255, 0, 0);" usesubmitbehavior="false">
Step 2, modify the code in Page_Load as
btnCreate.Attributes.Add("onclick",
"this.value='Please wait...'; this.disabled = true; ");
After that, the HTML source of rendered page is almost the same:
< input type="button" name="ctl00$MainPageContent$btnCreate" value="Create" onclick="this.value='Please wait...'; this.disabled = true; ;__doPostBack('ctl00$MainPageContent$btnCreate','')" id="ctl00_MainPageContent_btnCreate" />



Analysis:
The description of UseSubmitBehavior from Microsoft
is very confusing:
Use the UseSubmitBehavior property to specify whether a Button control uses the client browser's submit mechanism or the ASP.NET postback mechanism. By default the value of this property is true, causing the Button control to use the browser's submit mechanism. If you specify false, the ASP.NET page framework adds client-side script to the page to post the form to the server.
Originally, the
UseSubmitBehavior is "true" by default, the HTML source is
< input type="submit" name="ctl00$MainPageContent$btnCreate" value="Create" />

If you have been reading the HTML source carefully, you can notice that the < input > of first HTML source is a "Submit", and the second < input > is a "Button". The UseSubmitBehavior decides the difference. My first solution added a javascript __doPostBack into a "Submit", and the Firefox 3.5 decides to submit the form twice, I guess.

The combination of local javascript and serverside script can be very fragile, so extra attention must be taken to deal with it.