【问题标题】:ASP.Net double-click problemASP.Net双击问题
【发布时间】:2009-09-30 13:54:11
【问题描述】:

我的 ASP.net 页面有一点问题。如果用户双击“提交”按钮,它将两次写入数据库(即对图像按钮执行两次“onclick”方法)

我怎样才能使如果用户点击图像按钮,只有图像按钮被禁用?

我试过了:

<asp:ImageButton 
     runat="server" 
     ID="VerifyStepContinue" 
     ImageUrl=image src 
     ToolTip="Go" 
     TabIndex="98" 
     CausesValidation="true" 
     OnClick="methodName" 
     OnClientClick="this.disabled = true;" />

但是这个 OnClientClick 属性完全阻止了页面的提交!有什么帮助吗?

抱歉,是的,我确实有验证控件...因此出现了棘手的问题。


目前仍在处理这个问题:

ASP 代码:

 <asp:TextBox ID="hidToken" runat="server" Visible="False" Enabled="False"></asp:TextBox>
 ...
 <asp:ImageButton runat="server" ID="InputStepContinue" Name="InputStepContinue" ImageUrl="imagesrc" ToolTip="Go" TabIndex="98" CausesValidation="true" OnClick="SubmitMethod" OnClientClick="document.getElementById('InputStepContinue').style.visibility='hidden';" />

