javascriptasp.netwebforms

Strange behavior of OnClientClick in ASP.NET webForm


I'm dealing with a large ASP.NET project (Web From, Framework 4.6).

The issue is when user click on a button , button should show as disabled immediately and after a lengthily calculation is done but should show enabled.

I was able to recreate the issue with a very sample code:

aspx code:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication2.WebForm1"  %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Button Task Example</title>
   
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Button ID="Button1" runat="server" Text="Click Me" OnClick="Button1_Click" 
               OnClientClick="disableButton(this);"/>
            <br />
            <asp:Label ID="Label1" runat="server" Text=""></asp:Label>
        </div>
       
    </form>

     <script type="text/javascript">
         function disableButton(button) {
             button.disabled = true;
             return true;
         }
     </script>
   
</body>
</html>

C# Code:

using System.Threading;

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Button1.Enabled = true;
        }

        protected  void Button1_Click(object sender, EventArgs e)
        {
            Thread.Sleep(30000);
           
            Button1.Enabled = true;
            Button1.Text = "Done!";
        }
    }
}

So with this code, as soon I click on the button, button gets disabled, but Button1_Click method never run.

If I remove OnClientClick="disableButton(this);" then Button1_Click runs. Seem OnClientClick="disableButton(this);somehow blocks server side events.

My guess is this behavior is per design. If client side code disable a button, then server side event handler won't get fired.

Update: OK I was wrong, per documentation if after JavaScript code disables the button, returns true then server side click event should run.


Solution

  • If OnClientClick is set then the server-side OnClick only runs if OnClientClick returns true.

    For that to happen you would need to add return as in OnClientClick="return disableButton(this);".

    However... it turns out that in order to do the "OnClick", WebForms adds another handler somewhere - possibly onMouseUp - that doesn't run if the button is disabled before it is that handler's turn.

    A fix for that is to slightly delay to disableButton call:

    OnClientClick="setTimeout(() => disableButton(this), 0); return true"/>
    

    This will run disableButton as soon as the browser is done with whatever is in the click handlers themselves.