C#代码:

         private Random
    random = new Random();


    protected void Page_Load(object sender, EventArgs e)
    {
        //Use a Token to make sure it has only been clicked once.
        if (Page.IsPostBack)
        {
            if (double.Parse(hidToken.Text) == ((double)Session["NextToken"]))
            {
                InputMethod();
            }
            else
            {
                // double click
            }
        }

        double next = random.Next();

        hidToken.Text = next + "";
        Session["NextToken"] = next;

实际上……这几乎可行。双击问题几乎已解决(耶!)但图像仍然没有隐藏。

【问题讨论】:

    标签: c# asp.net javascript onclick double-click


    【解决方案1】:

    一般方法是双重的。

    服务器端

    1. 加载页面时,生成一个令牌(使用System.Random),将其保存在会话中,并将其写入隐藏的表单字段
    2. 提交时,检查隐藏的表单字段是否等于会话变量(再次设置之前)
    3. 工作

    客户端

    与您所拥有的类似,但可能只是隐藏按钮,并将其替换为一些文本,例如“提交”。

    客户端需要注意的重要一点是,用户可以通过点击“escape”来取消帖子,所以你应该考虑在这里做什么(取决于他们有多远,令牌不会被使用,因此您需要将按钮从禁用/隐藏状态恢复)。

    完整示例如下:

    C#(包括代码以查看它的实际效果):

    <html>
    <head runat="server">
        <title>double-click test</title>
        <script language="c#" runat="server">
        private Random
            random = new Random();
    
        private static int
            TEST = 0;
    
        public void Page_Load (object sender, EventArgs ea)
        {
            SetToken();
        }
    
        private void btnTest_Click (object sender, EventArgs ea)
        {
            if( IsTokenValid() ){
                DoWork();
            } else {
                // double click
                ltlResult.Text = "double click!";
            }
        }
    
        private bool IsTokenValid ()
        {
            bool result = double.Parse(hidToken.Value) == ((double) Session["NextToken"]);
            SetToken();
            return result;
        }
    
        private void SetToken ()
        {
            double next = random.Next();
    
            hidToken.Value       = next + "";
            Session["NextToken"] = next;
        }
    
    
        private void DoWork ()
        {
            TEST++;
            ltlResult.Text = "DoWork(): " + TEST + ".";
        }
        </script>
    </head>
    <body>
        <script language="javascript">
            var last = null;
            function f (obj)
            {
                obj.src = "http://www.gravatar.com/avatar/4659883ec420f39723c3df6ed99971b9?s=32&d=identicon&r=PG";
                // Note: Disabling it here produced strange results. More investigation required.
                last = obj;
                setTimeout("reset()", 1 * 1000);
                return true;
            }
    
            function reset ()
            {
                last.src = "http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG";
                last.disabled = "false";
            }
        </script>
        <form id="form1" runat="server">
            <asp:HiddenField runat="server" ID="hidToken" />
            <asp:ImageButton runat="server" ID="btnTest"
                OnClientClick="return f(this);"
                ImageUrl="http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG" OnClick="btnTest_Click" />
            <pre>Result: <asp:Literal runat="server" ID="ltlResult" /></pre>
        </form>
    </body>
    </html>
    

    【讨论】:

    • 在 ASP.Net 中没有内置的、简单的方法来处理这个问题吗?
    • MusiGenesis:我只知道我现在有 7777 个代表,而且我再也不想多一点了 (ffonline.com/media/guides/ff7/ffvii_faq_lucky7.txt)(也没有)。
    • @silky:ASP.Net 用一根柔软的吸管吸住 Cheez Whiz 的另一个原因。叹。他们本可以将 ASP.Net 设计为一个明智的 Web 开发平台,而不是试图让开发人员假装他们仍在编写 Windows 应用程序,但是不...
    • @silky:一个小问题——你不应该在没有锁定的情况下在.aspx 页面中使用像这样的静态Random
    • 好的。出于不好意思弄错了,我写了一个完整的例子。我认为它应该可以工作(设置禁用的javascript可能略有错误)。请测试并告诉我。出于某种原因,我不能休息,直到它起作用......:P
    【解决方案2】:

    如果您在页面上进行了验证,则禁用按钮客户端会有点棘手。如果验证失败,您不想禁用该按钮。这是一个添加客户端事件处理程序的 sn-p:

    private void BuildClickOnceButton(WebControl ctl)
    
    {
    
    System.Text.StringBuilder sbValid = new System.Text.StringBuilder();
    
    sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");
    
    sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");
    
    sbValid.Append(ctl.ClientID + ".value = 'Please wait...';");
    
    sbValid.Append(ctl.ClientID + ".disabled = true;");
    
    // GetPostBackEventReference obtains a reference to a client-side script 
    // function that causes the server to post back to the page.
    
    sbValid.Append(ClientScript.GetPostBackEventReference(ctl, ""));
    
    sbValid.Append(";");
    
    ctl.Attributes.Add("onclick", sbValid.ToString());
    
    }
    

    请参阅此asp.net thread 了解更多信息。

    更新:上面的代码将用于在后面的代码中添加 OnClientClick 处理程序。您也可以像这样在您的 aspx 标记中编写 javascript:

    <script type="text/javascript">
    function disableButton(button)
    {
        // if there are client validators on the page
        if (typeof(Page_ClientValidate) == 'function') 
        {
            // if validation failed return false
            // this will cancel the click event
            if (Page_ClientValidate() == false) 
            { 
                return false; 
            }
        }
    
        // change the button text (does not apply to an ImageButton)
        //button.value = "Please wait ...";
        // disable the button
        button.disabled = true;
    
        // fire postback
        __doPostBack(button.id, '');
    }
    </script>
    
    <asp:ImageButton runat="server" ID="VerifyStepContinue" ImageUrl="button.png" 
        ToolTip="Go" TabIndex="98" CausesValidation="true" OnClick="methodName" 
        OnClientClick="return disableButton(this);" />
    

    【讨论】:

    • 这看起来像我所追求的,但不太确定如何使用它......我需要为我的变量更改哪些变量?我看过论坛帖子,似乎是对的,但我不能完全理解。
    • 再次,不起作用...当我尝试使用它时,它仍然会禁用所有内容。
    • 您是否收到 javascript 错误?脚本是否不仅禁用了图像按钮?
    • 禁用的不仅仅是图像按钮,是的。
    • 这很漂亮。恕我直言,它应该是处理“防止表单重复提交”的 ASP .NET 官方方式。做得很好。
    【解决方案3】:

    我已经通过在点击服务器之前在客户端点击上设置一个隐藏字段来解决这个问题。

    然后在服务器中检查隐藏字段,如果该值是例如“FALSE”,这可能意味着我可以或不能执行该操作。

    【讨论】:

      【解决方案4】:

      与 Silky 的客户端响应类似,我通常会制作两个看起来相似的按钮,只是第二个按钮被禁用和隐藏。普通按钮的 OnClientClick 交换两个按钮的显示样式,使普通按钮隐藏,禁用按钮显示。

      【讨论】:

        【解决方案5】:

        双击功能是一种服务器端实现,用于防止处理相同的请求,可以通过 JavaScript 在客户端实现。该功能的主要目的是防止两次处理相同的请求。服务器端实现通过识别重复的请求来做到这一点;但是,理想的解决方案是防止这种情况发生在客户端。

        在发送给客户端允许他们提交请求的 HTML 内容中,可以使用一个小的验证 JavaScript 来检查请求是否已经提交,如果是,则阻止在线购物者再次提交请求。此 JavaScript 验证函数将检查全局标志以查看请求是否已提交,如果已提交;不重新提交请求。如果服务器禁用了双击功能,强烈建议 JSP 和 HTML 页面实现此 JavaScript 防护。

        以下示例通过使用表单对象的 onSubmit() 操作防止表单多次提交:

        ...
        <script>
        var requestSubmitted = false;
               function submitRequest() {
                      if (!requestSubmitted ) {
                             requestSubmitted  = true;
                             return true;
                      }
                      return false;
               }
        </script>
        ...
        
               <FORM method="POST" action="Logon" onSubmit="javascript:submitRequest()">
                      ......
               </FORM> 
        

        【讨论】:

        • onsubmit 代码应如下所示:onsubmit="return submitRequest()"。
        【解决方案6】:

        对于那些只想快速修复的人,只需将其隐藏并显示另一个没有事件的按钮

        <asp:Button ID="RedeemSubmitButton" runat="server" Text="Submit to Redeem" OnClick="RedeemSubmitButton_Click" OnClientClick="hideit();" />
        <asp:Button ID="RedeemSubmitButtonDisabled" style="display:none;" runat="server" Text="please wait" OnClientClick="javascript:alert('please wait, processing');"  />
        <script>
         function hideit() {
        
        
        
                var btn = $get('<%= this.RedeemSubmitButton.ClientID %>');
                var btn2 = $get('<%= this.RedeemSubmitButtonDisabled.ClientID %>');
                if (btn != null)
                {
        
                    btn.style.display = 'none';
                    btn2.style.display = 'block'
                }
         }
            </script>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-14
          相关资源
          最近更新 更多